Coding style overhaul for Python files (PEP8 conformant). Removed buggy csstidy pytho...
authorŁukasz Rekucki <lrekucki@gmail.com>
Sun, 11 Apr 2010 14:51:14 +0000 (16:51 +0200)
committerŁukasz Rekucki <lrekucki@gmail.com>
Sun, 11 Apr 2010 14:52:33 +0000 (16:52 +0200)
59 files changed:
apps/compress/filter_base.py
apps/compress/filters/csstidy/__init__.py
apps/compress/filters/csstidy_python/__init__.py [deleted file]
apps/compress/filters/csstidy_python/csstidy.py [deleted file]
apps/compress/filters/csstidy_python/data.py [deleted file]
apps/compress/filters/csstidy_python/optimizer.py [deleted file]
apps/compress/filters/csstidy_python/output.py [deleted file]
apps/compress/filters/csstidy_python/tools.py [deleted file]
apps/compress/filters/jsmin/__init__.py
apps/compress/filters/jsmin/jsmin.py
apps/compress/filters/yui/__init__.py
apps/compress/management/commands/synccompress.py
apps/compress/templatetags/compressed.py
apps/compress/utils.py
apps/compress/versioning/base.py
apps/compress/versioning/hash/__init__.py
apps/compress/versioning/mtime/__init__.py
apps/django_cas/backends.py
apps/django_cas/decorators.py
apps/django_cas/middleware.py
apps/django_cas/models.py
apps/django_cas/views.py
apps/filebrowser/base.py
apps/filebrowser/decorators.py
apps/filebrowser/fb_settings.py
apps/filebrowser/fields.py
apps/filebrowser/forms.py
apps/filebrowser/functions.py
apps/filebrowser/models.py
apps/filebrowser/templatetags/fb_tags.py
apps/filebrowser/templatetags/fb_versions.py
apps/filebrowser/urls.py
apps/filebrowser/views.py
apps/toolbar/admin.py
apps/toolbar/management/__init__.py
apps/toolbar/management/commands/fixbuttons.py
apps/toolbar/migrations/0001_initial.py
apps/toolbar/migrations/0002_auto__del_field_button_key_mod__chg_field_button_key.py
apps/toolbar/migrations/0003_button_key_rename_to_accesskey.py
apps/toolbar/models.py
apps/toolbar/templatetags/toolbar_tags.py
apps/wiki/forms.py
apps/wiki/helpers.py
apps/wiki/models.py
apps/wiki/nice_diff.py
apps/wiki/tests.py
apps/wiki/urls.py
apps/wiki/views.py
fabfile.py
lib/test_vstorage.py
lib/vstorage.py
lib/wlapi.py
platforma/context_processors.py
platforma/manage.py
platforma/settings.py
platforma/urls.py
scripts/crop.py
scripts/imgconv.py
setup.py

index 9b98531..3ce364f 100644 (file)
@@ -4,11 +4,13 @@ class FilterBase:
 
     def filter_css(self, css):
         raise NotImplementedError
+
     def filter_js(self, js):
         raise NotImplementedError
-        
+
+
 class FilterError(Exception):
     """
     This exception is raised when a filter fails
     """
-    pass
\ No newline at end of file
+    pass
index d40e8ee..de5dd09 100644 (file)
@@ -11,23 +11,25 @@ ARGUMENTS = getattr(settings, 'CSSTIDY_ARGUMENTS', '--template=highest')
 
 warnings.simplefilter('ignore', RuntimeWarning)
 
+
 class CSSTidyFilter(FilterBase):
+
     def filter_css(self, css):
         tmp_file = tempfile.NamedTemporaryFile(mode='w+b')
         tmp_file.write(css)
         tmp_file.flush()
 
         output_file = tempfile.NamedTemporaryFile(mode='w+b')
-        
+
         command = '%s %s %s %s' % (BINARY, tmp_file.name, ARGUMENTS, output_file.name)
-        
+
         command_output = os.popen(command).read()
-        
+
         filtered_css = output_file.read()
         output_file.close()
         tmp_file.close()
-        
+
         if self.verbose:
             print command_output
-        
+
         return filtered_css
diff --git a/apps/compress/filters/csstidy_python/__init__.py b/apps/compress/filters/csstidy_python/__init__.py
deleted file mode 100644 (file)
index 7d581ed..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.conf import settings
-
-from compress.filter_base import FilterBase
-from compress.filters.csstidy_python.csstidy import CSSTidy
-
-COMPRESS_CSSTIDY_SETTINGS = getattr(settings, 'COMPRESS_CSSTIDY_SETTINGS', {})
-
-class CSSTidyFilter(FilterBase):
-    def filter_css(self, css):
-        tidy = CSSTidy()
-        
-        for k, v in COMPRESS_CSSTIDY_SETTINGS.items():
-            tidy.setSetting(k, v)
-
-        tidy.parse(css)
-
-        r = tidy.Output('string')
-        
-        return r
diff --git a/apps/compress/filters/csstidy_python/csstidy.py b/apps/compress/filters/csstidy_python/csstidy.py
deleted file mode 100644 (file)
index 6ae8dc7..0000000
+++ /dev/null
@@ -1,636 +0,0 @@
-# CSSTidy - CSS Parse
-#
-# CSS Parser class
-#
-# This file is part of CSSTidy.
-#
-# CSSTidy is free software you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation either version 2 of the License, or
-# (at your option) any later version.
-#
-# CSSTidy is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with CSSTidy if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-#
-# @license http://opensource.org/licenses/gpl-license.php GNU Public License
-# @package csstidy
-# @author Dj Gilcrease (digitalxero at gmail dot com) 2005-2006
-
-import re
-
-from optimizer import CSSOptimizer
-from output import CSSPrinter
-import data
-from tools import SortedDict
-
-class CSSTidy(object):
-    #Saves the parsed CSS
-    _css = ""
-    _raw_css = SortedDict()
-    _optimized_css = SortedDict()
-
-    #List of Tokens
-    _tokens = []
-
-    #Printer class
-    _output = None
-
-    #Optimiser class
-    _optimizer = None
-
-    #Saves the CSS charset (@charset)
-    _charset = ''
-
-    #Saves all @import URLs
-    _import = []
-
-    #Saves the namespace
-    _namespace = ''
-
-    #Contains the version of csstidy
-    _version = '1.3'
-
-    #Stores the settings
-    _settings = {}
-
-    # Saves the parser-status.
-    #
-    # Possible values:
-    # - is = in selector
-    # - ip = in property
-    # - iv = in value
-    # - instr = in string (started at " or ' or ( )
-    # - ic = in comment (ignore everything)
-    # - at = in @-block
-    _status = 'is'
-
-    #Saves the current at rule (@media)
-    _at = ''
-
-    #Saves the current selector
-    _selector = ''
-
-    #Saves the current property
-    _property = ''
-
-    #Saves the position of , in selectors
-    _sel_separate = []
-
-    #Saves the current value
-    _value = ''
-
-    #Saves the current sub-value
-    _sub_value = ''
-
-    #Saves all subvalues for a property.
-    _sub_value_arr = []
-
-    #Saves the char which opened the last string
-    _str_char = ''
-    _cur_string = ''
-
-    #Status from which the parser switched to ic or instr
-    _from = ''
-
-    #Variable needed to manage string-in-strings, for example url("foo.png")
-    _str_in_str = False
-
-    #=True if in invalid at-rule
-    _invalid_at = False
-
-    #=True if something has been added to the current selector
-    _added = False
-
-    #Saves the message log
-    _log = SortedDict()
-
-    #Saves the line number
-    _line = 1
-
-    def __init__(self):
-        self._settings['remove_bslash'] = True
-        self._settings['compress_colors'] = True
-        self._settings['compress_font-weight'] = True
-        self._settings['lowercase_s'] = False
-        self._settings['optimise_shorthands'] = 2
-        self._settings['remove_last_'] = False
-        self._settings['case_properties'] = 1
-        self._settings['sort_properties'] = False
-        self._settings['sort_selectors'] = False
-        self._settings['merge_selectors'] = 2
-        self._settings['discard_invalid_properties'] = False
-        self._settings['css_level'] = 'CSS2.1'
-        self._settings['preserve_css'] = False
-        self._settings['timestamp'] = False
-        self._settings['template'] = 'highest_compression'
-
-        #Maps self._status to methods
-        self.__statusMethod = {'is':self.__parseStatus_is, 'ip': self.__parseStatus_ip, 'iv':self.__parseStatus_iv, 'instr':self.__parseStatus_instr, 'ic':self.__parseStatus_ic, 'at':self.__parseStatus_at}
-
-        self._output = CSSPrinter(self)
-        self._optimizer = CSSOptimizer(self)
-
-    #Public Methods
-    def getSetting(self, setting):
-        return self._settings.get(setting, False)
-
-    #Set the value of a setting.
-    def setSetting(self, setting, value):
-        self._settings[setting] = value
-        return True
-
-    def log(self, message, ttype, line = -1):
-        if line == -1:
-            line = self._line
-
-        line = int(line)
-
-        add = {'m': message, 't': ttype}
-
-        if not self._log.has_key(line):
-            self._log[line] = []
-            self._log[line].append(add)
-        elif add not in self._log[line]:
-            self._log[line].append(add)
-
-
-    #Checks if a character is escaped (and returns True if it is)
-    def escaped(self, string, pos):
-        return not (string[pos-1] != '\\' or self.escaped(string, pos-1))
-
-    #Adds CSS to an existing media/selector
-    def merge_css_blocks(self, media, selector, css_add):
-        for prop, value in css_add.iteritems():
-            self.__css_add_property(media, selector, prop, value, False)
-
-    #Checks if $value is !important.
-    def is_important(self, value):
-        return '!important' in value.lower()
-
-    #Returns a value without !important
-    def gvw_important(self, value):
-        if self.is_important(value):
-            ret = value.strip()
-            ret = ret[0:-9]
-            ret = ret.strip()
-            ret = ret[0:-1]
-            ret = ret.strip()
-            return ret
-
-        return value
-
-    def parse(self, cssString):
-        #Switch from \r\n to \n
-        self._css = cssString.replace("\r\n", "\n") + ' '
-        self._raw_css = {}
-        self._optimized_css = {}
-        self._curComment = ''
-
-        #Start Parsing
-        i = 0
-        while i < len(cssString):
-            if self._css[i] == "\n" or self._css[i] == "\r":
-                self._line += 1
-
-            i += self.__statusMethod[self._status](i)
-
-            i += 1;
-
-        self._optimized_css = self._optimizer.optimize(self._raw_css)
-
-    def parseFile(self, filename):
-        try:
-            f = open(filename, "r")
-            self.parse(f.read())
-        finally:
-            f.close()
-
-    #Private Methods
-    def __parseStatus_is(self, idx):
-        """
-            Parse in Selector
-        """
-        ret = 0
-
-        if self.__is_token(self._css, idx):
-            if self._css[idx] == '/' and self._css[idx+1] == '*' and self._selector.strip() == '':
-                self._status = 'ic'
-                self._from = 'is'
-                return 1
-
-            elif self._css[idx] == '@' and self._selector.strip() == '':
-                #Check for at-rule
-                self._invalid_at = True
-
-                for name, ttype in data.at_rules.iteritems():
-                    if self._css[idx+1:len(name)].lower() == name.lower():
-                        if ttype == 'at':
-                            self._at = '@' + name
-                        else:
-                            self._selector = '@' + name
-
-                        self._status = ttype
-                        self._invalid_at = False
-                        ret += len(name)
-
-                if self._invalid_at:
-                    self._selector = '@'
-                    invalid_at_name = ''
-                    for j in xrange(idx+1, len(self._css)):
-                        if not self._css[j].isalpha():
-                            break;
-
-                        invalid_at_name += self._css[j]
-
-                    self.log('Invalid @-rule: ' + invalid_at_name + ' (removed)', 'Warning')
-
-            elif self._css[idx] == '"' or self._css[idx] == "'":
-                self._cur_string = self._css[idx]
-                self._status = 'instr'
-                self._str_char = self._css[idx]
-                self._from = 'is'
-
-            elif self._invalid_at and self._css[idx] == ';':
-                self._invalid_at = False
-                self._status = 'is'
-
-            elif self._css[idx] == '{':
-                self._status = 'ip'
-                self.__add_token(data.SEL_START, self._selector)
-                self._added = False;
-
-            elif self._css[idx] == '}':
-                self.__add_token(data.AT_END, self._at)
-                self._at = ''
-                self._selector = ''
-                self._sel_separate = []
-
-            elif self._css[idx] == ',':
-                self._selector = self._selector.strip() + ','
-                self._sel_separate.append(len(self._selector))
-
-            elif self._css[idx] == '\\':
-                self._selector += self.__unicode(idx)
-
-            #remove unnecessary universal selector,  FS#147
-            elif not (self._css[idx] == '*' and self._css[idx+1] in ('.', '#', '[', ':')):
-                self._selector += self._css[idx]
-
-        else:
-            lastpos = len(self._selector)-1
-
-            if lastpos == -1 or not ((self._selector[lastpos].isspace() or self.__is_token(self._selector, lastpos) and self._selector[lastpos] == ',') and self._css[idx].isspace()):
-                self._selector += self._css[idx]
-
-        return ret
-
-    def __parseStatus_ip(self, idx):
-        """
-            Parse in property
-        """
-        if self.__is_token(self._css, idx):
-            if (self._css[idx] == ':' or self._css[idx] == '=') and self._property != '':
-                self._status = 'iv'
-
-                if not self.getSetting('discard_invalid_properties') or self.__property_is_valid(self._property):
-                    self.__add_token(data.PROPERTY, self._property)
-
-            elif self._css[idx] == '/' and self._css[idx+1] == '*' and self._property == '':
-                self._status = 'ic'
-                self._from = 'ip'
-                return 1
-
-            elif self._css[idx] == '}':
-                self.__explode_selectors()
-                self._status = 'is'
-                self._invalid_at = False
-                self.__add_token(data.SEL_END, self._selector)
-                self._selector = ''
-                self._property = ''
-
-            elif self._css[idx] == ';':
-                self._property = ''
-
-            elif self._css[idx] == '\\':
-                self._property += self.__unicode(idx)
-
-        elif not self._css[idx].isspace():
-            self._property += self._css[idx]
-
-        return 0
-
-    def __parseStatus_iv(self, idx):
-        """
-            Parse in value
-        """
-        pn = (( self._css[idx] == "\n" or self._css[idx] == "\r") and self.__property_is_next(idx+1) or idx == len(self._css)) #CHECK#
-        if self.__is_token(self._css, idx) or pn:
-            if self._css[idx] == '/' and self._css[idx+1] == '*':
-                self._status = 'ic'
-                self._from = 'iv'
-                return 1
-
-            elif self._css[idx] == '"' or self._css[idx] == "'" or self._css[idx] == '(':
-                self._cur_string = self._css[idx]
-                self._str_char = ')' if self._css[idx] == '(' else self._css[idx]
-                self._status = 'instr'
-                self._from = 'iv'
-
-            elif self._css[idx] == ',':
-                self._sub_value = self._sub_value.strip() + ','
-
-            elif self._css[idx] == '\\':
-                self._sub_value += self.__unicode(idx)
-
-            elif self._css[idx] == ';' or pn:
-                if len(self._selector) > 0 and self._selector[0] == '@' and data.at_rules.has_key(self._selector[1:]) and data.at_rules[self._selector[1:]] == 'iv':
-                    self._sub_value_arr.append(self._sub_value.strip())
-
-                    self._status = 'is'
-
-                    if '@charset' in self._selector:
-                        self._charset = self._sub_value_arr[0]
-
-                    elif '@namespace' in self._selector:
-                        self._namespace = ' '.join(self._sub_value_arr)
-
-                    elif '@import' in self._selector:
-                        self._import.append(' '.join(self._sub_value_arr))
-
-
-                    self._sub_value_arr = []
-                    self._sub_value = ''
-                    self._selector = ''
-                    self._sel_separate = []
-
-                else:
-                    self._status = 'ip'
-
-            elif self._css[idx] != '}':
-                self._sub_value += self._css[idx]
-
-            if (self._css[idx] == '}' or self._css[idx] == ';' or pn) and self._selector != '':
-                if self._at == '':
-                    self._at = data.DEFAULT_AT
-
-                #case settings
-                if self.getSetting('lowercase_s'):
-                    self._selector = self._selector.lower()
-
-                self._property = self._property.lower()
-
-                if self._sub_value != '':
-                    self._sub_value_arr.append(self._sub_value)
-                    self._sub_value = ''
-
-                self._value = ' '.join(self._sub_value_arr)
-
-
-                self._selector = self._selector.strip()
-
-                valid = self.__property_is_valid(self._property)
-
-                if (not self._invalid_at or self.getSetting('preserve_css')) and (not self.getSetting('discard_invalid_properties') or valid):
-                    self.__css_add_property(self._at, self._selector, self._property, self._value)
-                    self.__add_token(data.VALUE, self._value)
-
-                if not valid:
-                    if self.getSetting('discard_invalid_properties'):
-                        self.log('Removed invalid property: ' + self._property, 'Warning')
-
-                    else:
-                        self.log('Invalid property in ' + self.getSetting('css_level').upper() + ': ' + self._property, 'Warning')
-
-                self._property = '';
-                self._sub_value_arr = []
-                self._value = ''
-
-            if self._css[idx] == '}':
-                self.__explode_selectors()
-                self.__add_token(data.SEL_END, self._selector)
-                self._status = 'is'
-                self._invalid_at = False
-                self._selector = ''
-
-        elif not pn:
-            self._sub_value += self._css[idx]
-
-            if self._css[idx].isspace():
-                if self._sub_value != '':
-                    self._sub_value_arr.append(self._sub_value)
-                    self._sub_value = ''
-
-        return 0
-
-    def __parseStatus_instr(self, idx):
-        """
-            Parse in String
-        """
-        if self._str_char == ')' and (self._css[idx] == '"' or self._css[idx] == "'") and not self.escaped(self._css, idx):
-            self._str_in_str = not self._str_in_str
-
-        temp_add = self._css[idx] # ...and no not-escaped backslash at the previous position
-        if (self._css[idx] == "\n" or self._css[idx] == "\r") and not (self._css[idx-1] == '\\' and not self.escaped(self._css, idx-1)):
-            temp_add = "\\A "
-            self.log('Fixed incorrect newline in string', 'Warning')
-
-        if not (self._str_char == ')' and self._css[idx].isspace() and not self._str_in_str):
-            self._cur_string += temp_add
-
-        if self._css[idx] == self._str_char and not self.escaped(self._css, idx) and not self._str_in_str:
-            self._status = self._from
-            regex = re.compile(r'([\s]+)', re.I | re.U | re.S)
-            if regex.match(self._cur_string) is None and self._property != 'content':
-                if self._str_char == '"' or self._str_char == "'":
-                    self._cur_string = self._cur_string[1:-1]
-
-                elif len(self._cur_string) > 3 and (self._cur_string[1] == '"' or self._cur_string[1] == "'"):
-                    self._cur_string = self._cur_string[0] + self._cur_string[2:-2] + self._cur_string[-1]
-
-            if self._from == 'iv':
-                self._sub_value += self._cur_string
-
-            elif self._from == 'is':
-                self._selector += self._cur_string
-
-        return 0
-
-    def __parseStatus_ic(self, idx):
-        """
-            Parse css In Comment
-        """
-        if self._css[idx] == '*' and self._css[idx+1] == '/':
-            self._status = self._from
-            self.__add_token(data.COMMENT, self._curComment)
-            self._curComment = ''
-            return 1
-
-        else:
-            self._curComment += self._css[idx]
-
-        return 0
-
-    def __parseStatus_at(self, idx):
-        """
-            Parse in at-block
-        """
-        if self.__is_token(string, idx):
-            if self._css[idx] == '/' and self._css[idx+1] == '*':
-                self._status = 'ic'
-                self._from = 'at'
-                return 1
-
-            elif self._css[i] == '{':
-                self._status = 'is'
-                self.__add_token(data.AT_START, self._at)
-
-            elif self._css[i] == ',':
-                self._at = self._at.strip() + ','
-
-            elif self._css[i] == '\\':
-                self._at += self.__unicode(i)
-        else:
-            lastpos = len(self._at)-1
-            if not (self._at[lastpos].isspace() or self.__is_token(self._at, lastpos) and self._at[lastpos] == ',') and self._css[i].isspace():
-                self._at += self._css[i]
-
-        return 0
-
-    def __explode_selectors(self):
-        #Explode multiple selectors
-        if self.getSetting('merge_selectors') == 1:
-            new_sels = []
-            lastpos = 0;
-            self._sel_separate.append(len(self._selector))
-
-            for num in xrange(len(self._sel_separate)):
-                pos = self._sel_separate[num]
-                if num == (len(self._sel_separate)): #CHECK#
-                    pos += 1
-
-                new_sels.append(self._selector[lastpos:(pos-lastpos-1)])
-                lastpos = pos
-
-            if len(new_sels) > 1:
-                for selector in new_sels:
-                    self.merge_css_blocks(self._at, selector, self._raw_css[self._at][self._selector])
-
-                del self._raw_css[self._at][self._selector]
-
-        self._sel_separate = []
-
-    #Adds a property with value to the existing CSS code
-    def __css_add_property(self, media, selector, prop, new_val):
-        if self.getSetting('preserve_css') or new_val.strip() == '':
-            return
-
-        if not self._raw_css.has_key(media):
-            self._raw_css[media] = SortedDict()
-
-        if not self._raw_css[media].has_key(selector):
-            self._raw_css[media][selector] = SortedDict()
-
-        self._added = True
-        if self._raw_css[media][selector].has_key(prop):
-            if (self.is_important(self._raw_css[media][selector][prop]) and self.is_important(new_val)) or not self.is_important(self._raw_css[media][selector][prop]):
-                del self._raw_css[media][selector][prop]
-                self._raw_css[media][selector][prop] = new_val.strip()
-
-        else:
-            self._raw_css[media][selector][prop] = new_val.strip()
-
-    #Checks if the next word in a string from pos is a CSS property
-    def __property_is_next(self, pos):
-        istring = self._css[pos: len(self._css)]
-        pos = istring.find(':')
-        if pos == -1:
-            return False;
-
-        istring = istring[:pos].strip().lower()
-        if data.all_properties.has_key(istring):
-            self.log('Added semicolon to the end of declaration', 'Warning')
-            return True
-
-        return False;
-
-    #Checks if a property is valid
-    def __property_is_valid(self, prop):
-        return (data.all_properties.has_key(prop) and data.all_properties[prop].find(self.getSetting('css_level').upper()) != -1)
-
-    #Adds a token to self._tokens
-    def __add_token(self, ttype, cssdata, do=False):
-        if self.getSetting('preserve_css') or do:
-            if ttype == data.COMMENT:
-                token = [ttype, cssdata]
-            else:
-                token = [ttype, cssdata.strip()]
-
-            self._tokens.append(token)
-
-    #Parse unicode notations and find a replacement character
-    def __unicode(self, idx):
-       ##FIX##
-       return ''
-
-    #Starts parsing from URL
-    ##USED?
-    def __parse_from_url(self, url):
-        try:
-            if "http" in url.lower() or "https" in url.lower():
-                f = urllib.urlopen(url)
-            else:
-                f = open(url)
-
-            data = f.read()
-            return self.parse(data)
-        finally:
-            f.close()
-
-    #Checks if there is a token at the current position
-    def __is_token(self, string, idx):
-        return (string[idx] in data.tokens and not self.escaped(string, idx))
-
-
-    #Property Methods
-    def _getOutput(self):
-        self._output.prepare(self._optimized_css)
-        return self._output.render
-
-    def _getLog(self):
-        ret = ""
-        ks = self._log.keys()
-        ks.sort()
-        for line in ks:
-            for msg in self._log[line]:
-                ret += "Type: " + msg['t'] + "\n"
-                ret += "Message: " + msg['m'] + "\n"
-            ret += "\n"
-
-        return ret
-
-    def _getCSS(self):
-        return self._css
-
-
-    #Properties
-    Output = property(_getOutput, None)
-    Log = property(_getLog, None)
-    CSS = property(_getCSS, None)
-
-
-if __name__ == '__main__':
-    import sys
-    tidy = CSSTidy()
-    f = open(sys.argv[1], "r")
-    css = f.read()
-    f.close()
-    tidy.parse(css)
-    tidy.Output('file', filename="Stylesheet.min.css")
-    print tidy.Output()
-    #print tidy._import
\ No newline at end of file
diff --git a/apps/compress/filters/csstidy_python/data.py b/apps/compress/filters/csstidy_python/data.py
deleted file mode 100644 (file)
index bd728cb..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-# Various CSS Data for CSSTidy
-#
-# This file is part of CSSTidy.
-#
-# CSSTidy is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# CSSTidy is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with CSSTidy; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-#
-# @license http://opensource.org/licenses/gpl-license.php GNU Public License
-# @package csstidy
-# @author Florian Schmitz (floele at gmail dot com) 2005
-
-AT_START    = 1
-AT_END      = 2
-SEL_START   = 3
-SEL_END     = 4
-PROPERTY    = 5
-VALUE       = 6
-COMMENT     = 7
-DEFAULT_AT  = 41
-
-# All whitespace allowed in CSS
-#
-# @global array whitespace
-# @version 1.0
-whitespace = frozenset([' ',"\n","\t","\r","\x0B"])
-
-# All CSS tokens used by csstidy
-#
-# @global string tokens
-# @version 1.0
-tokens = '/@}{;:=\'"(,\\!$%&)#+.<>?[]^`|~'
-
-# All CSS units (CSS 3 units included)
-#
-# @see compress_numbers()
-# @global array units
-# @version 1.0
-units = frozenset(['in','cm','mm','pt','pc','px','rem','em','%','ex','gd','vw','vh','vm','deg','grad','rad','ms','s','khz','hz'])
-
-# Available at-rules
-#
-# @global array at_rules
-# @version 1.0
-at_rules = {'page':'is', 'font-face':'is', 'charset':'iv', 'import':'iv', 'namespace':'iv', 'media':'at'}
-
-# Properties that need a value with unit
-#
-# @todo CSS3 properties
-# @see compress_numbers()
-# @global array unit_values
-# @version 1.2
-unit_values = frozenset(['background', 'background-position', 'border', 'border-top', 'border-right', 'border-bottom',
-                                    'border-left', 'border-width', 'border-top-width', 'border-right-width', 'border-left-width',
-                                    'border-bottom-width', 'bottom', 'border-spacing', 'font-size','height', 'left', 'margin', 'margin-top',
-                                    'margin-right', 'margin-bottom', 'margin-left', 'max-height', 'max-width', 'min-height', 'min-width',
-                                    'outline-width', 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left','position',
-                                    'right', 'top', 'text-indent', 'letter-spacing', 'word-spacing', 'width'
-                                    ])
-
-
-# Properties that allow <color> as value
-#
-# @todo CSS3 properties
-# @see compress_numbers()
-# @global array color_values
-# @version 1.0
-color_values = frozenset(['background-color', 'border-color', 'border-top-color', 'border-right-color',
-                                        'border-bottom-color', 'border-left-color', 'color', 'outline-color'])
-
-
-# Default values for the background properties
-#
-# @todo Possibly property names will change during CSS3 development
-# @global array background_prop_default
-# @see dissolve_short_bg()
-# @see merge_bg()
-# @version 1.0
-background_prop_default = {}
-background_prop_default['background-image'] = 'none'
-background_prop_default['background-size'] = 'auto'
-background_prop_default['background-repeat'] = 'repeat'
-background_prop_default['background-position'] = '0 0'
-background_prop_default['background-attachment'] = 'scroll'
-background_prop_default['background-clip'] = 'border'
-background_prop_default['background-origin'] = 'padding'
-background_prop_default['background-color'] = 'transparent'
-
-# A list of non-W3C color names which get replaced by their hex-codes
-#
-# @global array replace_colors
-# @see cut_color()
-# @version 1.0
-replace_colors = {}
-replace_colors['aliceblue'] = '#F0F8FF'
-replace_colors['antiquewhite'] = '#FAEBD7'
-replace_colors['aquamarine'] = '#7FFFD4'
-replace_colors['azure'] = '#F0FFFF'
-replace_colors['beige'] = '#F5F5DC'
-replace_colors['bisque'] = '#FFE4C4'
-replace_colors['blanchedalmond'] = '#FFEBCD'
-replace_colors['blueviolet'] = '#8A2BE2'
-replace_colors['brown'] = '#A52A2A'
-replace_colors['burlywood'] = '#DEB887'
-replace_colors['cadetblue'] = '#5F9EA0'
-replace_colors['chartreuse'] = '#7FFF00'
-replace_colors['chocolate'] = '#D2691E'
-replace_colors['coral'] = '#FF7F50'
-replace_colors['cornflowerblue'] = '#6495ED'
-replace_colors['cornsilk'] = '#FFF8DC'
-replace_colors['crimson'] = '#DC143C'
-replace_colors['cyan'] = '#00FFFF'
-replace_colors['darkblue'] = '#00008B'
-replace_colors['darkcyan'] = '#008B8B'
-replace_colors['darkgoldenrod'] = '#B8860B'
-replace_colors['darkgray'] = '#A9A9A9'
-replace_colors['darkgreen'] = '#006400'
-replace_colors['darkkhaki'] = '#BDB76B'
-replace_colors['darkmagenta'] = '#8B008B'
-replace_colors['darkolivegreen'] = '#556B2F'
-replace_colors['darkorange'] = '#FF8C00'
-replace_colors['darkorchid'] = '#9932CC'
-replace_colors['darkred'] = '#8B0000'
-replace_colors['darksalmon'] = '#E9967A'
-replace_colors['darkseagreen'] = '#8FBC8F'
-replace_colors['darkslateblue'] = '#483D8B'
-replace_colors['darkslategray'] = '#2F4F4F'
-replace_colors['darkturquoise'] = '#00CED1'
-replace_colors['darkviolet'] = '#9400D3'
-replace_colors['deeppink'] = '#FF1493'
-replace_colors['deepskyblue'] = '#00BFFF'
-replace_colors['dimgray'] = '#696969'
-replace_colors['dodgerblue'] = '#1E90FF'
-replace_colors['feldspar'] = '#D19275'
-replace_colors['firebrick'] = '#B22222'
-replace_colors['floralwhite'] = '#FFFAF0'
-replace_colors['forestgreen'] = '#228B22'
-replace_colors['gainsboro'] = '#DCDCDC'
-replace_colors['ghostwhite'] = '#F8F8FF'
-replace_colors['gold'] = '#FFD700'
-replace_colors['goldenrod'] = '#DAA520'
-replace_colors['greenyellow'] = '#ADFF2F'
-replace_colors['honeydew'] = '#F0FFF0'
-replace_colors['hotpink'] = '#FF69B4'
-replace_colors['indianred'] = '#CD5C5C'
-replace_colors['indigo'] = '#4B0082'
-replace_colors['ivory'] = '#FFFFF0'
-replace_colors['khaki'] = '#F0E68C'
-replace_colors['lavender'] = '#E6E6FA'
-replace_colors['lavenderblush'] = '#FFF0F5'
-replace_colors['lawngreen'] = '#7CFC00'
-replace_colors['lemonchiffon'] = '#FFFACD'
-replace_colors['lightblue'] = '#ADD8E6'
-replace_colors['lightcoral'] = '#F08080'
-replace_colors['lightcyan'] = '#E0FFFF'
-replace_colors['lightgoldenrodyellow'] = '#FAFAD2'
-replace_colors['lightgrey'] = '#D3D3D3'
-replace_colors['lightgreen'] = '#90EE90'
-replace_colors['lightpink'] = '#FFB6C1'
-replace_colors['lightsalmon'] = '#FFA07A'
-replace_colors['lightseagreen'] = '#20B2AA'
-replace_colors['lightskyblue'] = '#87CEFA'
-replace_colors['lightslateblue'] = '#8470FF'
-replace_colors['lightslategray'] = '#778899'
-replace_colors['lightsteelblue'] = '#B0C4DE'
-replace_colors['lightyellow'] = '#FFFFE0'
-replace_colors['limegreen'] = '#32CD32'
-replace_colors['linen'] = '#FAF0E6'
-replace_colors['magenta'] = '#FF00FF'
-replace_colors['mediumaquamarine'] = '#66CDAA'
-replace_colors['mediumblue'] = '#0000CD'
-replace_colors['mediumorchid'] = '#BA55D3'
-replace_colors['mediumpurple'] = '#9370D8'
-replace_colors['mediumseagreen'] = '#3CB371'
-replace_colors['mediumslateblue'] = '#7B68EE'
-replace_colors['mediumspringgreen'] = '#00FA9A'
-replace_colors['mediumturquoise'] = '#48D1CC'
-replace_colors['mediumvioletred'] = '#C71585'
-replace_colors['midnightblue'] = '#191970'
-replace_colors['mintcream'] = '#F5FFFA'
-replace_colors['mistyrose'] = '#FFE4E1'
-replace_colors['moccasin'] = '#FFE4B5'
-replace_colors['navajowhite'] = '#FFDEAD'
-replace_colors['oldlace'] = '#FDF5E6'
-replace_colors['olivedrab'] = '#6B8E23'
-replace_colors['orangered'] = '#FF4500'
-replace_colors['orchid'] = '#DA70D6'
-replace_colors['palegoldenrod'] = '#EEE8AA'
-replace_colors['palegreen'] = '#98FB98'
-replace_colors['paleturquoise'] = '#AFEEEE'
-replace_colors['palevioletred'] = '#D87093'
-replace_colors['papayawhip'] = '#FFEFD5'
-replace_colors['peachpuff'] = '#FFDAB9'
-replace_colors['peru'] = '#CD853F'
-replace_colors['pink'] = '#FFC0CB'
-replace_colors['plum'] = '#DDA0DD'
-replace_colors['powderblue'] = '#B0E0E6'
-replace_colors['rosybrown'] = '#BC8F8F'
-replace_colors['royalblue'] = '#4169E1'
-replace_colors['saddlebrown'] = '#8B4513'
-replace_colors['salmon'] = '#FA8072'
-replace_colors['sandybrown'] = '#F4A460'
-replace_colors['seagreen'] = '#2E8B57'
-replace_colors['seashell'] = '#FFF5EE'
-replace_colors['sienna'] = '#A0522D'
-replace_colors['skyblue'] = '#87CEEB'
-replace_colors['slateblue'] = '#6A5ACD'
-replace_colors['slategray'] = '#708090'
-replace_colors['snow'] = '#FFFAFA'
-replace_colors['springgreen'] = '#00FF7F'
-replace_colors['steelblue'] = '#4682B4'
-replace_colors['tan'] = '#D2B48C'
-replace_colors['thistle'] = '#D8BFD8'
-replace_colors['tomato'] = '#FF6347'
-replace_colors['turquoise'] = '#40E0D0'
-replace_colors['violet'] = '#EE82EE'
-replace_colors['violetred'] = '#D02090'
-replace_colors['wheat'] = '#F5DEB3'
-replace_colors['whitesmoke'] = '#F5F5F5'
-replace_colors['yellowgreen'] = '#9ACD32'
-
-#A list of optimized colors
-optimize_colors = {}
-optimize_colors['black'] = '#000'
-optimize_colors['fuchsia'] = '#F0F'
-optimize_colors['white'] = '#FFF'
-optimize_colors['yellow'] = '#FF0'
-optimize_colors['cyan'] = '#0FF'
-optimize_colors['magenta'] = '#F0F'
-optimize_colors['lightslategray'] = '#789'
-
-optimize_colors['#800000'] = 'maroon'
-optimize_colors['#FFA500'] = 'orange'
-optimize_colors['#808000'] = 'olive'
-optimize_colors['#800080'] = 'purple'
-optimize_colors['#008000'] = 'green'
-optimize_colors['#000080'] = 'navy'
-optimize_colors['#008080'] = 'teal'
-optimize_colors['#C0C0C0'] = 'silver'
-optimize_colors['#808080'] = 'gray'
-optimize_colors['#4B0082'] = 'indigo'
-optimize_colors['#FFD700'] = 'gold'
-optimize_colors['#A52A2A'] = 'brown'
-optimize_colors['#00FFFF'] = 'cyan'
-optimize_colors['#EE82EE'] = 'violet'
-optimize_colors['#DA70D6'] = 'orchid'
-optimize_colors['#FFE4C4'] = 'bisque'
-optimize_colors['#F0E68C'] = 'khaki'
-optimize_colors['#F5DEB3'] = 'wheat'
-optimize_colors['#FF7F50'] = 'coral'
-optimize_colors['#F5F5DC'] = 'beige'
-optimize_colors['#F0FFFF'] = 'azure'
-optimize_colors['#A0522D'] = 'sienna'
-optimize_colors['#CD853F'] = 'peru'
-optimize_colors['#FFFFF0'] = 'ivory'
-optimize_colors['#DDA0DD'] = 'plum'
-optimize_colors['#D2B48C'] = 'tan'
-optimize_colors['#FFC0CB'] = 'pink'
-optimize_colors['#FFFAFA'] = 'snow'
-optimize_colors['#FA8072'] = 'salmon'
-optimize_colors['#FF6347'] = 'tomato'
-optimize_colors['#FAF0E6'] = 'linen'
-optimize_colors['#F00'] = 'red'
-
-
-# A list of all shorthand properties that are devided into four properties and/or have four subvalues
-#
-# @global array shorthands
-# @todo Are there new ones in CSS3?
-# @see dissolve_4value_shorthands()
-# @see merge_4value_shorthands()
-# @version 1.0
-shorthands = {}
-shorthands['border-color'] = ['border-top-color','border-right-color','border-bottom-color','border-left-color']
-shorthands['border-style'] = ['border-top-style','border-right-style','border-bottom-style','border-left-style']
-shorthands['border-width'] = ['border-top-width','border-right-width','border-bottom-width','border-left-width']
-shorthands['margin'] = ['margin-top','margin-right','margin-bottom','margin-left']
-shorthands['padding'] = ['padding-top','padding-right','padding-bottom','padding-left']
-shorthands['-moz-border-radius'] = 0
-
-# All CSS Properties. Needed for csstidy::property_is_next()
-#
-# @global array all_properties
-# @todo Add CSS3 properties
-# @version 1.0
-# @see csstidy::property_is_next()
-all_properties = {}
-all_properties['background'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['background-color'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['background-image'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['background-repeat'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['background-attachment'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['background-position'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-top'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-right'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-bottom'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-left'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-color'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-top-color'] = 'CSS2.0,CSS2.1'
-all_properties['border-bottom-color'] = 'CSS2.0,CSS2.1'
-all_properties['border-left-color'] = 'CSS2.0,CSS2.1'
-all_properties['border-right-color'] = 'CSS2.0,CSS2.1'
-all_properties['border-style'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-top-style'] = 'CSS2.0,CSS2.1'
-all_properties['border-right-style'] = 'CSS2.0,CSS2.1'
-all_properties['border-left-style'] = 'CSS2.0,CSS2.1'
-all_properties['border-bottom-style'] = 'CSS2.0,CSS2.1'
-all_properties['border-width'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-top-width'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-right-width'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-left-width'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-bottom-width'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['border-collapse'] = 'CSS2.0,CSS2.1'
-all_properties['border-spacing'] = 'CSS2.0,CSS2.1'
-all_properties['bottom'] = 'CSS2.0,CSS2.1'
-all_properties['caption-side'] = 'CSS2.0,CSS2.1'
-all_properties['content'] = 'CSS2.0,CSS2.1'
-all_properties['clear'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['clip'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['color'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['counter-reset'] = 'CSS2.0,CSS2.1'
-all_properties['counter-increment'] = 'CSS2.0,CSS2.1'
-all_properties['cursor'] = 'CSS2.0,CSS2.1'
-all_properties['empty-cells'] = 'CSS2.0,CSS2.1'
-all_properties['display'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['direction'] = 'CSS2.0,CSS2.1'
-all_properties['float'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['font'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['font-family'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['font-style'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['font-variant'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['font-weight'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['font-stretch'] = 'CSS2.0'
-all_properties['font-size-adjust'] = 'CSS2.0'
-all_properties['font-size'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['height'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['left'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['line-height'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['list-style'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['list-style-type'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['list-style-image'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['list-style-position'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['margin'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['margin-top'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['margin-right'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['margin-bottom'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['margin-left'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['marks'] = 'CSS1.0,CSS2.0'
-all_properties['marker-offset'] = 'CSS2.0'
-all_properties['max-height'] = 'CSS2.0,CSS2.1'
-all_properties['max-width'] = 'CSS2.0,CSS2.1'
-all_properties['min-height'] = 'CSS2.0,CSS2.1'
-all_properties['min-width'] = 'CSS2.0,CSS2.1'
-all_properties['overflow'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['orphans'] = 'CSS2.0,CSS2.1'
-all_properties['outline'] = 'CSS2.0,CSS2.1'
-all_properties['outline-width'] = 'CSS2.0,CSS2.1'
-all_properties['outline-style'] = 'CSS2.0,CSS2.1'
-all_properties['outline-color'] = 'CSS2.0,CSS2.1'
-all_properties['padding'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['padding-top'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['padding-right'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['padding-bottom'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['padding-left'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['page-break-before'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['page-break-after'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['page-break-inside'] = 'CSS2.0,CSS2.1'
-all_properties['page'] = 'CSS2.0'
-all_properties['position'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['quotes'] = 'CSS2.0,CSS2.1'
-all_properties['right'] = 'CSS2.0,CSS2.1'
-all_properties['size'] = 'CSS1.0,CSS2.0'
-all_properties['speak-header'] = 'CSS2.0,CSS2.1'
-all_properties['table-layout'] = 'CSS2.0,CSS2.1'
-all_properties['top'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['text-indent'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['text-align'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['text-decoration'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['text-shadow'] = 'CSS2.0'
-all_properties['letter-spacing'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['word-spacing'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['text-transform'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['white-space'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['unicode-bidi'] = 'CSS2.0,CSS2.1'
-all_properties['vertical-align'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['visibility'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['width'] = 'CSS1.0,CSS2.0,CSS2.1'
-all_properties['widows'] = 'CSS2.0,CSS2.1'
-all_properties['z-index'] = 'CSS1.0,CSS2.0,CSS2.1'
-
-# Speech #
-all_properties['volume'] = 'CSS2.0,CSS2.1'
-all_properties['speak'] = 'CSS2.0,CSS2.1'
-all_properties['pause'] = 'CSS2.0,CSS2.1'
-all_properties['pause-before'] = 'CSS2.0,CSS2.1'
-all_properties['pause-after'] = 'CSS2.0,CSS2.1'
-all_properties['cue'] = 'CSS2.0,CSS2.1'
-all_properties['cue-before'] = 'CSS2.0,CSS2.1'
-all_properties['cue-after'] = 'CSS2.0,CSS2.1'
-all_properties['play-during'] = 'CSS2.0,CSS2.1'
-all_properties['azimuth'] = 'CSS2.0,CSS2.1'
-all_properties['elevation'] = 'CSS2.0,CSS2.1'
-all_properties['speech-rate'] = 'CSS2.0,CSS2.1'
-all_properties['voice-family'] = 'CSS2.0,CSS2.1'
-all_properties['pitch'] = 'CSS2.0,CSS2.1'
-all_properties['pitch-range'] = 'CSS2.0,CSS2.1'
-all_properties['stress'] = 'CSS2.0,CSS2.1'
-all_properties['richness'] = 'CSS2.0,CSS2.1'
-all_properties['speak-punctuation'] = 'CSS2.0,CSS2.1'
-all_properties['speak-numeral'] = 'CSS2.0,CSS2.1'
\ No newline at end of file
diff --git a/apps/compress/filters/csstidy_python/optimizer.py b/apps/compress/filters/csstidy_python/optimizer.py
deleted file mode 100644 (file)
index 7cd284c..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-# CSSTidy - CSS Optimizer
-#
-# CSS Optimizer class
-#
-# This file is part of CSSTidy.
-#
-# CSSTidy is free software you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation either version 2 of the License, or
-# (at your option) any later version.
-#
-# CSSTidy is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with CSSTidy if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-#
-# @license http://opensource.org/licenses/gpl-license.php GNU Public License
-# @package csstidy
-# @author Dj Gilcrease (digitalxero at gmail dot com) 2005-2006
-
-import data
-from tools import SortedDict
-
-
-class CSSOptimizer(object):
-    def __init__(self, parser):
-        #raw_css is a dict
-        self.parser = parser
-        self._optimized_css = SortedDict
-
-
-#PUBLIC METHODS
-    def optimize(self, raw_css):
-        if self.parser.getSetting('preserve_css'):
-            return raw_css
-
-        self._optimized_css = raw_css
-
-        if self.parser.getSetting('merge_selectors') == 2:
-            self.__merge_selectors()
-
-        ##OPTIMIZE##
-        for media, css in self._optimized_css.iteritems():
-            for selector, cssdata in css.iteritems():
-                if self.parser.getSetting('optimise_shorthands') >= 1:
-                    cssdata = self.__merge_4value_shorthands(cssdata)
-
-                if self.parser.getSetting('optimise_shorthands') >= 2:
-                    cssdata = self.__merge_bg(cssdata)
-
-                for item, value in cssdata.iteritems():
-                    value = self.__compress_numbers(item, value)
-                    value = self.__compress_important(value)
-
-                    if item in data.color_values and self.parser.getSetting('compress_colors'):
-                        old = value[:]
-                        value = self.__compress_color(value)
-                        if old != value:
-                            self.parser.log('In "' + selector + '" Optimised ' + item + ': Changed ' + old + ' to ' + value, 'Information')
-
-                    if item == 'font-weight' and self.parser.getSetting('compress_font-weight'):
-                        if value  == 'bold':
-                            value = '700'
-                            self.parser.log('In "' + selector + '" Optimised font-weight: Changed "bold" to "700"', 'Information')
-
-                        elif value == 'normal':
-                            value = '400'
-                            self.parser.log('In "' + selector + '" Optimised font-weight: Changed "normal" to "400"', 'Information')
-
-                    self._optimized_css[media][selector][item] = value
-
-
-        return self._optimized_css
-
-
-#PRIVATE METHODS
-    def __merge_bg(self, cssdata):
-        """
-            Merges all background properties
-            @cssdata (dict) is a dictionary of the selector properties
-        """
-        #Max number of background images. CSS3 not yet fully implemented
-        img = 1
-        clr = 1
-        bg_img_list = []
-        if cssdata.has_key('background-image'):
-            img = len(cssdata['background-image'].split(','))
-            bg_img_list = self.parser.gvw_important(cssdata['background-image']).split(',')
-
-        elif cssdata.has_key('background-color'):
-            clr = len(cssdata['background-color'].split(','))
-
-
-        number_of_values = max(img, clr, 1)
-
-        new_bg_value = ''
-        important = ''
-
-        for i in xrange(number_of_values):
-            for bg_property, default_value in data.background_prop_default.iteritems():
-                #Skip if property does not exist
-                if not cssdata.has_key(bg_property):
-                    continue
-
-                cur_value = cssdata[bg_property]
-
-                #Skip some properties if there is no background image
-                if (len(bg_img_list) > i and bg_img_list[i] == 'none') and bg_property in frozenset(['background-size', 'background-position', 'background-attachment', 'background-repeat']):
-                    continue
-
-                #Remove !important
-                if self.parser.is_important(cur_value):
-                    important = ' !important'
-                    cur_value = self.parser.gvw_important(cur_value)
-
-                #Do not add default values
-                if cur_value == default_value:
-                    continue
-
-                temp = cur_value.split(',')
-
-                if len(temp) > i:
-                    if bg_property == 'background-size':
-                        new_bg_value += '(' + temp[i] + ') '
-
-                    else:
-                        new_bg_value += temp[i] + ' '
-
-            new_bg_value = new_bg_value.strip()
-            if i != (number_of_values-1):
-                new_bg_value += ','
-
-        #Delete all background-properties
-        for bg_property, default_value in data.background_prop_default.iteritems():
-            try:
-                del cssdata[bg_property]
-            except:
-                pass
-
-        #Add new background property
-        if new_bg_value != '':
-            cssdata['background'] = new_bg_value + important
-
-        return cssdata
-
-    def __merge_4value_shorthands(self, cssdata):
-        """
-            Merges Shorthand properties again, the opposite of dissolve_4value_shorthands()
-            @cssdata (dict) is a dictionary of the selector properties
-        """
-        for key, value in data.shorthands.iteritems():
-            important = ''
-            if value != 0 and cssdata.has_key(value[0]) and cssdata.has_key(value[1]) and cssdata.has_key(value[2]) and cssdata.has_key(value[3]):
-                cssdata[key] = ''
-
-                for i in xrange(4):
-                    val = cssdata[value[i]]
-                    if self.parser.is_important(val):
-                        important = '!important'
-                        cssdata[key] += self.parser.gvw_important(val) + ' '
-
-                    else:
-                        cssdata[key] += val + ' '
-
-                    del cssdata[value[i]]
-            if cssdata.has_key(key):
-                cssdata[key] = self.__shorthand(cssdata[key] + important.strip())
-
-        return cssdata
-
-
-    def __merge_selectors(self):
-        """
-            Merges selectors with same properties. Example: a{color:red} b{color:red} . a,b{color:red}
-            Very basic and has at least one bug. Hopefully there is a replacement soon.
-            @selector_one (string) is the current selector
-            @value_one (dict) is a dictionary of the selector properties
-            Note: Currently is the elements of a selector are identical, but in a different order, they are not merged
-        """
-
-        ##OPTIMIZE##
-        ##FIX##
-
-        raw_css = self._optimized_css.copy()
-        delete = []
-        add = SortedDict()
-        for media, css in raw_css.iteritems():
-            for selector_one, value_one in css.iteritems():
-                newsel = selector_one
-
-                for selector_two, value_two in css.iteritems():
-                    if selector_one == selector_two:
-                        #We need to skip self
-                        continue
-
-                    if value_one == value_two:
-                        #Ok, we need to merge these two selectors
-                        newsel += ', ' + selector_two
-                        delete.append((media, selector_two))
-
-
-        if not add.has_key(media):
-            add[media] = SortedDict()
-
-        add[media][newsel] = value_one
-        delete.append((media, selector_one))
-
-        for item in delete:
-            try:
-                del self._optimized_css[item[0]][item[1]]
-            except:
-                #Must have already been deleted
-                continue
-
-        for media, css in add.iteritems():
-            self._optimized_css[media].update(css)
-
-
-
-    def __shorthand(self, value):
-        """
-            Compresses shorthand values. Example: margin:1px 1px 1px 1px . margin:1px
-            @value (string)
-        """
-
-        ##FIX##
-
-        important = '';
-        if self.parser.is_important(value):
-            value_list = self.parser.gvw_important(value)
-            important = '!important'
-        else:
-            value_list = value
-
-        ret = value
-        value_list = value_list.split(' ')
-
-        if len(value_list) == 4:
-            if value_list[0] == value_list[1] and value_list[0] == value_list[2] and value_list[0] == value_list[3]:
-                ret = value_list[0] + important
-
-            elif value_list[1] == value_list[3] and value_list[0] == value_list[2]:
-                ret = value_list[0] + ' ' + value_list[1] + important
-
-            elif value_list[1] == value_list[3]:
-                ret = value_list[0] + ' ' + value_list[1] + ' ' + value_list[2] + important
-
-        elif len(value_list) == 3:
-            if value_list[0] == value_list[1] and value_list[0] == value_list[2]:
-                ret = value_list[0] + important
-
-            elif value_list[0] == value_list[2]:
-                return value_list[0] + ' ' + value_list[1] + important
-
-        elif len(value_list) == 2:
-            if value_list[0] == value_list[1]:
-                ret = value_list[0] + important
-
-        if ret != value:
-            self.parser.log('Optimised shorthand notation: Changed "' + value + '" to "' + ret + '"', 'Information')
-
-        return ret
-
-    def __compress_important(self, value):
-        """
-            Removes unnecessary whitespace in ! important
-            @value (string)
-        """
-        if self.parser.is_important(value):
-            value = self.parser.gvw_important(value) + '!important'
-
-        return value
-
-    def __compress_numbers(self, prop, value):
-        """
-            Compresses numbers (ie. 1.0 becomes 1 or 1.100 becomes 1.1 )
-            @value (string) is the posible number to be compressed
-        """
-
-        ##FIX##
-
-        value = value.split('/')
-
-        for l in xrange(len(value)):
-            #continue if no numeric value
-            if not (len(value[l]) > 0 and (value[l][0].isdigit() or value[l][0] in ('+', '-') )):
-                continue
-
-            #Fix bad colors
-            if prop in data.color_values:
-                value[l] = '#' + value[l]
-
-            is_floatable = False
-            try:
-                float(value[l])
-                is_floatable = True
-            except:
-                pass
-
-            if is_floatable and float(value[l]) == 0:
-                value[l] = '0'
-
-            elif value[l][0] != '#':
-                unit_found = False
-                for unit in data.units:
-                    pos = value[l].lower().find(unit)
-                    if pos != -1 and prop not in data.shorthands:
-                        value[l] = self.__remove_leading_zeros(float(value[l][:pos])) + unit
-                        unit_found = True
-                        break;
-
-                if not unit_found and prop in data.unit_values and prop not in data.shorthands:
-                    value[l] = self.__remove_leading_zeros(float(value[l])) + 'px'
-
-                elif not unit_found and prop not in data.shorthands:
-                    value[l] = self.__remove_leading_zeros(float(value[l]))
-
-
-        if len(value) > 1:
-            return '/'.join(value)
-
-        return value[0]
-
-    def __remove_leading_zeros(self, float_val):
-        """
-            Removes the leading zeros from a float value
-            @float_val (float)
-            @returns (string)
-        """
-        #Remove leading zero
-        if abs(float_val) < 1:
-            if float_val < 0:
-                float_val = '-' . str(float_val)[2:]
-            else:
-                float_val = str(float_val)[1:]
-
-        return str(float_val)
-
-    def __compress_color(self, color):
-        """
-            Color compression function. Converts all rgb() values to #-values and uses the short-form if possible. Also replaces 4 color names by #-values.
-            @color (string) the {posible} color to change
-        """
-
-        #rgb(0,0,0) . #000000 (or #000 in this case later)
-        if color[:4].lower() == 'rgb(':
-            color_tmp = color[4:(len(color)-5)]
-            color_tmp = color_tmp.split(',')
-
-            for c in color_tmp:
-                c = c.strip()
-                if c[:-1] == '%':
-                    c = round((255*color_tmp[i])/100)
-
-                if color_tmp[i] > 255:
-                    color_tmp[i] = 255
-
-            color = '#'
-
-            for i in xrange(3):
-                if color_tmp[i] < 16:
-                    color += '0' + str(hex(color_tmp[i])).replace('0x', '')
-                else:
-                    color += str(hex(color_tmp[i])).replace('0x', '')
-
-        #Fix bad color names
-        if data.replace_colors.has_key(color.lower()):
-            color = data.replace_colors[color.lower()]
-
-        #aabbcc . #abc
-        if len(color) == 7:
-            color_temp = color.lower()
-            if color_temp[0] == '#' and color_temp[1] == color_temp[2] and color_temp[3] == color_temp[4] and color_temp[5] == color_temp[6]:
-                color = '#' + color[1] + color[3] + color[5]
-
-        if data.optimize_colors.has_key(color.lower()):
-            color = data.optimize_colors[color.lower()]
-
-        return color
\ No newline at end of file
diff --git a/apps/compress/filters/csstidy_python/output.py b/apps/compress/filters/csstidy_python/output.py
deleted file mode 100644 (file)
index 795a0d0..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-# CSSTidy - CSS Printer
-#
-# CSS Printer class
-#
-# This file is part of CSSTidy.
-#
-# CSSTidy is free software you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation either version 2 of the License, or
-# (at your option) any later version.
-#
-# CSSTidy is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with CSSTidy if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-#
-# @license http://opensource.org/licenses/gpl-license.php GNU Public License
-# @package csstidy
-# @author Dj Gilcrease (digitalxero at gmail dot com) 2005-2006
-
-import data
-
-class CSSPrinter(object):
-    def __init__(self, parser):
-        self.parser = parser
-        self._css = {}
-        self.__renderMethods = {'string': self.__renderString, 'file': self.__renderFile}
-
-#PUBLIC METHODS
-    def prepare(self, css):
-        self._css = css
-
-    def render(self, output="string", *args, **kwargs):
-        return self.__renderMethods[output](*args, **kwargs)
-
-#PRIVATE METHODS
-    def __renderString(self, *args, **kwargs):
-        ##OPTIMIZE##
-        template = self.parser.getSetting('template')
-        ret = ""
-
-        if template == 'highest_compression':
-            top_line_end = ""
-            iner_line_end = ""
-            bottom_line_end = ""
-            indent = ""
-
-        elif template == 'high_compression':
-            top_line_end = "\n"
-            iner_line_end = ""
-            bottom_line_end = "\n"
-            indent = ""
-
-        elif template == 'default':
-            top_line_end = "\n"
-            iner_line_end = "\n"
-            bottom_line_end = "\n\n"
-            indent = ""
-
-        elif template == 'low_compression':
-            top_line_end = "\n"
-            iner_line_end = "\n"
-            bottom_line_end = "\n\n"
-            indent = "    "
-
-        if self.parser.getSetting('timestamp'):
-            ret += '/# CSSTidy ' + self.parser.version + ': ' + datetime.now().strftime("%a, %d %b %Y %H:%M:%S +0000") + ' #/' + top_line_end
-
-        for item in self.parser._import:
-            ret += '@import(' + item + ');' + top_line_end
-
-        for item in self.parser._charset:
-            ret += '@charset(' + item + ');' + top_line_end
-
-        for item in self.parser._namespace:
-            ret += '@namespace(' + item + ');' + top_line_end
-
-        for media, css in self._css.iteritems():
-            for selector, cssdata in css.iteritems():
-                ret += selector + '{' + top_line_end
-
-                for item, value in cssdata.iteritems():
-                    ret += indent +  item + ':' + value + ';' + iner_line_end
-
-                ret += '}' + bottom_line_end
-
-        return ret
-
-    def __renderFile(self, filename=None, *args, **kwargs):
-        if filename is None:
-            return self.__renderString()
-
-        try:
-            f = open(filename, "w")
-            f.write(self.__renderString())
-        finally:
-            f.close()
\ No newline at end of file
diff --git a/apps/compress/filters/csstidy_python/tools.py b/apps/compress/filters/csstidy_python/tools.py
deleted file mode 100644 (file)
index e62faef..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-
-class SortedDict(dict):
-    """
-    A dictionary that keeps its keys in the order in which they're inserted.
-    """
-    def __init__(self, data=None):
-        if data is None:
-            data = {}
-        super(SortedDict, self).__init__(data)
-        if isinstance(data, dict):
-            self.keyOrder = data.keys()
-        else:
-            self.keyOrder = []
-            for key, value in data:
-                if key not in self.keyOrder:
-                    self.keyOrder.append(key)
-
-    def __deepcopy__(self, memo):
-        from copy import deepcopy
-        return self.__class__([(key, deepcopy(value, memo))
-                               for key, value in self.iteritems()])
-
-    def __setitem__(self, key, value):
-        super(SortedDict, self).__setitem__(key, value)
-        if key not in self.keyOrder:
-            self.keyOrder.append(key)
-
-    def __delitem__(self, key):
-        super(SortedDict, self).__delitem__(key)
-        self.keyOrder.remove(key)
-
-    def __iter__(self):
-        for k in self.keyOrder:
-            yield k
-
-    def pop(self, k, *args):
-        result = super(SortedDict, self).pop(k, *args)
-        try:
-            self.keyOrder.remove(k)
-        except ValueError:
-            # Key wasn't in the dictionary in the first place. No problem.
-            pass
-        return result
-
-    def popitem(self):
-        result = super(SortedDict, self).popitem()
-        self.keyOrder.remove(result[0])
-        return result
-
-    def items(self):
-        return zip(self.keyOrder, self.values())
-
-    def iteritems(self):
-        for key in self.keyOrder:
-            yield key, super(SortedDict, self).__getitem__(key)
-
-    def keys(self):
-        return self.keyOrder[:]
-
-    def iterkeys(self):
-        return iter(self.keyOrder)
-
-    def values(self):
-        return [super(SortedDict, self).__getitem__(k) for k in self.keyOrder]
-
-    def itervalues(self):
-        for key in self.keyOrder:
-            yield super(SortedDict, self).__getitem__(key)
-
-    def update(self, dict_):
-        for k, v in dict_.items():
-            self.__setitem__(k, v)
-
-    def setdefault(self, key, default):
-        if key not in self.keyOrder:
-            self.keyOrder.append(key)
-        return super(SortedDict, self).setdefault(key, default)
-
-    def value_for_index(self, index):
-        """Returns the value of the item at the given zero-based index."""
-        return self[self.keyOrder[index]]
-
-    def insert(self, index, key, value):
-        """Inserts the key, value pair before the item with the given index."""
-        if key in self.keyOrder:
-            n = self.keyOrder.index(key)
-            del self.keyOrder[n]
-            if n < index:
-                index -= 1
-        self.keyOrder.insert(index, key)
-        super(SortedDict, self).__setitem__(key, value)
-
-    def copy(self):
-        """Returns a copy of this object."""
-        # This way of initializing the copy means it works for subclasses, too.
-        obj = self.__class__(self)
-        obj.keyOrder = self.keyOrder[:]
-        return obj
-
-    def __repr__(self):
-        """
-        Replaces the normal dict.__repr__ with a version that returns the keys
-        in their sorted order.
-        """
-        return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()])
-
-    def clear(self):
-        super(SortedDict, self).clear()
-        self.keyOrder = []
\ No newline at end of file
index d226200..340bef2 100644 (file)
@@ -1,6 +1,8 @@
 from compress.filters.jsmin.jsmin import jsmin
 from compress.filter_base import FilterBase
 
+
 class JSMinFilter(FilterBase):
+
     def filter_js(self, js):
-        return jsmin(js)
\ No newline at end of file
+        return jsmin(js)
index 4f9d384..60202e1 100644 (file)
@@ -32,6 +32,7 @@
 
 from StringIO import StringIO
 
+
 def jsmin(js):
     ins = StringIO(js)
     outs = StringIO()
@@ -41,26 +42,33 @@ def jsmin(js):
         str = str[1:]
     return str
 
+
 def isAlphanum(c):
     """return true if the character is a letter, digit, underscore,
            dollar sign, or non-ASCII character.
     """
-    return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or
-            (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126));
+    return (c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') \
+        or (c >= '0' and c <= '9') or c == '_' or c == '$' or c == '\\' \
+        or (c is not None and ord(c) > 126)
+
 
 class UnterminatedComment(Exception):
     pass
 
+
 class UnterminatedStringLiteral(Exception):
     pass
 
+
 class UnterminatedRegularExpression(Exception):
     pass
 
+
 class JavascriptMinify(object):
 
     def _outA(self):
         self.outstream.write(self.theA)
+
     def _outB(self):
         self.outstream.write(self.theB)
 
@@ -75,7 +83,7 @@ class JavascriptMinify(object):
             c = self.instream.read(1)
         if c >= ' ' or c == '\n':
             return c
-        if c == '': # EOF
+        if c == '':  # EOF
             return '\000'
         if c == '\r':
             return '\n'
@@ -135,7 +143,6 @@ class JavascriptMinify(object):
                         self._outA()
                         self.theA = self._get()
 
-
         if action <= 3:
             self.theB = self._next()
             if self.theB == '/' and (self.theA == '(' or self.theA == ',' or
@@ -159,7 +166,6 @@ class JavascriptMinify(object):
                     self._outA()
                 self.theB = self._next()
 
-
     def _jsmin(self):
         """Copy the input to the output, deleting the characters which are
            insignificant to JavaScript. Comments will be removed. Tabs will be
@@ -215,4 +221,4 @@ class JavascriptMinify(object):
 if __name__ == '__main__':
     import sys
     jsm = JavascriptMinify()
-    jsm.minify(sys.stdin, sys.stdout)
\ No newline at end of file
+    jsm.minify(sys.stdin, sys.stdout)
index 1e2e711..47b2cfb 100644 (file)
@@ -8,6 +8,7 @@ BINARY = getattr(settings, 'COMPRESS_YUI_BINARY', 'java -jar yuicompressor.jar')
 CSS_ARGUMENTS = getattr(settings, 'COMPRESS_YUI_CSS_ARGUMENTS', '')
 JS_ARGUMENTS = getattr(settings, 'COMPRESS_YUI_JS_ARGUMENTS', '')
 
+
 class YUICompressorFilter(FilterBase):
 
     def filter_common(self, content, type_, arguments):
@@ -41,4 +42,4 @@ class YUICompressorFilter(FilterBase):
         return self.filter_common(js, 'js', JS_ARGUMENTS)
 
     def filter_css(self, css):
-        return self.filter_common(css, 'css', CSS_ARGUMENTS)
\ No newline at end of file
+        return self.filter_common(css, 'css', CSS_ARGUMENTS)
index 8217979..b1cdafc 100644 (file)
@@ -3,6 +3,7 @@ from optparse import make_option
 
 from django.conf import settings
 
+
 class Command(NoArgsCommand):
     option_list = NoArgsCommand.option_list + (
         make_option('--force', action='store_true', default=False, help='Force update of all files, even if the source files are older than the current compressed file.'),
@@ -11,14 +12,14 @@ class Command(NoArgsCommand):
     args = ''
 
     def handle_noargs(self, **options):
-        
+
         force = options.get('force', False)
         verbosity = int(options.get('verbosity', 1))
 
         from compress.utils import needs_update, filter_css, filter_js
 
         for name, css in settings.COMPRESS_CSS.items():
-            u, version = needs_update(css['output_filename'], 
+            u, version = needs_update(css['output_filename'],
                 css['source_filenames'])
 
             if (force or u) or verbosity >= 2:
@@ -34,7 +35,7 @@ class Command(NoArgsCommand):
                 print
 
         for name, js in settings.COMPRESS_JS.items():
-            u, version = needs_update(js['output_filename'], 
+            u, version = needs_update(js['output_filename'],
                 js['source_filenames'])
 
             if (force or u) or verbosity >= 2:
@@ -50,7 +51,7 @@ class Command(NoArgsCommand):
                 print
 
 # Backwards compatibility for Django r9110
-if not [opt for opt in Command.option_list if opt.dest=='verbosity']:
+if not [opt for opt in Command.option_list if opt.dest == 'verbosity']:
     Command.option_list += (
     make_option('--verbosity', '-v', action="store", dest="verbosity",
         default='1', type='choice', choices=['0', '1', '2'],
index f9c55f9..eeed319 100644 (file)
@@ -2,13 +2,12 @@ import os
 
 from django import template
 
-from django.conf import settings as django_settings
-
 from compress.conf import settings
 from compress.utils import media_root, media_url, needs_update, filter_css, filter_js, get_output_filename, get_version, get_version_from_file
 
 register = template.Library()
 
+
 def render_common(template_name, obj, filename, version):
     if settings.COMPRESS:
         filename = get_output_filename(filename, version)
@@ -19,16 +18,20 @@ def render_common(template_name, obj, filename, version):
         context['url'] = filename
     else:
         context['url'] = media_url(filename, prefix)
-        
+
     return template.loader.render_to_string(template_name, context)
 
+
 def render_css(css, filename, version=None):
     return render_common(css.get('template_name', 'compress/css.html'), css, filename, version)
 
+
 def render_js(js, filename, version=None):
     return render_common(js.get('template_name', 'compress/js.html'), js, filename, version)
 
+
 class CompressedCSSNode(template.Node):
+
     def __init__(self, name):
         self.name = name
 
@@ -38,14 +41,14 @@ class CompressedCSSNode(template.Node):
         try:
             css = settings.COMPRESS_CSS[css_name]
         except KeyError:
-            return '' # fail silently, do not return anything if an invalid group is specified
+            return ''  # fail silently, do not return anything if an invalid group is specified
 
         if settings.COMPRESS:
 
             version = None
 
             if settings.COMPRESS_AUTO:
-                u, version = needs_update(css['output_filename'], 
+                u, version = needs_update(css['output_filename'],
                     css['source_filenames'])
                 if u:
                     filter_css(css)
@@ -53,7 +56,7 @@ class CompressedCSSNode(template.Node):
                 filename_base, filename = os.path.split(css['output_filename'])
                 path_name = media_root(filename_base)
                 version = get_version_from_file(path_name, filename)
-                
+
             return render_css(css, css['output_filename'], version)
         else:
             # output source files
@@ -63,7 +66,9 @@ class CompressedCSSNode(template.Node):
 
             return r
 
+
 class CompressedJSNode(template.Node):
+
     def __init__(self, name):
         self.name = name
 
@@ -73,24 +78,24 @@ class CompressedJSNode(template.Node):
         try:
             js = settings.COMPRESS_JS[js_name]
         except KeyError:
-            return '' # fail silently, do not return anything if an invalid group is specified
-        
+            return ''  # fail silently, do not return anything if an invalid group is specified
+
         if 'external_urls' in js:
             r = ''
             for url in js['external_urls']:
                 r += render_js(js, url)
             return r
-                    
+
         if settings.COMPRESS:
 
             version = None
 
             if settings.COMPRESS_AUTO:
-                u, version = needs_update(js['output_filename'], 
+                u, version = needs_update(js['output_filename'],
                     js['source_filenames'])
                 if u:
                     filter_js(js)
-            else: 
+            else:
                 filename_base, filename = os.path.split(js['output_filename'])
                 path_name = media_root(filename_base)
                 version = get_version_from_file(path_name, filename)
@@ -103,6 +108,7 @@ class CompressedJSNode(template.Node):
                 r += render_js(js, source_file)
             return r
 
+
 #@register.tag
 def compressed_css(parser, token):
     try:
@@ -113,6 +119,7 @@ def compressed_css(parser, token):
     return CompressedCSSNode(name)
 compressed_css = register.tag(compressed_css)
 
+
 #@register.tag
 def compressed_js(parser, token):
     try:
@@ -121,4 +128,5 @@ def compressed_js(parser, token):
         raise template.TemplateSyntaxError, '%r requires exactly one argument: the name of a group in the COMPRESS_JS setting' % token.split_contents()[0]
 
     return CompressedJSNode(name)
+
 compressed_js = register.tag(compressed_js)
index 5e13222..1e5f4cc 100644 (file)
@@ -9,6 +9,7 @@ from django.dispatch import dispatcher
 from compress.conf import settings
 from compress.signals import css_filtered, js_filtered
 
+
 def get_class(class_string):
     """
     Convert a string version of a function name to the callable object.
@@ -26,6 +27,7 @@ def get_class(class_string):
 
     return class_string
 
+
 def get_mod_func(callback):
     """
     Converts 'django.views.news.stories.story_detail' to
@@ -36,7 +38,8 @@ def get_mod_func(callback):
         dot = callback.rindex('.')
     except ValueError:
         return callback, ''
-    return callback[:dot], callback[dot+1:]
+    return callback[:dot], callback[dot + 1:]
+
 
 def needs_update(output_file, source_files, verbosity=0):
     """
@@ -44,27 +47,30 @@ def needs_update(output_file, source_files, verbosity=0):
     """
 
     version = get_version(source_files)
-    
+
     on = get_output_filename(output_file, version)
     compressed_file_full = media_root(on)
 
     if not os.path.exists(compressed_file_full):
         return True, version
-        
+
     update_needed = getattr(get_class(settings.COMPRESS_VERSIONING)(), 'needs_update')(output_file, source_files, version)
     return update_needed
 
+
 def media_root(filename):
     """
     Return the full path to ``filename``. ``filename`` is a relative path name in MEDIA_ROOT
     """
     return os.path.join(django_settings.STATIC_ROOT, filename)
 
+
 def media_url(url, prefix=None):
     if prefix:
         return prefix + urlquote(url)
     return django_settings.STATIC_URL + urlquote(url)
 
+
 def concat(filenames, separator=''):
     """
     Concatenate the files from the list of the ``filenames``, ouput separated with ``separator``.
@@ -77,9 +83,11 @@ def concat(filenames, separator=''):
         fd.close()
     return r
 
+
 def max_mtime(files):
     return int(max([os.stat(media_root(f)).st_mtime for f in files]))
 
+
 def save_file(filename, contents):
     dirname = os.path.dirname(media_root(filename))
     if not os.path.exists(dirname):
@@ -88,16 +96,19 @@ def save_file(filename, contents):
     fd.write(contents)
     fd.close()
 
+
 def get_output_filename(filename, version):
     if settings.COMPRESS_VERSION and version is not None:
         return filename.replace(settings.COMPRESS_VERSION_PLACEHOLDER, version)
     else:
         return filename.replace(settings.COMPRESS_VERSION_PLACEHOLDER, settings.COMPRESS_VERSION_DEFAULT)
 
+
 def get_version(source_files, verbosity=0):
     version = getattr(get_class(settings.COMPRESS_VERSIONING)(), 'get_version')(source_files)
     return version
-    
+
+
 def get_version_from_file(path, filename):
     regex = re.compile(r'^%s$' % (get_output_filename(settings.COMPRESS_VERSION_PLACEHOLDER.join([re.escape(part) for part in filename.split(settings.COMPRESS_VERSION_PLACEHOLDER)]), r'([A-Za-z0-9]+)')))
     for f in os.listdir(path):
@@ -105,19 +116,21 @@ def get_version_from_file(path, filename):
         if result and result.groups():
             return result.groups()[0]
 
-def remove_files(path, filename, verbosity=0):    
+
+def remove_files(path, filename, verbosity=0):
     regex = re.compile(r'^%s$' % (os.path.basename(get_output_filename(settings.COMPRESS_VERSION_PLACEHOLDER.join([re.escape(part) for part in filename.split(settings.COMPRESS_VERSION_PLACEHOLDER)]), r'[A-Za-z0-9]+'))))
     if os.path.exists(path):
         for f in os.listdir(path):
             if regex.match(f):
                 if verbosity >= 1:
                     print "Removing outdated file %s" % f
-        
+
                 os.unlink(os.path.join(path, f))
 
+
 def filter_common(obj, verbosity, filters, attr, separator, signal):
     output = concat(obj['source_filenames'], separator)
-    
+
     filename = get_output_filename(obj['output_filename'], get_version(obj['source_filenames']))
 
     if settings.COMPRESS_VERSION:
@@ -132,8 +145,10 @@ def filter_common(obj, verbosity, filters, attr, separator, signal):
     save_file(filename, output)
     signal.send(None)
 
+
 def filter_css(css, verbosity=0):
     return filter_common(css, verbosity, filters=settings.COMPRESS_CSS_FILTERS, attr='filter_css', separator='', signal=css_filtered)
 
+
 def filter_js(js, verbosity=0):
     return filter_common(js, verbosity, filters=settings.COMPRESS_JS_FILTERS, attr='filter_js', separator='', signal=js_filtered)
index 8b81519..0be9aca 100644 (file)
@@ -2,12 +2,13 @@ class VersioningBase(object):
 
     def get_version(self, source_files):
         raise NotImplementedError
-        
+
     def needs_update(self, output_file, source_files, version):
         raise NotImplementedError
-        
+
+
 class VersioningError(Exception):
     """
     This exception is raised when version creation fails
     """
-    pass
\ No newline at end of file
+    pass
index 74721fe..a298961 100644 (file)
@@ -6,30 +6,32 @@ from compress.conf import settings
 from compress.utils import concat, get_output_filename
 from compress.versioning.base import VersioningBase
 
+
 class HashVersioningBase(VersioningBase):
+
     def __init__(self, hash_method):
         self.hash_method = hash_method
-    
+
     def needs_update(self, output_file, source_files, version):
         output_file_name = get_output_filename(output_file, version)
         ph = settings.COMPRESS_VERSION_PLACEHOLDER
         of = output_file
         try:
             phi = of.index(ph)
-            old_version = output_file_name[phi:phi+len(ph)-len(of)]
+            old_version = output_file_name[phi:phi + len(ph) - len(of)]
             return (version != old_version), version
         except ValueError:
             # no placeholder found, do not update, manual update if needed
             return False, version
-            
+
     def get_version(self, source_files):
         buf = concat(source_files)
         s = cStringIO.StringIO(buf)
         version = self.get_hash(s)
         s.close()
-        return version            
-            
-    def get_hash(self, f, CHUNK=2**16):
+        return version
+
+    def get_hash(self, f, CHUNK=2 ** 16):
         m = self.hash_method()
         while 1:
             chunk = f.read(CHUNK)
@@ -38,10 +40,14 @@ class HashVersioningBase(VersioningBase):
             m.update(chunk)
         return m.hexdigest()
 
+
 class MD5Versioning(HashVersioningBase):
+
     def __init__(self):
         super(MD5Versioning, self).__init__(md5)
 
+
 class SHA1Versioning(HashVersioningBase):
+
     def __init__(self):
-        super(SHA1Versioning, self).__init__(sha1)
\ No newline at end of file
+        super(SHA1Versioning, self).__init__(sha1)
index 31b9d0b..010aba9 100644 (file)
@@ -3,6 +3,7 @@ import os
 from compress.utils import get_output_filename, media_root
 from compress.versioning.base import VersioningBase
 
+
 class MTimeVersioning(VersioningBase):
 
     def get_version(self, source_files):
@@ -16,4 +17,3 @@ class MTimeVersioning(VersioningBase):
         compressed_file_full = media_root(output_file_name)
 
         return (int(os.stat(compressed_file_full).st_mtime) < int(version)), version
-
index f14619d..328469a 100644 (file)
@@ -7,6 +7,7 @@ from django_cas.models import User
 
 __all__ = ['CASBackend']
 
+
 def _verify_cas1(ticket, service):
     """Verifies CAS 1.0 authentication ticket.
 
@@ -77,7 +78,7 @@ class CASBackend(object):
         if not username:
             return None
         try:
-            user = User.objects.get(username__iexact = username)
+            user = User.objects.get(username__iexact=username)
         except User.DoesNotExist:
             # user will have an "unusable" password
             user = User.objects.create_user(username, '')
@@ -88,6 +89,6 @@ class CASBackend(object):
         """Retrieve the user's entry in the User model if it exists"""
 
         try:
-            return User.objects.get(pk = user_id)
+            return User.objects.get(pk=user_id)
         except User.DoesNotExist:
             return None
index 54a3734..0bf989b 100644 (file)
@@ -12,6 +12,7 @@ from django.utils.http import urlquote
 
 __all__ = ['login_required', 'permission_required', 'user_passes_test']
 
+
 def user_passes_test(test_func, login_url=None,
                      redirect_field_name=REDIRECT_FIELD_NAME):
     """Replacement for django.contrib.auth.decorators.user_passes_test that
index 8d5243d..35fd0d5 100644 (file)
@@ -12,6 +12,7 @@ from django_cas.views import login as cas_login, logout as cas_logout
 
 __all__ = ['CASMiddleware']
 
+
 class CASMiddleware(object):
     """Middleware that allows CAS authentication on admin pages"""
 
index 7658df9..85206e0 100644 (file)
@@ -1,2 +1,2 @@
 from django.db import models
-from django.contrib.auth.models import User
\ No newline at end of file
+from django.contrib.auth.models import User
index 8bbe566..dee3279 100644 (file)
@@ -9,7 +9,8 @@ from django.contrib.auth import REDIRECT_FIELD_NAME
 
 __all__ = ['login', 'logout']
 
-def _service_url(request, redirect_to = None):
+
+def _service_url(request, redirect_to=None):
     """Generates application service URL for CAS"""
 
     protocol = ('http://', 'https://')[request.is_secure()]
@@ -51,7 +52,7 @@ def _login_url(service):
     return urljoin(settings.CAS_SERVER_URL, 'login') + '?' + urlencode(params)
 
 
-def _logout_url(request, next_page = None):
+def _logout_url(request, next_page=None):
     """Generates CAS logout URL"""
 
     url = urljoin(settings.CAS_SERVER_URL, 'logout')
@@ -62,7 +63,7 @@ def _logout_url(request, next_page = None):
     return url
 
 
-def login(request, next_page = None, required = False):
+def login(request, next_page=None, required=False):
     """Forwards to CAS login URL or verifies CAS ticket"""
 
     print "LOGIN original NEXT_PAGE:", next_page
@@ -73,7 +74,7 @@ def login(request, next_page = None, required = False):
 
     if request.user.is_authenticated():
         message = "You are logged in as %s." % request.user.username
-        request.user.message_set.create(message = message)
+        request.user.message_set.create(message=message)
         return HttpResponseRedirect(next_page)
     ticket = request.GET.get('ticket')
     service = _service_url(request, next_page)
@@ -81,12 +82,12 @@ def login(request, next_page = None, required = False):
     print "SERVICE: ", service
     if ticket:
         from django.contrib import auth
-        user = auth.authenticate(ticket = ticket, service = service)
+        user = auth.authenticate(ticket=ticket, service=service)
         if user is not None:
             auth.login(request, user)
             name = user.first_name or user.username
             message = "Login succeeded. Welcome, %s." % name
-            user.message_set.create(message = message)
+            user.message_set.create(message=message)
             return HttpResponseRedirect(next_page)
         elif settings.CAS_RETRY_LOGIN or required:
             return HttpResponseRedirect(_login_url(service))
@@ -98,7 +99,7 @@ def login(request, next_page = None, required = False):
         return HttpResponseRedirect(_login_url(service))
 
 
-def logout(request, next_page = None):
+def logout(request, next_page=None):
     """Redirects to CAS logout page"""
 
     from django.contrib.auth import logout
index 4f0a024..c124026 100644 (file)
@@ -1,16 +1,22 @@
-# coding: utf-8
+# -*- coding: utf-8
 
-import locale
-
-import os, re, datetime
-from time import gmtime, strftime
 from django.conf import settings
 from django.utils.encoding import smart_unicode
+from filebrowser.fb_settings import *
+
+from filebrowser.functions import _get_file_type, _url_join, _is_selectable, \
+    _get_version_path
+
+from time import gmtime, strftime
+
+import locale
+import os
+import re
+import datetime
 import urllib
 
+
 # filebrowser imports
-from filebrowser.fb_settings import *
-from filebrowser.functions import _get_file_type, _url_join, _is_selectable, _get_version_path
 
 # PIL import
 if STRICT_PIL:
@@ -27,10 +33,11 @@ def filesystem_encoding(ucode):
     ucode = urllib.quote(ucode)
     return ucode
 
+
 class FileObject(object):
     """
     The FileObject represents a File on the Server.
-    
+
     PATH has to be relative to MEDIA_ROOT.
     """
 
@@ -38,7 +45,7 @@ class FileObject(object):
         self.path = path
         self.head = os.path.split(path)[0]
         self.filename = os.path.split(path)[1]
-        self.filename_lower = self.filename.lower() # important for sorting
+        self.filename_lower = self.filename.lower()  # important for sorting
         self.filetype = _get_file_type(self.filename)
 
     def _filesize(self):
@@ -205,6 +212,3 @@ class FileObject(object):
 
     def __unicode__(self):
         return u"%s" % self.url_save
-
-
-
index 070fa2d..5297889 100644 (file)
@@ -1,4 +1,4 @@
-# coding: utf-8
+# -*- coding: utf-8
 
 from django.contrib.sessions.models import Session
 from django.shortcuts import get_object_or_404, render_to_response
@@ -12,7 +12,7 @@ def flash_login_required(function):
     Decorator to recognize a user  by its session.
     Used for Flash-Uploading.
     """
-    
+
     def decorator(request, *args, **kwargs):
         try:
             engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
@@ -25,5 +25,3 @@ def flash_login_required(function):
         request.user = get_object_or_404(User, pk=user_id)
         return function(request, *args, **kwargs)
     return decorator
-
-
index 59de825..57bec8e 100644 (file)
@@ -1,4 +1,4 @@
-# coding: utf-8
+# -*- coding: utf-8
 
 import os
 from django.conf import settings
@@ -42,7 +42,7 @@ EXTENSIONS = getattr(settings, "FILEBROWSER_EXTENSIONS", {
     'Video': ['.mov', '.wmv', '.mpeg', '.mpg', '.avi', '.rm'],
     'Document': ['.pdf', '.doc', '.rtf', '.txt', '.xls', '.csv'],
     'Sound': ['.mp3', '.mp4', '.wav', '.aiff', '.midi', '.m4p'],
-    'Code': ['.html', '.py', '.js', '.css']
+    'Code': ['.html', '.py', '.js', '.css'],
 })
 
 # Define different formats for allowed selections.
@@ -107,5 +107,3 @@ _('Video')
 _('Document')
 _('Sound')
 _('Code')
-
-
index 85e981b..78419cd 100644 (file)
@@ -1,4 +1,4 @@
-# coding: utf-8
+# -*- coding: utf-8
 
 import os
 
@@ -16,12 +16,13 @@ from filebrowser.functions import _url_to_path, _dir_from_url, _get_version_path
 from filebrowser.fb_settings import *
 from filebrowser.base import FileObject
 
+
 class FileBrowseWidget(Input):
     input_type = 'text'
-    
+
     class Media:
-        js = (os.path.join(URL_FILEBROWSER_MEDIA, 'js/AddFileBrowser.js'), )
-    
+        js = (os.path.join(URL_FILEBROWSER_MEDIA, 'js/AddFileBrowser.js'),)
+
     def __init__(self, attrs=None):
         self.directory = attrs.get('directory', '')
         self.extensions = attrs.get('extensions', '')
@@ -30,7 +31,7 @@ class FileBrowseWidget(Input):
             self.attrs = attrs.copy()
         else:
             self.attrs = {}
-    
+
     def render(self, name, value, attrs=None):
         if value is None:
             value = ""
@@ -47,15 +48,15 @@ class FileBrowseWidget(Input):
             except:
                 pass
         return render_to_string("filebrowser/custom_field.html", locals())
-    
+
 
 class FileBrowseFormField(forms.CharField):
     widget = FileBrowseWidget
-    
+
     default_error_messages = {
         'extension': _(u'Extension %(ext)s is not allowed. Only %(allowed)s is allowed.'),
     }
-    
+
     def __init__(self, max_length=None, min_length=None,
                  directory=None, extensions=None, format=None,
                  *args, **kwargs):
@@ -66,7 +67,7 @@ class FileBrowseFormField(forms.CharField):
             self.format = format or ''
             self.extensions = extensions or EXTENSIONS.get(format)
         super(FileBrowseFormField, self).__init__(*args, **kwargs)
-    
+
     def clean(self, value):
         value = super(FileBrowseFormField, self).clean(value)
         if value == '':
@@ -75,34 +76,33 @@ class FileBrowseFormField(forms.CharField):
         if self.extensions and not file_extension in self.extensions:
             raise forms.ValidationError(self.error_messages['extension'] % {'ext': file_extension, 'allowed': ", ".join(self.extensions)})
         return value
-    
+
 
 class FileBrowseField(Field):
     __metaclass__ = models.SubfieldBase
-    
+
     def __init__(self, *args, **kwargs):
         self.directory = kwargs.pop('directory', '')
         self.extensions = kwargs.pop('extensions', '')
         self.format = kwargs.pop('format', '')
         return super(FileBrowseField, self).__init__(*args, **kwargs)
-    
+
     def to_python(self, value):
         if not value or isinstance(value, FileObject):
             return value
         return FileObject(_url_to_path(value))
-    
+
     def get_db_prep_value(self, value):
         if value is None:
             return None
         return unicode(value)
-        
-    
+
     def get_manipulator_field_objs(self):
         return [oldforms.TextField]
-    
+
     def get_internal_type(self):
         return "CharField"
-    
+
     def formfield(self, **kwargs):
         attrs = {}
         attrs["directory"] = self.directory
@@ -113,9 +113,7 @@ class FileBrowseField(Field):
             'widget': FileBrowseWidget(attrs=attrs),
             'directory': self.directory,
             'extensions': self.extensions,
-            'format': self.format
+            'format': self.format,
         }
         defaults.update(kwargs)
         return super(FileBrowseField, self).formfield(**defaults)
-    
-
index eef418c..465c2bd 100644 (file)
@@ -1,6 +1,7 @@
 # coding: utf-8
 
-import re, os
+import os
+import re
 
 from django import forms
 from django.forms.formsets import BaseFormSet
@@ -12,18 +13,19 @@ from filebrowser.functions import _get_file_type, _convert_filename
 
 alnum_name_re = re.compile(r'^[\sa-zA-Z0-9._/-]+$')
 
+
 class MakeDirForm(forms.Form):
     """
     Form for creating Directory.
     """
-    
+
     def __init__(self, path, *args, **kwargs):
         self.path = path
         super(MakeDirForm, self).__init__(*args, **kwargs)
-        
-    dir_name = forms.CharField(widget=forms.TextInput(attrs=dict({ 'class': 'vTextField' }, max_length=50, min_length=3)), label=_(u'Name'), help_text=_(u'Only letters, numbers, underscores, spaces and hyphens are allowed.'), required=True)
-    
-    def clean_dir_name(self):   
+
+    dir_name = forms.CharField(widget=forms.TextInput(attrs=dict({'class': 'vTextField'}, max_length=50, min_length=3)), label=_(u'Name'), help_text=_(u'Only letters, numbers, underscores, spaces and hyphens are allowed.'), required=True)
+
+    def clean_dir_name(self):
         if self.cleaned_data['dir_name']:
             # only letters, numbers, underscores, spaces and hyphens are allowed.
             if not alnum_name_re.search(self.cleaned_data['dir_name']):
@@ -32,20 +34,20 @@ class MakeDirForm(forms.Form):
             if os.path.isdir(os.path.join(self.path, _convert_filename(self.cleaned_data['dir_name']))):
                 raise forms.ValidationError(_(u'The Folder already exists.'))
         return _convert_filename(self.cleaned_data['dir_name'])
-    
+
 
 class RenameForm(forms.Form):
     """
     Form for renaming File/Directory.
     """
-    
+
     def __init__(self, path, file_extension, *args, **kwargs):
         self.path = path
         self.file_extension = file_extension
         super(RenameForm, self).__init__(*args, **kwargs)
-    
-    name = forms.CharField(widget=forms.TextInput(attrs=dict({ 'class': 'vTextField' }, max_length=50, min_length=3)), label=_(u'New Name'), help_text=_('Only letters, numbers, underscores, spaces and hyphens are allowed.'), required=True)
-    
+
+    name = forms.CharField(widget=forms.TextInput(attrs=dict({'class': 'vTextField'}, max_length=50, min_length=3)), label=_(u'New Name'), help_text=_('Only letters, numbers, underscores, spaces and hyphens are allowed.'), required=True)
+
     def clean_name(self):
         if self.cleaned_data['name']:
             # only letters, numbers, underscores, spaces and hyphens are allowed.
@@ -55,5 +57,3 @@ class RenameForm(forms.Form):
             if os.path.isdir(os.path.join(self.path, _convert_filename(self.cleaned_data['name']))) or os.path.isfile(os.path.join(self.path, _convert_filename(self.cleaned_data['name']) + self.file_extension)):
                 raise forms.ValidationError(_(u'The File/Folder already exists.'))
         return _convert_filename(self.cleaned_data['name'])
-    
-
index afcdffd..c8cde3f 100644 (file)
@@ -1,11 +1,15 @@
-# coding: utf-8
+# -*- coding: utf-8
+
+import os
+import re
+import decimal
 
 from django.utils.translation import ugettext as _
 from django.utils.safestring import mark_safe
 from time import gmtime, strftime, localtime, mktime, time
 from django.core.files import File
 from django.core.files.storage import default_storage
-import os, re, decimal
+
 from urlparse import urlparse
 
 # filebrowser imports
@@ -25,7 +29,7 @@ def _url_to_path(value):
     """
     Change URL to PATH.
     Value has to be an URL relative to MEDIA URL or a full URL (including MEDIA_URL).
-    
+
     Returns a PATH relative to MEDIA_ROOT.
     """
     print "URL2PATH", repr(value)
@@ -38,7 +42,7 @@ def _path_to_url(value):
     """
     Change PATH to URL.
     Value has to be a PATH relative to MEDIA_ROOT.
-    
+
     Return an URL relative to MEDIA_ROOT.
     """
     mediaroot_re = re.compile(r'^(%s)' % (MEDIA_ROOT))
@@ -64,7 +68,7 @@ def _get_version_path(value, version_prefix):
     """
     Construct the PATH to an Image version.
     Value has to be server-path, relative to MEDIA_ROOT.
-    
+
     version_filename = filename + version_prefix + ext
     Returns a path relative to MEDIA_ROOT.
     """
@@ -135,16 +139,23 @@ def _get_filterdate(filterDate, dateTime):
     Get filterdate.
     """
 
-    returnvalue = ''
     dateYear = strftime("%Y", gmtime(dateTime))
     dateMonth = strftime("%m", gmtime(dateTime))
     dateDay = strftime("%d", gmtime(dateTime))
-    if filterDate == 'today' and int(dateYear) == int(localtime()[0]) and int(dateMonth) == int(localtime()[1]) and int(dateDay) == int(localtime()[2]): returnvalue = 'true'
-    elif filterDate == 'thismonth' and dateTime >= time() - 2592000: returnvalue = 'true'
-    elif filterDate == 'thisyear' and int(dateYear) == int(localtime()[0]): returnvalue = 'true'
-    elif filterDate == 'past7days' and dateTime >= time() - 604800: returnvalue = 'true'
-    elif filterDate == '': returnvalue = 'true'
-    return returnvalue
+
+    if filterDate == 'today' and int(dateYear) == int(localtime()[0]) and int(dateMonth) == int(localtime()[1]) and int(dateDay) == int(localtime()[2]):
+        return 'true'
+
+    if filterDate == 'thismonth' and dateTime >= time() - 2592000:
+        return 'true'
+
+    if filterDate == 'thisyear' and int(dateYear) == int(localtime()[0]):
+        return 'true'
+
+    if filterDate == 'past7days' and dateTime >= time() - 604800:
+        return 'true'
+
+    return 'true' if filterDate == '' else ''
 
 
 def _get_settings_var():
@@ -214,7 +225,7 @@ def _is_selectable(filename, selecttype):
     return select_types
 
 
-def _version_generator(value, version_prefix, force = None):
+def _version_generator(value, version_prefix, force=None):
     """
     Generate Version for an Image.
     value has to be a serverpath relative to MEDIA_ROOT.
@@ -229,7 +240,7 @@ def _version_generator(value, version_prefix, force = None):
             from PIL import ImageFile
         except ImportError:
             import ImageFile
-    ImageFile.MAXBLOCK = IMAGE_MAXBLOCK # default is 64k
+    ImageFile.MAXBLOCK = IMAGE_MAXBLOCK  # default is 64k
 
     try:
         im = Image.open(os.path.join(MEDIA_ROOT, value))
@@ -241,9 +252,9 @@ def _version_generator(value, version_prefix, force = None):
             os.chmod(version_dir, 0775)
         version = scale_and_crop(im, VERSIONS[version_prefix]['width'], VERSIONS[version_prefix]['height'], VERSIONS[version_prefix]['opts'])
         try:
-            version.save(absolute_version_path, quality = 90, optimize = 1)
+            version.save(absolute_version_path, quality=90, optimize=1)
         except IOError:
-            version.save(absolute_version_path, quality = 90)
+            version.save(absolute_version_path, quality=90)
         return version_path
     except:
         return None
@@ -266,7 +277,7 @@ def scale_and_crop(im, width, height, opts):
         r = min(xr / x, yr / y)
 
     if r < 1.0 or (r > 1.0 and 'upscale' in opts):
-        im = im.resize((int(x * r), int(y * r)), resample = Image.ANTIALIAS)
+        im = im.resize((int(x * r), int(y * r)), resample=Image.ANTIALIAS)
 
     if 'crop' in opts:
         x, y = [float(v) for v in im.size]
@@ -282,6 +293,3 @@ def _convert_filename(value):
         return value.replace(" ", "_").lower()
     else:
         return value
-
-
-
index a11084e..655d082 100644 (file)
@@ -1 +1 @@
-# This file is only necessary for the tests to work
\ No newline at end of file
+# This file is only necessary for the tests to work
index 3733485..21aed14 100644 (file)
@@ -8,13 +8,14 @@ from filebrowser.fb_settings import SELECT_FORMATS
 
 register = template.Library()
 
-@register.inclusion_tag('filebrowser/include/_response.html', takes_context = True)
-def query_string(context, add = None, remove = None):
+
+@register.inclusion_tag('filebrowser/include/_response.html', takes_context=True)
+def query_string(context, add=None, remove=None):
     """
     Allows the addition and removal of query string parameters.
-    
+
     _response.html is just {{ response }}
-    
+
     Usage:
     http://www.url.com/{% query_string "param_to_add=value, param_to_add=value" "param_to_remove, params_to_remove" %}
     http://www.url.com/{% query_string "" "filter" %}filter={{new_filter}}
@@ -25,10 +26,10 @@ def query_string(context, add = None, remove = None):
     remove = string_to_list(remove)
     params = context['query'].copy()
     response = get_query_string(params, add, remove)
-    return {'response': smart_unicode(response) }
+    return {'response': smart_unicode(response)}
 
 
-def query_helper(query, add = None, remove = None):
+def query_helper(query, add=None, remove=None):
     """
     Helper Function for use within views.
     """
@@ -38,12 +39,16 @@ def query_helper(query, add = None, remove = None):
     return get_query_string(params, add, remove)
 
 
-def get_query_string(p, new_params = None, remove = None):
+def get_query_string(p, new_params=None, remove=None):
     """
     Add and remove query parameters. From `django.contrib.admin`.
     """
-    if new_params is None: new_params = {}
-    if remove is None: remove = []
+    if new_params is None:
+        new_params = {}
+
+    if remove is None:
+        remove = []
+
     for r in remove:
         for k in p.keys():
             if k.startswith(r):
@@ -59,29 +64,26 @@ def get_query_string(p, new_params = None, remove = None):
 def string_to_dict(string):
     """
     Usage::
-    
+
         {{ url|thumbnail:"width=10,height=20" }}
         {{ url|thumbnail:"width=10" }}
         {{ url|thumbnail:"height=20" }}
     """
     kwargs = {}
+
     if string:
         string = str(string)
-        if ',' not in string:
-            # ensure at least one ','
-            string += ','
-        for arg in string.split(','):
-            arg = arg.strip()
-            if arg == '': continue
-            kw, val = arg.split('=', 1)
-            kwargs[kw] = val
+
+        args = (arg.strip() for arg in string.split(',') if not arg.iswhitespace())
+        kwargs.update(arg.split('=', 1) for arg in args)
+
     return kwargs
 
 
 def string_to_list(string):
     """
     Usage::
-    
+
         {{ url|thumbnail:"width,height" }}
     """
     args = []
@@ -92,7 +94,8 @@ def string_to_list(string):
             string += ','
         for arg in string.split(','):
             arg = arg.strip()
-            if arg == '': continue
+            if arg == '':
+                continue
             args.append(arg)
     return args
 
@@ -126,7 +129,7 @@ def selectable(parser, token):
     try:
         tag, filetype, format = token.split_contents()
     except:
-        raise TemplateSyntaxError, "%s tag requires 2 arguments" % token.contents.split()[0]
+        raise TemplateSyntaxError("%s tag requires 2 arguments" % token.contents.split()[0])
 
     return SelectableNode(filetype, format)
 
index cdb0519..cb67b2f 100644 (file)
@@ -1,19 +1,22 @@
 # coding: utf-8
 
-import os, re
-from time import gmtime
+import os
+import re
 from django.template import Library, Node, Variable, VariableDoesNotExist, TemplateSyntaxError
 from django.conf import settings
 from django.utils.encoding import force_unicode
-import urllib
 
 # filebrowser imports
 from filebrowser.fb_settings import MEDIA_ROOT, MEDIA_URL, VERSIONS
 from filebrowser.functions import _url_to_path, _path_to_url, _get_version_path, _version_generator
 from filebrowser.base import FileObject
 
+import logging
+logger = logging.getLogger("django.filebrowser")
+
 register = Library()
 
+
 class VersionNode(Node):
     def __init__(self, src, version_prefix):
         self.src = Variable(src)
@@ -44,37 +47,35 @@ class VersionNode(Node):
                 version_path = _version_generator(_url_to_path(str(source)), version_prefix)
             elif os.path.getmtime(os.path.join(MEDIA_ROOT, _url_to_path(str(source)))) > os.path.getmtime(os.path.join(MEDIA_ROOT, version_path)):
                 # recreate version if original image was updated
-                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force = True)
+                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force=True)
             return _path_to_url(version_path)
-        except Exception, e:
-            import traceback, sys
-            print "FB VERSION ERROR"
-            traceback.print_exc(file = sys.stdout)
+        except Exception:
+            logger.exception("Version error")
             return u""
 
 
-
 def version(parser, token):
     """
     Displaying a version of an existing Image according to the predefined VERSIONS settings (see fb_settings).
     {% version field_name version_prefix %}
-    
+
     Use {% version my_image 'medium' %} in order to display the medium-size
     version of an Image stored in a field name my_image.
-    
+
     version_prefix can be a string or a variable. if version_prefix is a string, use quotes.
     """
 
     try:
         tag, src, version_prefix = token.split_contents()
     except:
-        raise TemplateSyntaxError, "%s tag requires 2 arguments" % token.contents.split()[0]
+        raise TemplateSyntaxError("%s tag requires 2 arguments" % token.contents.split()[0])
     if (version_prefix[0] == version_prefix[-1] and version_prefix[0] in ('"', "'")) and version_prefix.lower()[1:-1] not in VERSIONS:
-        raise TemplateSyntaxError, "%s tag received bad version_prefix %s" % (tag, version_prefix)
+        raise TemplateSyntaxError("%s tag received bad version_prefix %s" % (tag, version_prefix))
     return VersionNode(src, version_prefix)
 
 
 class VersionObjectNode(Node):
+
     def __init__(self, src, version_prefix, var_name):
         self.var_name = var_name
         self.src = Variable(src)
@@ -103,7 +104,7 @@ class VersionObjectNode(Node):
                 version_path = _version_generator(_url_to_path(str(source)), version_prefix)
             elif os.path.getmtime(os.path.join(MEDIA_ROOT, _url_to_path(str(source)))) > os.path.getmtime(os.path.join(MEDIA_ROOT, version_path)):
                 # recreate version if original image was updated
-                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force = True)
+                version_path = _version_generator(_url_to_path(str(source)), version_prefix, force=True)
             context[self.var_name] = FileObject(version_path)
         except:
             context[self.var_name] = ""
@@ -114,12 +115,12 @@ def version_object(parser, token):
     """
     Returns a context variable 'version_object'.
     {% version_object field_name version_prefix %}
-    
+
     Use {% version_object my_image 'medium' %} in order to retrieve the medium
     version of an Image stored in a field name my_image.
     Use {% version_object my_image 'medium' as var %} in order to use 'var' as
     your context variable.
-    
+
     version_prefix can be a string or a variable. if version_prefix is a string, use quotes.
     """
 
@@ -127,17 +128,18 @@ def version_object(parser, token):
         #tag, src, version_prefix = token.split_contents()
         tag, arg = token.contents.split(None, 1)
     except:
-        raise TemplateSyntaxError, "%s tag requires arguments" % token.contents.split()[0]
+        raise TemplateSyntaxError("%s tag requires arguments" % token.contents.split()[0])
     m = re.search(r'(.*?) (.*?) as (\w+)', arg)
     if not m:
-        raise TemplateSyntaxError, "%r tag had invalid arguments" % tag
+        raise TemplateSyntaxError("%r tag had invalid arguments" % tag)
     src, version_prefix, var_name = m.groups()
     if (version_prefix[0] == version_prefix[-1] and version_prefix[0] in ('"', "'")) and version_prefix.lower()[1:-1] not in VERSIONS:
-        raise TemplateSyntaxError, "%s tag received bad version_prefix %s" % (tag, version_prefix)
+        raise TemplateSyntaxError("%s tag received bad version_prefix %s" % (tag, version_prefix))
     return VersionObjectNode(src, version_prefix, var_name)
 
 
 class VersionSettingNode(Node):
+
     def __init__(self, version_prefix):
         if (version_prefix[0] == version_prefix[-1] and version_prefix[0] in ('"', "'")):
             self.version_prefix = version_prefix[1:-1]
@@ -165,14 +167,12 @@ def version_setting(parser, token):
     try:
         tag, version_prefix = token.split_contents()
     except:
-        raise TemplateSyntaxError, "%s tag requires 1 argument" % token.contents.split()[0]
+        raise TemplateSyntaxError("%s tag requires 1 argument" % token.contents.split()[0])
     if (version_prefix[0] == version_prefix[-1] and version_prefix[0] in ('"', "'")) and version_prefix.lower()[1:-1] not in VERSIONS:
-        raise TemplateSyntaxError, "%s tag received bad version_prefix %s" % (tag, version_prefix)
+        raise TemplateSyntaxError("%s tag received bad version_prefix %s" % (tag, version_prefix))
     return VersionSettingNode(version_prefix)
 
 
 register.tag(version)
 register.tag(version_object)
 register.tag(version_setting)
-
-
index 5cfc259..60bfff8 100644 (file)
@@ -1,7 +1,7 @@
 from django.conf.urls.defaults import *
 
 urlpatterns = patterns('',
-    
+
     # filebrowser urls
     url(r'^browse/$', 'filebrowser.views.browse', name="fb_browse"),
     url(r'^mkdir/', 'filebrowser.views.mkdir', name="fb_mkdir"),
@@ -9,7 +9,7 @@ urlpatterns = patterns('',
     url(r'^rename/$', 'filebrowser.views.rename', name="fb_rename"),
     url(r'^delete/$', 'filebrowser.views.delete', name="fb_delete"),
     url(r'^versions/$', 'filebrowser.views.versions', name="fb_versions"),
-    
+
     url(r'^check_file/$', 'filebrowser.views._check_file', name="fb_check"),
     url(r'^upload_file/$', 'filebrowser.views._upload_file', name="fb_do_upload"),
 
index 30869a4..7870b9d 100644 (file)
@@ -1,8 +1,7 @@
 # coding: utf-8
 
 # general imports
-import os, re, locale
-from time import gmtime, strftime
+import re
 
 # django imports
 from django.shortcuts import render_to_response, HttpResponse
@@ -21,15 +20,21 @@ from django.utils.encoding import smart_unicode, smart_str
 
 # filebrowser imports
 from filebrowser.fb_settings import *
-from filebrowser.functions import _url_to_path, _path_to_url, _get_path, _get_file, _get_version_path, _get_breadcrumbs, _get_filterdate, _get_settings_var, _handle_file_upload, _get_file_type, _url_join, _convert_filename
+
+from filebrowser.functions import (
+        _url_to_path, _path_to_url, _get_path, _get_file, _get_version_path,
+        _get_breadcrumbs, _get_filterdate, _get_settings_var, _handle_file_upload,
+        _get_file_type, _url_join, _convert_filename)
+
 from filebrowser.templatetags.fb_tags import query_helper
 from filebrowser.base import FileObject
 from filebrowser.decorators import flash_login_required
 
 # Precompile regular expressions
 filter_re = []
+
 for exp in EXCLUDE:
-   filter_re.append(re.compile(exp))
+    filter_re.append(re.compile(exp))
 for k, v in VERSIONS.iteritems():
     exp = (r'_%s.(%s)') % (k, '|'.join(EXTENSION_LIST))
     filter_re.append(re.compile(exp))
@@ -47,16 +52,16 @@ def browse(request):
 
     if path is None:
         msg = _('Directory/File does not exist.')
-        request.user.message_set.create(message = msg)
+        request.user.message_set.create(message=msg)
         if directory is None:
             # The DIRECTORY does not exist, raise an error to prevent eternal redirecting.
-            raise ImproperlyConfigured, _("Error finding upload directory. Maybe it does not exist?")
+            raise ImproperlyConfigured(_("Error finding upload directory. Maybe it does not exist?"))
         redirect_url = reverse("fb_browse") + query_helper(query, "", "dir")
         return HttpResponseRedirect(redirect_url)
     abs_path = os.path.join(MEDIA_ROOT, DIRECTORY, path)
 
     # INITIAL VARIABLES
-    results_var = {'results_total': 0, 'results_current': 0, 'delete_total': 0, 'images_total': 0, 'select_total': 0 }
+    results_var = {'results_total': 0, 'results_current': 0, 'delete_total': 0, 'images_total': 0, 'select_total': 0}
     counter = {}
     for k, v in EXTENSIONS.iteritems():
         counter[k] = 0
@@ -106,7 +111,7 @@ def browse(request):
             counter[fileobject.filetype] += 1
 
     # SORTING
-    files.sort(key = lambda e: getattr(e, request.GET.get('o', DEFAULT_ORDER)))
+    files.sort(key=lambda e: getattr(e, request.GET.get('o', DEFAULT_ORDER)))
     if request.GET.get('ot') == "desc":
         files.reverse()
 
@@ -119,13 +124,14 @@ def browse(request):
         'title': _(u'FileBrowser'),
         'settings_var': _get_settings_var(),
         'breadcrumbs': _get_breadcrumbs(query, path, ''),
-    }, context_instance = Context(request))
+    }, context_instance=Context(request))
 browse = staff_member_required(never_cache(browse))
 
 
 # mkdir signals
-filebrowser_pre_createdir = Signal(providing_args = ["path", "dirname"])
-filebrowser_post_createdir = Signal(providing_args = ["path", "dirname"])
+filebrowser_pre_createdir = Signal(providing_args=["path", "dirname"])
+filebrowser_post_createdir = Signal(providing_args=["path", "dirname"])
+
 
 def mkdir(request):
     """
@@ -139,7 +145,7 @@ def mkdir(request):
     path = _get_path(query.get('dir', ''))
     if path is None:
         msg = _('Directory/File does not exist.')
-        request.user.message_set.create(message = msg)
+        request.user.message_set.create(message=msg)
         return HttpResponseRedirect(reverse("fb_browse"))
     abs_path = os.path.join(MEDIA_ROOT, DIRECTORY, path)
 
@@ -149,15 +155,15 @@ def mkdir(request):
             server_path = os.path.join(abs_path, form.cleaned_data['dir_name'])
             try:
                 # PRE CREATE SIGNAL
-                filebrowser_pre_createdir.send(sender = request, path = path, dirname = form.cleaned_data['dir_name'])
+                filebrowser_pre_createdir.send(sender=request, path=path, dirname=form.cleaned_data['dir_name'])
                 # CREATE FOLDER
                 os.mkdir(server_path)
                 os.chmod(server_path, 0775)
                 # POST CREATE SIGNAL
-                filebrowser_post_createdir.send(sender = request, path = path, dirname = form.cleaned_data['dir_name'])
+                filebrowser_post_createdir.send(sender=request, path=path, dirname=form.cleaned_data['dir_name'])
                 # MESSAGE & REDIRECT
                 msg = _('The Folder %s was successfully created.') % (form.cleaned_data['dir_name'])
-                request.user.message_set.create(message = msg)
+                request.user.message_set.create(message=msg)
                 # on redirect, sort by date desc to see the new directory on top of the list
                 # remove filter in order to actually _see_ the new folder
                 redirect_url = reverse("fb_browse") + query_helper(query, "ot=desc,o=date", "ot,o,filter_type,filter_date,q")
@@ -176,7 +182,7 @@ def mkdir(request):
         'title': _(u'New Folder'),
         'settings_var': _get_settings_var(),
         'breadcrumbs': _get_breadcrumbs(query, path, _(u'New Folder')),
-    }, context_instance = Context(request))
+    }, context_instance=Context(request))
 mkdir = staff_member_required(never_cache(mkdir))
 
 
@@ -192,7 +198,7 @@ def upload(request):
     path = _get_path(query.get('dir', ''))
     if path is None:
         msg = _('Directory/File does not exist.')
-        request.user.message_set.create(message = msg)
+        request.user.message_set.create(message=msg)
         return HttpResponseRedirect(reverse("fb_browse"))
     abs_path = os.path.join(MEDIA_ROOT, DIRECTORY, path)
 
@@ -207,7 +213,7 @@ def upload(request):
         'settings_var': _get_settings_var(),
         'breadcrumbs': _get_breadcrumbs(query, path, _(u'Upload')),
         'session_key': session_key,
-    }, context_instance = Context(request))
+    }, context_instance=Context(request))
 upload = staff_member_required(never_cache(upload))
 
 
@@ -234,8 +240,9 @@ def _check_file(request):
 
 
 # upload signals
-filebrowser_pre_upload = Signal(providing_args = ["path", "file"])
-filebrowser_post_upload = Signal(providing_args = ["path", "file"])
+filebrowser_pre_upload = Signal(providing_args=["path", "file"])
+filebrowser_post_upload = Signal(providing_args=["path", "file"])
+
 
 def _upload_file(request):
     """
@@ -253,7 +260,7 @@ def _upload_file(request):
             filedata = request.FILES['Filedata']
             filedata.name = _convert_filename(filedata.name)
             # PRE UPLOAD SIGNAL
-            filebrowser_pre_upload.send(sender = request, path = request.POST.get('folder'), file = filedata)
+            filebrowser_pre_upload.send(sender=request, path=request.POST.get('folder'), file=filedata)
             # HANDLE UPLOAD
             uploadedfile = _handle_file_upload(abs_path, filedata)
             # MOVE UPLOADED FILE
@@ -263,19 +270,20 @@ def _upload_file(request):
                 new_file = os.path.join(abs_path, uploadedfile)
                 file_move_safe(new_file, old_file)
             # POST UPLOAD SIGNAL
-            filebrowser_post_upload.send(sender = request, path = request.POST.get('folder'), file = FileObject(os.path.join(DIRECTORY, folder, filedata.name)))
+            filebrowser_post_upload.send(sender=request, path=request.POST.get('folder'), file=FileObject(os.path.join(DIRECTORY, folder, filedata.name)))
     return HttpResponse('True')
 _upload_file = flash_login_required(_upload_file)
 
 
 # delete signals
-filebrowser_pre_delete = Signal(providing_args = ["path", "filename"])
-filebrowser_post_delete = Signal(providing_args = ["path", "filename"])
+filebrowser_pre_delete = Signal(providing_args=["path", "filename"])
+filebrowser_post_delete = Signal(providing_args=["path", "filename"])
+
 
 def delete(request):
     """
     Delete existing File/Directory.
-    
+
     When trying to delete a Directory, the Directory has to be empty.
     """
 
@@ -285,7 +293,7 @@ def delete(request):
     filename = _get_file(query.get('dir', ''), query.get('filename', ''))
     if path is None or filename is None:
         msg = _('Directory/File does not exist.')
-        request.user.message_set.create(message = msg)
+        request.user.message_set.create(message=msg)
         return HttpResponseRedirect(reverse("fb_browse"))
     abs_path = os.path.join(MEDIA_ROOT, DIRECTORY, path)
 
@@ -295,7 +303,7 @@ def delete(request):
             relative_server_path = os.path.join(DIRECTORY, path, filename)
             try:
                 # PRE DELETE SIGNAL
-                filebrowser_pre_delete.send(sender = request, path = path, filename = filename)
+                filebrowser_pre_delete.send(sender=request, path=path, filename=filename)
                 # DELETE IMAGE VERSIONS/THUMBNAILS
                 for version in VERSIONS:
                     try:
@@ -305,10 +313,10 @@ def delete(request):
                 # DELETE FILE
                 os.unlink(os.path.join(abs_path, filename))
                 # POST DELETE SIGNAL
-                filebrowser_post_delete.send(sender = request, path = path, filename = filename)
+                filebrowser_post_delete.send(sender=request, path=path, filename=filename)
                 # MESSAGE & REDIRECT
                 msg = _('The file %s was successfully deleted.') % (filename.lower())
-                request.user.message_set.create(message = msg)
+                request.user.message_set.create(message=msg)
                 redirect_url = reverse("fb_browse") + query_helper(query, "", "filename,filetype")
                 return HttpResponseRedirect(redirect_url)
             except OSError:
@@ -317,14 +325,14 @@ def delete(request):
         else:
             try:
                 # PRE DELETE SIGNAL
-                filebrowser_pre_delete.send(sender = request, path = path, filename = filename)
+                filebrowser_pre_delete.send(sender=request, path=path, filename=filename)
                 # DELETE FOLDER
                 os.rmdir(os.path.join(abs_path, filename))
                 # POST DELETE SIGNAL
-                filebrowser_post_delete.send(sender = request, path = path, filename = filename)
+                filebrowser_post_delete.send(sender=request, path=path, filename=filename)
                 # MESSAGE & REDIRECT
                 msg = _('The directory %s was successfully deleted.') % (filename.lower())
-                request.user.message_set.create(message = msg)
+                request.user.message_set.create(message=msg)
                 redirect_url = reverse("fb_browse") + query_helper(query, "", "filename,filetype")
                 return HttpResponseRedirect(redirect_url)
             except OSError:
@@ -332,7 +340,7 @@ def delete(request):
                 msg = OSError
 
     if msg:
-        request.user.message_set.create(message = msg)
+        request.user.message_set.create(message=msg)
 
     return render_to_response('filebrowser/index.html', {
         'dir': dir_name,
@@ -340,18 +348,19 @@ def delete(request):
         'query': query,
         'settings_var': _get_settings_var(),
         'breadcrumbs': _get_breadcrumbs(query, dir_name, ''),
-    }, context_instance = Context(request))
+    }, context_instance=Context(request))
 delete = staff_member_required(never_cache(delete))
 
 
 # delete signals
-filebrowser_pre_rename = Signal(providing_args = ["path", "filename"])
-filebrowser_post_rename = Signal(providing_args = ["path", "filename"])
+filebrowser_pre_rename = Signal(providing_args=["path", "filename"])
+filebrowser_post_rename = Signal(providing_args=["path", "filename"])
+
 
 def rename(request):
     """
     Rename existing File/Directory.
-    
+
     Includes renaming existing Image Versions/Thumbnails.
     """
 
@@ -363,7 +372,7 @@ def rename(request):
     filename = _get_file(query.get('dir', ''), query.get('filename', ''))
     if path is None or filename is None:
         msg = _('Directory/File does not exist.')
-        request.user.message_set.create(message = msg)
+        request.user.message_set.create(message=msg)
         return HttpResponseRedirect(reverse("fb_browse"))
     abs_path = os.path.join(MEDIA_ROOT, DIRECTORY, path)
     file_extension = os.path.splitext(filename)[1].lower()
@@ -375,7 +384,7 @@ def rename(request):
             new_relative_server_path = os.path.join(DIRECTORY, path, form.cleaned_data['name'] + file_extension)
             try:
                 # PRE RENAME SIGNAL
-                filebrowser_pre_delete.send(sender = request, path = path, filename = filename)
+                filebrowser_pre_delete.send(sender=request, path=path, filename=filename)
                 # DELETE IMAGE VERSIONS/THUMBNAILS
                 # regenerating versions/thumbs will be done automatically
                 for version in VERSIONS:
@@ -386,10 +395,10 @@ def rename(request):
                 # RENAME ORIGINAL
                 os.rename(os.path.join(MEDIA_ROOT, relative_server_path), os.path.join(MEDIA_ROOT, new_relative_server_path))
                 # POST RENAME SIGNAL
-                filebrowser_post_delete.send(sender = request, path = path, filename = filename)
+                filebrowser_post_delete.send(sender=request, path=path, filename=filename)
                 # MESSAGE & REDIRECT
                 msg = _('Renaming was successful.')
-                request.user.message_set.create(message = msg)
+                request.user.message_set.create(message=msg)
                 redirect_url = reverse("fb_browse") + query_helper(query, "", "filename")
                 return HttpResponseRedirect(redirect_url)
             except OSError, (errno, strerror):
@@ -404,7 +413,7 @@ def rename(request):
         'title': _(u'Rename "%s"') % filename,
         'settings_var': _get_settings_var(),
         'breadcrumbs': _get_breadcrumbs(query, path, _(u'Rename')),
-    }, context_instance = Context(request))
+    }, context_instance=Context(request))
 rename = staff_member_required(never_cache(rename))
 
 
@@ -419,7 +428,7 @@ def versions(request):
     filename = _get_file(query.get('dir', ''), query.get('filename', ''))
     if path is None or filename is None:
         msg = _('Directory/File does not exist.')
-        request.user.message_set.create(message = msg)
+        request.user.message_set.create(message=msg)
         return HttpResponseRedirect(reverse("fb_browse"))
     abs_path = os.path.join(MEDIA_ROOT, DIRECTORY, path)
 
@@ -429,7 +438,6 @@ def versions(request):
         'title': _(u'Versions for "%s"') % filename,
         'settings_var': _get_settings_var(),
         'breadcrumbs': _get_breadcrumbs(query, path, _(u'Versions for "%s"') % filename),
-    }, context_instance = Context(request))
-versions = staff_member_required(never_cache(versions))
-
+    }, context_instance=Context(request))
 
+versions = staff_member_required(never_cache(versions))
index 7edd26b..6f69fb9 100644 (file)
@@ -5,6 +5,7 @@ from django.utils import simplejson as json
 
 from toolbar import models
 
+
 class ButtonAdminForm(forms.ModelForm):
     class Meta:
         model = models.Button
@@ -16,6 +17,7 @@ class ButtonAdminForm(forms.ModelForm):
         except ValueError, e:
             raise forms.ValidationError(e)
 
+
 class ButtonAdmin(admin.ModelAdmin):
     form = ButtonAdminForm
     list_display = ('slug', 'label', 'tooltip', 'accesskey')
@@ -25,4 +27,4 @@ class ButtonAdmin(admin.ModelAdmin):
 
 admin.site.register(models.Button, ButtonAdmin)
 admin.site.register(models.ButtonGroup)
-admin.site.register(models.Scriptlet)
\ No newline at end of file
+admin.site.register(models.Scriptlet)
index 5ff26b2..792d600 100644 (file)
@@ -1,4 +1 @@
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
-
-
+#
index 7a49b37..ea797fc 100644 (file)
@@ -2,24 +2,24 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
-__author__="lreqc"
-__date__ ="$2009-09-08 14:31:26$"
+
 from django.core.management.base import NoArgsCommand
 from toolbar.models import Button, ButtonGroup
 from django.utils import simplejson as json
 import re
 
+
 class Command(NoArgsCommand):
-    
+
     def handle_noargs(self, **options):
         buttons = Button.objects.all()
         print "Validating parameters... "
         for b in buttons:
-            params = b.params;
+            params = b.params
             try:
-                v = json.loads(b.params)               
+                v = json.loads(b.params)
             except ValueError, e:
                 print 'Trying to fix button "%s" ...' % b.slug
                 if params[0] == u'(':
@@ -43,7 +43,7 @@ class Command(NoArgsCommand):
             if b.slug not in hash:
                 hash[b.slug] = b
                 continue
-                
+
             # duplicate button
             print "Found duplicate of '%s'" % b.slug
             a = hash[b.slug]
@@ -66,8 +66,8 @@ class Command(NoArgsCommand):
         print "Searching for empty groups and orphaned buttons:"
         for g in ButtonGroup.objects.all():
             if len(g.button_set.all()) == 0:
-                print "Empty group: '%s'"  % g.slug
-                
+                print "Empty group: '%s'" % g.slug
+
         for b in Button.objects.all():
             if len(b.group.all()) == 0:
-                print "orphan: '%s'"  % b.slug
+                print "orphan: '%s'" % b.slug
index 974ea66..5a6f27c 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
-        
+
         # Adding model 'ButtonGroup'
         db.create_table('toolbar_buttongroup', (
             ('position', self.gf('django.db.models.fields.IntegerField')(default=0)),
@@ -45,10 +45,10 @@ class Migration(SchemaMigration):
             ('name', self.gf('django.db.models.fields.CharField')(max_length=64, primary_key=True)),
         ))
         db.send_create_signal('toolbar', ['Scriptlet'])
-    
-    
+
+
     def backwards(self, orm):
-        
+
         # Deleting model 'ButtonGroup'
         db.delete_table('toolbar_buttongroup')
 
@@ -60,8 +60,8 @@ class Migration(SchemaMigration):
 
         # Deleting model 'Scriptlet'
         db.delete_table('toolbar_scriptlet')
-    
-    
+
+
     models = {
         'toolbar.button': {
             'Meta': {'object_name': 'Button'},
@@ -89,5 +89,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'})
         }
     }
-    
+
     complete_apps = ['toolbar']
index 09ddd32..af58c6e 100644 (file)
@@ -5,23 +5,23 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
-        
+
         # Deleting field 'Button.key_mod'
         db.delete_column('toolbar_button', 'key_mod')
 
         # Changing field 'Button.key'
         db.alter_column('toolbar_button', 'key', self.gf('django.db.models.fields.CharField')(max_length=1, null=True))
-    
+
     def backwards(self, orm):
-        
+
         # Adding field 'Button.key_mod'
         db.add_column('toolbar_button', 'key_mod', self.gf('django.db.models.fields.PositiveIntegerField')(default=1, blank=True), keep_default=False)
 
         # Changing field 'Button.key'
-        db.alter_column('toolbar_button', 'key', self.gf('django.db.models.fields.CharField')(max_length=1, blank=True))    
-    
+        db.alter_column('toolbar_button', 'key', self.gf('django.db.models.fields.CharField')(max_length=1, blank=True))
+
     models = {
         'toolbar.button': {
             'Meta': {'object_name': 'Button'},
@@ -48,5 +48,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'})
         }
     }
-    
+
     complete_apps = ['toolbar']
index 0d2e906..7a0961d 100644 (file)
@@ -5,18 +5,18 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
-        
+
         # Deleting field 'Button.key'
         db.rename_column('toolbar_button', 'key', 'accesskey')
 
-    
-    
-    def backwards(self, orm):        
+
+
+    def backwards(self, orm):
         db.rename_column('toolbar_button', 'accesskey', 'key')
-    
-    
+
+
     models = {
         'toolbar.button': {
             'Meta': {'object_name': 'Button'},
@@ -43,5 +43,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '64', 'primary_key': 'True'})
         }
     }
-    
+
     complete_apps = ['toolbar']
index d736c02..3c8ff4f 100644 (file)
@@ -1,16 +1,16 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
 
 
 class ButtonGroup(models.Model):
-    name = models.CharField(max_length = 32)
+    name = models.CharField(max_length=32)
     slug = models.SlugField()
-    position = models.IntegerField(default = 0)
+    position = models.IntegerField(default=0)
 
     class Meta:
         ordering = ('position', 'name',)
@@ -19,49 +19,31 @@ class ButtonGroup(models.Model):
     def __unicode__(self):
         return self.name
 
-    def to_dict(self, with_buttons = False):
+    def to_dict(self, with_buttons=False):
         d = {'name': self.name, 'position': self.position}
 
         if with_buttons:
-            d['buttons'] = [ b.to_dict() for b in self.button_set.all() ]
+            d['buttons'] = [b.to_dict() for b in self.button_set.all()]
 
         return d
 
-#class ButtonGroupManager(models.Manager):
-#
-#    def with_buttons(self):
-#        from django.db import connection
-#        cursor = connection.cursor()
-#        cursor.execute("""
-#            SELECT g.name, g.slug, CONCAT(b.slug),
-#            FROM toolbar_buttongroup as g LEFT JOIN toolbar_button as b
-#
-#            WHERE p.id = r.poll_id
-#            GROUP BY 1, 2, 3
-#            ORDER BY 3 DESC""")
-#        result_list = []
-#        for row in cursor.fetchall():
-#            p = self.model(id=row[0], question=row[1], poll_date=row[2])
-#            p.num_responses = row[3]
-#            result_list.append(p)
-#        return result_list
 
 class Button(models.Model):
-    label = models.CharField(max_length = 32)
-    slug = models.SlugField(unique = True) #unused
+    label = models.CharField(max_length=32)
+    slug = models.SlugField(unique=True)  # unused
 
     # behaviour
-    params = models.TextField(default = '[]') # TODO: should be a JSON field
-    scriptlet = models.ForeignKey('Scriptlet', null = True, blank = True)
-    link = models.CharField(max_length = 256, blank = True, default = '')
+    params = models.TextField(default='[]')  # TODO: should be a JSON field
+    scriptlet = models.ForeignKey('Scriptlet', null=True, blank=True)
+    link = models.CharField(max_length=256, blank=True, default='')
 
     # ui related stuff
-    accesskey = models.CharField(null = True, max_length = 1)
-        
-    tooltip = models.CharField(blank = True, max_length = 120)
+    accesskey = models.CharField(null=True, max_length=1)
+
+    tooltip = models.CharField(blank=True, max_length=120)
 
     # Why the button is restricted to have the same position in each group ?
-    # position = models.IntegerField(default=0)   
+    # position = models.IntegerField(default=0)
     group = models.ManyToManyField(ButtonGroup)
 
     class Meta:
@@ -76,16 +58,17 @@ class Button(models.Model):
         return {
             'label': self.label,
             'tooltip': self.tooltip,
-            'accesskey': self.accesskey,            
+            'accesskey': self.accesskey,
             'params': self.params,
-            'scriptlet_id': self.scriptlet_id
+            'scriptlet_id': self.scriptlet_id,
         }
 
     def __unicode__(self):
         return self.label
 
+
 class Scriptlet(models.Model):
-    name = models.CharField(max_length = 64, primary_key = True)
+    name = models.CharField(max_length=64, primary_key=True)
     code = models.TextField()
 
     def __unicode__(self):
index 421709e..0766677 100644 (file)
@@ -1,16 +1,18 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django import template
 from toolbar import models
 
 register = template.Library()
 
+
 @register.inclusion_tag('toolbar/toolbar.html')
 def toolbar():
-    return {'toolbar_groups': models.ButtonGroup.objects.all().select_related() }
+    return {'toolbar_groups': models.ButtonGroup.objects.all().select_related()}
+
 
 @register.inclusion_tag('toolbar/button.html')
 def toolbar_button(b):
index 236c3f0..2bd6e64 100644 (file)
@@ -1,21 +1,21 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django import forms
 from wiki.models import Document, getstorage
-from django.utils.translation import ugettext_lazy as _ 
+from django.utils.translation import ugettext_lazy as _
 
 
 class DocumentForm(forms.Form):
     """ Old form for saving document's text """
-    
+
     name = forms.CharField(widget=forms.HiddenInput)
     text = forms.CharField(widget=forms.Textarea)
     revision = forms.IntegerField(widget=forms.HiddenInput)
     comment = forms.CharField()
-    
+
     def __init__(self, *args, **kwargs):
         document = kwargs.pop('instance', None)
         super(DocumentForm, self).__init__(*args, **kwargs)
@@ -23,65 +23,66 @@ class DocumentForm(forms.Form):
             self.fields['name'].initial = document.name
             self.fields['text'].initial = document.text
             self.fields['revision'].initial = document.revision()
-        
-    def save(self, document_author = 'anonymous'):
+
+    def save(self, document_author='anonymous'):
         storage = getstorage()
-        
+
         document = Document(storage, name=self.cleaned_data['name'], text=self.cleaned_data['text'])
-        
-        storage.put(document, 
-                author = document_author, 
-                comment = self.cleaned_data['comment'],
-                parent =self.cleaned_data['revision'] )
-        
+
+        storage.put(document,
+                author=document_author,
+                comment=self.cleaned_data['comment'],
+                parent=self.cleaned_data['revision'])
+
         return storage.get(self.cleaned_data['name'])
-    
+
+
 class DocumentTagForm(forms.Form):
     TAGS = (
-        ("publish", "Do publikacji"),        
+        ("publish", "Do publikacji"),
     )
-        
-    tag = forms.ChoiceField(choices = TAGS)
-    version = forms.IntegerField(widget = forms.HiddenInput)
+
+    tag = forms.ChoiceField(choices=TAGS)
+    version = forms.IntegerField(widget=forms.HiddenInput)
+
 
 class DocumentTextSaveForm(forms.Form):
-    """ 
+    """
     Form for saving document's text:
-           
+
         * name - document's storage identifier.
         * parent_revision - revision which the modified text originated from.
         * comment - user's verbose comment; will be used in commit.
         * stage_completed - mark this change as end of given stage.
-               
+
     """
     DOC_STAGES = (
         ('', 'Nic konkretnego'),
         ('tagging', 'Tagowanie'),
         ('modernized', 'Uwspółcześnienia'),
         ('editing', 'Redakcja'),
-    )    
-                
+    )
+
     id = forms.CharField(widget=forms.HiddenInput)
     parent_revision = forms.IntegerField(widget=forms.HiddenInput)
     text = forms.CharField(widget=forms.HiddenInput)
-    
+
     author = forms.CharField(
-        required = False,
-        label = _(u"Autor"),
-        help_text = _(u"Twoje imie i nazwisko lub email.")
+        required=False,
+        label=_(u"Autor"),
+        help_text=_(u"Twoje imie i nazwisko lub email."),
     )
-    
+
     comment = forms.CharField(
-        required = True, 
+        required=True,
         widget=forms.Textarea,
-        label = _(u"Twój komentarz"),
-        help_text = _(u"Opisz w miarę dokładnie swoje zmiany."), 
+        label=_(u"Twój komentarz"),
+        help_text=_(u"Opisz w miarę dokładnie swoje zmiany."),
     )
-    
+
     stage_completed = forms.ChoiceField(
-        choices=DOC_STAGES, 
-        required= False,        
-        label = _(u"Skończyłem robić"),
-        help_text = _(u"Jeśli skończyłeś jeden z etapów utworu, wybierz go."),
+        choices=DOC_STAGES,
+        required=False,
+        label=_(u"Skończyłem robić"),
+        help_text=_(u"Jeśli skończyłeś jeden z etapów utworu, wybierz go."),
     )
-    
\ No newline at end of file
index 7ed97b4..d4daf1a 100644 (file)
@@ -4,38 +4,38 @@ from django.utils.functional import Promise
 from django.template.loader import render_to_string
 from datetime import datetime
 
+
 class ExtendedEncoder(json.JSONEncoder):
 
     def default(self, obj):
         if isinstance(obj, Promise):
-            return unicode(obj)  
-            
+            return unicode(obj)
+
         if isinstance(obj, datetime):
             return datetime.ctime(obj) + " " + (datetime.tzname(obj) or 'GMT')
-        
+
         return json.JSONEncoder.default(self, obj)
 
+
 # shortcut for JSON reponses
 class JSONResponse(http.HttpResponse):
-    
-    def __init__(self, data = {}, **kwargs):
+
+    def __init__(self, data={}, **kwargs):
         # get rid of mimetype
         kwargs.pop('mimetype', None)
-                
+
         super(JSONResponse, self).__init__(
-            json.dumps(data, cls=ExtendedEncoder), 
-            mimetype = "application/json", **kwargs)
-        
+            json.dumps(data, cls=ExtendedEncoder),
+            mimetype="application/json", **kwargs)
+
 
 # return errors
 class JSONFormInvalid(JSONResponse):
-    def __init__(self, form):                 
-        super(JSONFormInvalid, self).__init__(form.errors, status = 400)
-    
-class JSONServerError(JSONResponse):    
+    def __init__(self, form):
+        super(JSONFormInvalid, self).__init__(form.errors, status=400)
+
+
+class JSONServerError(JSONResponse):
     def __init__(self, *args, **kwargs):
         kwargs['status'] = 500
         super(JSONServerError, self).__init__(*args, **kwargs)
-    
-    
-    
\ No newline at end of file
index a530916..e4ac728 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import re
 import os
@@ -14,37 +14,38 @@ from django.http import Http404
 import logging
 logger = logging.getLogger("fnp.wiki")
 
+
 class DocumentStorage(object):
     def __init__(self, path):
         self.vstorage = vstorage.VersionedStorage(path)
 
-    def get(self, name, revision = None):
+    def get(self, name, revision=None):
         if revision is None:
             text = self.vstorage.page_text(name)
         else:
             text = self.vstorage.revision_text(name, revision)
-        return Document(self, name = name, text = text)
-    
+        return Document(self, name=name, text=text)
+
     def get_or_404(self, *args, **kwargs):
         try:
             return self.get(*args, **kwargs)
         except DocumentNotFound:
-            raise Http404            
+            raise Http404
 
     def put(self, document, author, comment, parent):
         self.vstorage.save_text(
-                title = document.name,
-                text = document.text, 
-                author = author, 
-                comment = comment, 
-                parent = parent)
+                title=document.name,
+                text=document.text,
+                author=author,
+                comment=comment,
+                parent=parent)
 
     def delete(self, name, author, comment):
         self.vstorage.delete_page(name, author, comment)
 
     def all(self):
         return list(self.vstorage.all_pages())
-    
+
     def history(self, title):
         return list(self.vstorage.page_history(title))
 
@@ -64,8 +65,8 @@ class Document(object):
         try:
             return self.storage._info(self.name)[0]
         except DocumentNotFound:
-            return -1
-        
+            return - 1
+
     def add_tag(self, tag):
         """ Add document specific tag """
         logger.debug("Adding tag %s to doc %s version %d", tag, self.name, self.revision)
@@ -85,25 +86,26 @@ class Document(object):
                     k, v = line.split(':', 1)
                     result[k.strip()] = v.strip()
                 except ValueError:
-                    continue                
-                
+                    continue
+
         gallery = result.get('gallery', self.name.replace(' ', '_'))
-        
-        if gallery.startswith('/'):            
+
+        if gallery.startswith('/'):
             gallery = os.path.basename(gallery)
-            
+
         result['gallery'] = gallery
-            
+
         if 'title' not in result:
-            result['title'] = self.name.title()            
+            result['title'] = self.name.title()
 
         return result
-    
+
     def info(self):
         return dict(zip(
             ('revision', 'last_update', 'last_comitter', 'commit_message'),
-            self.storage._info(self.name)
-        ))                         
+            self.storage._info(self.name),
+        ))
+
 
 def getstorage():
     return DocumentStorage(settings.REPOSITORY_PATH)
index c000b13..6f6e607 100755 (executable)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import difflib
 import re
@@ -9,21 +9,23 @@ import re
 from django.template.loader import render_to_string
 from django.utils.html import escape as html_escape
 
-DIFF_RE = re.compile(r"""\x00([+^-])""" ,re.UNICODE)
-NAMES = { '+': 'added', '-': 'removed', '^': 'changed' }
+DIFF_RE = re.compile(r"""\x00([+^-])""", re.UNICODE)
+NAMES = {'+': 'added', '-': 'removed', '^': 'changed'}
+
 
 def diff_replace(match):
-       return """<span class="diff_mark diff_mark_%s">""" %  NAMES[match.group(1)]
+    return """<span class="diff_mark diff_mark_%s">""" % NAMES[match.group(1)]
+
 
 def filter_line(line):
-       return  DIFF_RE.sub(diff_replace, html_escape(line)).replace('\x01', '</span>')
+    return  DIFF_RE.sub(diff_replace, html_escape(line)).replace('\x01', '</span>')
+
 
 def html_diff_table(la, lb):
-       return render_to_string("wiki/diff_table.html", {
-               "changes": [(a[0],filter_line(a[1]),
-                                        b[0],filter_line(b[1]),
-                                        change) for a, b, change in difflib._mdiff(la, lb)]
-       }); 
-                                                                               
-       
-__all__ = ['html_diff_table']
\ No newline at end of file
+    return render_to_string("wiki/diff_table.html", {
+        "changes": [(a[0], filter_line(a[1]), b[0], filter_line(b[1]), change)
+                        for a, b, change in difflib._mdiff(la, lb)],
+    })
+
+
+__all__ = ['html_diff_table']
index 91eccc8..6577737 100644 (file)
@@ -1,20 +1,19 @@
 from nose.tools import *
 import wiki.models as models
-import shutil, tempfile
+import shutil
+import tempfile
+
 
 class TestStorageBase:
     def setUp(self):
-        self.dirpath = tempfile.mkdtemp(prefix = 'nosetest_')
+        self.dirpath = tempfile.mkdtemp(prefix='nosetest_')
 
     def tearDown(self):
         shutil.rmtree(self.dirpath)
 
+
 class TestDocumentStorage(TestStorageBase):
 
     def test_storage_empty(self):
         storage = models.DocumentStorage(self.dirpath)
         eq_(storage.all(), [])
-
-
-
-
index b319465..fa4add3 100644 (file)
@@ -1,19 +1,19 @@
 from django.conf.urls.defaults import *
 from django.conf import settings
 
-urlpatterns = patterns('wiki.views',    
-    url(r'^$', 
+urlpatterns = patterns('wiki.views',
+    url(r'^$',
         'document_list', name='wiki_doclist'),
-    url(r'^gallery/(?P<directory>[^/]+)$', 
+    url(r'^gallery/(?P<directory>[^/]+)$',
         'document_gallery', name="wiki_gallery"),
-    url(r'^(?P<name>[^/]+)/history$', 
+    url(r'^(?P<name>[^/]+)/history$',
         'document_history', name="wiki_history"),
-    url(r'^(?P<name>[^/]+)/text$', 
+    url(r'^(?P<name>[^/]+)/text$',
         'document_text', name="wiki_text"),
-    url(r'^(?P<name>[^/]+)/publish/(?P<version>\d+)$', 
+    url(r'^(?P<name>[^/]+)/publish/(?P<version>\d+)$',
         'document_publish', name="wiki_publish"),
-    url(r'^(?P<name>[^/]+)/diff$', 
-        'document_diff', name="wiki_diff"),    
-    url(r'^(?P<name>[^/]+)$', 
-        'document_detail', name="wiki_details"),       
-)   
\ No newline at end of file
+    url(r'^(?P<name>[^/]+)/diff$',
+        'document_diff', name="wiki_diff"),
+    url(r'^(?P<name>[^/]+)$',
+        'document_detail', name="wiki_details"),
+)
index 29039b7..64e9330 100644 (file)
@@ -25,68 +25,70 @@ import operator
 
 MAX_LAST_DOCS = 10
 
+
 @never_cache
-def document_list(request, template_name = 'wiki/document_list.html'):
+def document_list(request, template_name='wiki/document_list.html'):
     # TODO: find a way to cache "Storage All"
-    return direct_to_template(request, template_name, extra_context = {
+    return direct_to_template(request, template_name, extra_context={
         'document_list': getstorage().all(),
-        'last_docs': sorted(request.session.get("wiki_last_docs", {}).items(), 
-                        key=operator.itemgetter(1), reverse = True)
-    })  
+        'last_docs': sorted(request.session.get("wiki_last_docs", {}).items(),
+                        key=operator.itemgetter(1), reverse=True),
+    })
+
 
 @never_cache
-def document_detail(request, name, template_name = 'wiki/document_details.html'):
-    
+def document_detail(request, name, template_name='wiki/document_details.html'):
+
     document = getstorage().get_or_404(name)
-    
+
     access_time = datetime.now()
-    last_documents = request.session.get("wiki_last_docs", {})      
+    last_documents = request.session.get("wiki_last_docs", {})
     last_documents[name] = access_time
-    
+
     if len(last_documents) > MAX_LAST_DOCS:
-        oldest_key = min(last_documents, key = last_documents.__getitem__)
-        del last_documents[oldest_key]        
-    request.session['wiki_last_docs'] = last_documents      
+        oldest_key = min(last_documents, key=last_documents.__getitem__)
+        del last_documents[oldest_key]
+    request.session['wiki_last_docs'] = last_documents
 
-    return direct_to_template(request, template_name, extra_context = {
+    return direct_to_template(request, template_name, extra_context={
         'document': document,
         'document_info': document.info,
         'document_meta': document.meta,
-        'forms': {"text_save": DocumentTextSaveForm(), "add_tag": DocumentTagForm() },         
+        'forms': {"text_save": DocumentTextSaveForm(), "add_tag": DocumentTagForm()},
     })
 
+
 @never_cache
-def document_text(request, name):    
+def document_text(request, name):
     storage = getstorage()
-    document = storage.get_or_404(name) 
-    
-    if request.method == 'POST':        
+    document = storage.get_or_404(name)
+
+    if request.method == 'POST':
         form = DocumentTextSaveForm(request.POST)
-        
-        if form.is_valid():            
+
+        if form.is_valid():
             revision = form.cleaned_data['parent_revision']
             document.text = form.cleaned_data['text']
-            
-            storage.put(document, 
-                author = form.cleaned_data['author'] or request.user.username, 
-                comment = form.cleaned_data['comment'],
-                parent = revision 
+
+            storage.put(document,
+                author=form.cleaned_data['author'] or request.user.username,
+                comment=form.cleaned_data['comment'],
+                parent=revision,
             )
-                        
+
             return JSONResponse({
-                'text': document.plain_text if revision != document.revision() else None, 
-                'meta': document.meta(), 
-                'revision': document.revision() 
+                'text': document.plain_text if revision != document.revision() else None,
+                'meta': document.meta(),
+                'revision': document.revision(),
             })
         else:
-            return JSONFormInvalid(form)                            
+            return JSONFormInvalid(form)
     else:
         return JSONResponse({
-            'text': document.plain_text, 
-            'meta': document.meta(), 
-            'revision': document.revision()
+            'text': document.plain_text,
+            'meta': document.meta(),
+            'revision': document.revision(),
         })
-   
 
 
 @never_cache
@@ -96,71 +98,75 @@ def document_gallery(request, directory):
                         smart_unicode(settings.MEDIA_URL),
                         smart_unicode(settings.FILEBROWSER_DIRECTORY),
                         smart_unicode(directory)))
-        
+
         base_dir = os.path.join(
-                    smart_unicode(settings.MEDIA_ROOT), 
+                    smart_unicode(settings.MEDIA_ROOT),
                     smart_unicode(settings.FILEBROWSER_DIRECTORY),
                     smart_unicode(directory))
-        
+
         def map_to_url(filename):
             return "%s/%s" % (base_url, smart_unicode(filename))
-            
+
         def is_image(filename):
             return os.path.splitext(f)[1].lower() in (u'.jpg', u'.jpeg', u'.png')
-            
-        images = [ map_to_url(f) for f in map(smart_unicode, os.listdir(base_dir)) if is_image(f) ]
+
+        images = [map_to_url(f) for f in map(smart_unicode, os.listdir(base_dir)) if is_image(f)]
         images.sort()
         return JSONResponse(images)
     except (IndexError, OSError), exc:
         import traceback
         traceback.print_exc()
         raise http.Http404
-    
+
+
 @never_cache
 def document_diff(request, name):
-    storage = getstorage()    
-    
+    storage = getstorage()
+
     revA = int(request.GET.get('from', 0))
     revB = int(request.GET.get('to', 0))
-    
+
     if revA > revB:
         revA, revB = revB, revA
-        
+
     if revB == 0:
-        revB = None   
-         
+        revB = None
+
     docA = storage.get_or_404(name, int(revA))
-    docB = storage.get_or_404(name, int(revB)) 
-        
-    return http.HttpResponse(nice_diff.html_diff_table(docA.plain_text.splitlines(), 
-                                         docB.plain_text.splitlines()) )                                           
-    
-@never_cache    
+    docB = storage.get_or_404(name, int(revB))
+
+    return http.HttpResponse(nice_diff.html_diff_table(docA.plain_text.splitlines(),
+                                         docB.plain_text.splitlines()))
+
+
+@never_cache
 def document_history(request, name):
     storage = getstorage()
-    return JSONResponse(storage.history(name)) 
+    return JSONResponse(storage.history(name))
+
 
 @require_POST
-def document_add_tag(request, name): 
+def document_add_tag(request, name):
     storage = getstorage()
-    
+
     form = DocumentTagForm(request.POST)
     if form.is_valid():
         doc = storage.get_or_404(name, form.cleaned_data['version'])
         doc.add_tag(form.cleaned_data['tag'])
-        return JSONResponse({"message": _("Tag added")})  
+        return JSONResponse({"message": _("Tag added")})
     else:
         return JSONFormInvalid(form)
-    
+
+
 @require_POST
 def document_publish(request, name, version):
     storage = getstorage()
-    
+
     # get the document
-    document = storage.get_or_404(name, revision = int(version))
-    
-    api = wlapi.WLAPI(settings.WL_API_CONFIG)    
-    try:        
+    document = storage.get_or_404(name, revision=int(version))
+
+    api = wlapi.WLAPI(settings.WL_API_CONFIG)
+    try:
         return JSONResponse({"result": api.publish_book(document)})
-    except wlapi.APICallException, e:  
-        return JSONServerError({"message": str(e)})                     
\ No newline at end of file
+    except wlapi.APICallException, e:
+        return JSONServerError({"message": str(e)})
index 724fca2..587821b 100644 (file)
@@ -1,4 +1,4 @@
-from __future__ import with_statement # needed for python 2.5
+from __future__ import with_statement  # needed for python 2.5
 from fabric.api import *
 from fabric.contrib import files
 
@@ -12,6 +12,7 @@ import os
 env.project_name = 'platforma'
 env.use_south = True
 
+
 # Servers
 def staging():
     """Use staging server"""
@@ -22,6 +23,7 @@ def staging():
     env.virtualenv = '/usr/bin/virtualenv'
     env.pip = '/usr/bin/pip'
 
+
 def production():
     """Use production server"""
     env.hosts = ['szo.nowoczesnapolska.org.pl:2225']
@@ -37,28 +39,30 @@ def production():
 # =========
 def test():
     "Run the test suite and bail out if it fails"
-    require('hosts', 'path', provided_by = [staging, production])
+    require('hosts', 'path', provided_by=[staging, production])
     result = run('cd %(path)s/%(project_name)s; %(python)s manage.py test' % env)
 
+
 def setup():
     """
     Setup a fresh virtualenv as well as a few useful directories, then run
     a full deployment. virtualenv and pip should be already installed.
     """
-    require('hosts', 'path', provided_by = [staging, production])
+    require('hosts', 'path', provided_by=[staging, production])
 
-    run('mkdir -p %(path)s; cd %(path)s; %(virtualenv)s --no-site-packages .;' % env, pty = True)
-    run('cd %(path)s; mkdir releases; mkdir shared; mkdir packages;' % env, pty = True)
-    run('cd %(path)s/releases; ln -s . current; ln -s . previous' % env, pty = True)
+    run('mkdir -p %(path)s; cd %(path)s; %(virtualenv)s --no-site-packages .;' % env, pty=True)
+    run('cd %(path)s; mkdir releases; mkdir shared; mkdir packages;' % env, pty=True)
+    run('cd %(path)s/releases; ln -s . current; ln -s . previous' % env, pty=True)
     deploy()
 
+
 def deploy():
     """
-    Deploy the latest version of the site to the servers, 
-    install any required third party modules, 
+    Deploy the latest version of the site to the servers,
+    install any required third party modules,
     install the virtual host and then restart the webserver
     """
-    require('hosts', 'path', provided_by = [staging, production])
+    require('hosts', 'path', provided_by=[staging, production])
 
     import time
     env.release = time.strftime('%Y-%m-%dT%H%M')
@@ -73,26 +77,28 @@ def deploy():
     django_compress()
     restart_webserver()
 
+
 def deploy_version(version):
     "Specify a specific version to be made live"
-    require('hosts', 'path', provided_by = [localhost, webserver])
+    require('hosts', 'path', provided_by=[localhost, webserver])
     env.version = version
     with cd(env.path):
-        run('rm releases/previous; mv releases/current releases/previous;', pty = True)
-        run('ln -s %(version)s releases/current' % env, pty = True)
+        run('rm releases/previous; mv releases/current releases/previous;', pty=True)
+        run('ln -s %(version)s releases/current' % env, pty=True)
     restart_webserver()
 
+
 def rollback():
     """
     Limited rollback capability. Simple loads the previously current
     version of the code. Rolling back again will swap between the two.
     """
-    require('hosts', provided_by = [staging, production])
+    require('hosts', provided_by=[staging, production])
     require('path')
     with cd(env.path):
-        run('mv releases/current releases/_previous;', pty = True)
-        run('mv releases/previous releases/current;', pty = True)
-        run('mv releases/_previous releases/previous;', pty = True)
+        run('mv releases/current releases/_previous;', pty=True)
+        run('mv releases/previous releases/current;', pty=True)
+        run('mv releases/_previous releases/previous;', pty=True)
     restart_webserver()
 
 
@@ -102,65 +108,72 @@ def rollback():
 def upload_tar_from_git():
     "Create an archive from the current Git master branch and upload it"
     print '>>> upload tar from git'
-    require('release', provided_by = [deploy])
+    require('release', provided_by=[deploy])
     local('git archive --format=tar master | gzip > %(release)s.tar.gz' % env)
-    run('mkdir -p %(path)s/releases/%(release)s' % env, pty = True)
-    run('mkdir -p %(path)s/packages' % env, pty = True)
+    run('mkdir -p %(path)s/releases/%(release)s' % env, pty=True)
+    run('mkdir -p %(path)s/packages' % env, pty=True)
     put('%(release)s.tar.gz' % env, '%(path)s/packages/' % env)
-    run('cd %(path)s/releases/%(release)s && tar zxf ../../packages/%(release)s.tar.gz' % env, pty = True)
+    run('cd %(path)s/releases/%(release)s && tar zxf ../../packages/%(release)s.tar.gz' % env, pty=True)
     local('rm %(release)s.tar.gz' % env)
 
+
 def upload_vhost_sample():
     "Create and upload Apache virtual host configuration sample"
     print ">>> upload vhost sample"
-    files.upload_template('%(project_name)s.vhost.template' % env, '%(path)s/%(project_name)s.vhost.sample' % env, context = env)
+    files.upload_template('%(project_name)s.vhost.template' % env, '%(path)s/%(project_name)s.vhost.sample' % env, context=env)
+
 
 def upload_wsgi_script():
     "Create and upload a wsgi script sample"
     print ">>> upload wsgi script sample"
-    files.upload_template('%(project_name)s.wsgi.template' % env, '%(path)s/%(project_name)s.wsgi' % env, context = env)
+    files.upload_template('%(project_name)s.wsgi.template' % env, '%(path)s/%(project_name)s.wsgi' % env, context=env)
     run('chmod ug+x %(path)s/%(project_name)s.wsgi' % env)
 
+
 def install_requirements():
     "Install the required packages from the requirements file using pip"
     print '>>> install requirements'
-    require('release', provided_by = [deploy])
-    run('cd %(path)s; %(pip)s install -E . -r %(path)s/releases/%(release)s/requirements.txt' % env, pty = True)
+    require('release', provided_by=[deploy])
+    run('cd %(path)s; %(pip)s install -E . -r %(path)s/releases/%(release)s/requirements.txt' % env, pty=True)
+
 
 def copy_localsettings():
     "Copy localsettings.py from root directory to release directory (if this file exists)"
     print ">>> copy localsettings"
-    require('release', provided_by = [deploy])
-    require('path', provided_by = [staging, production])
+    require('release', provided_by=[deploy])
+    require('path', provided_by=[staging, production])
 
-    with settings(warn_only = True):
+    with settings(warn_only=True):
         run('cp %(path)s/localsettings.py %(path)s/releases/%(release)s/%(project_name)s' % env)
 
+
 def symlink_current_release():
     "Symlink our current release"
     print '>>> symlink current release'
-    require('release', provided_by = [deploy])
-    require('path', provided_by = [staging, production])
+    require('release', provided_by=[deploy])
+    require('path', provided_by=[staging, production])
     with cd(env.path):
         run('rm releases/previous; mv releases/current releases/previous')
         run('ln -s %(release)s releases/current' % env)
 
+
 def migrate():
     "Update the database"
     print '>>> migrate'
-    require('project_name', provided_by = [staging, production])
+    require('project_name', provided_by=[staging, production])
     with cd('%(path)s/releases/current/%(project_name)s' % env):
-        run('../../../bin/python manage.py syncdb --noinput' % env, pty = True)
+        run('../../../bin/python manage.py syncdb --noinput' % env, pty=True)
         if env.use_south:
-            run('../../../bin/python manage.py migrate' % env, pty = True)
-            
+            run('../../../bin/python manage.py migrate' % env, pty=True)
+
+
 def django_compress():
     "Update static files"
     print '>>> migrate'
-    require('project_name', provided_by = [staging, production])
+    require('project_name', provided_by=[staging, production])
     with cd('%(path)s/releases/current/%(project_name)s' % env):
-        run('../../../bin/python manage.py synccompress --force' % env, pty = True)
-        
+        run('../../../bin/python manage.py synccompress --force' % env, pty=True)
+
 
 def restart_webserver():
     "Restart the web server"
index eaea46f..23375f0 100644 (file)
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 
 import os
@@ -12,6 +12,8 @@ from nose.core import runmodule
 
 import vstorage
 
+NULL_PARENT = -1
+
 
 def clear_directory(top):
     for root, dirs, files in os.walk(top, topdown=False):
@@ -29,20 +31,24 @@ class TestVersionedStorage(object):
     def setUp(self):
         self.repo_path = tempfile.mkdtemp()
         self.repo = vstorage.VersionedStorage(self.repo_path)
-        
+
     def tearDown(self):
         clear_directory(self.repo_path)
-    
+
     def test_save_text(self):
         text = u"test text"
         title = u"test title"
         author = u"test author"
         comment = u"test comment"
-        
-        self.repo.save_text(title = title, 
-                    text = text, author = author, 
-                    comment = comment, parent=-1)
-        
+
+        self.repo.save_text(
+            title=title,
+            text=text,
+            author=author,
+            comment=comment,
+            parent=NULL_PARENT,
+        )
+
         saved = self.repo.open_page(title).read()
         assert_equal(saved, text)
 
@@ -51,11 +57,11 @@ class TestVersionedStorage(object):
         title = u"test title"
         author = u"test author"
         comment = u"test comment"
-        
-        self.repo.save_text(title = title, 
-                    text = text, author = author, 
-                    comment = comment, parent=None)
-        
+
+        self.repo.save_text(title=title,
+                    text=text, author=author,
+                    comment=comment, parent=None)
+
         saved = self.repo.open_page(title).read()
         assert_equal(saved, text)
 
@@ -64,15 +70,15 @@ class TestVersionedStorage(object):
         title = u"test title"
         author = u"test author"
         comment = u"test comment"
-        self.repo.save_text(title = title, 
-                    text = text, author = author, 
-                    comment = comment, parent=-1)
-        self.repo.save_text(title = title, 
-                    text = text, author = author, 
-                    comment = comment, parent=-1)
+        self.repo.save_text(title=title,
+                    text=text, author=author,
+                    comment=comment, parent=NULL_PARENT)
+        self.repo.save_text(title=title,
+                    text=text, author=author,
+                    comment=comment, parent=NULL_PARENT)
         saved = self.repo.open_page(title).read()
         assert_equal(saved, text)
-    
+
     def test_save_merge_line_conflict(self):
         text = u"test\ntest\n"
         text1 = u"test\ntext\n"
@@ -80,21 +86,21 @@ class TestVersionedStorage(object):
         title = u"test title"
         author = u"test author"
         comment = u"test comment"
-        
-        self.repo.save_text(title = title, 
-                    text = text, author = author, 
-                    comment = comment, parent=-1)
-        
-        self.repo.save_text(title = title, 
-                    text = text1, author = author, 
-                    comment = comment, parent=0)
-        
-        self.repo.save_text(title = title, 
-                    text = text2, author = author, 
-                    comment = comment, parent=0)
-        
+
+        self.repo.save_text(title=title,
+                    text=text, author=author,
+                    comment=comment, parent=NULL_PARENT)
+
+        self.repo.save_text(title=title,
+                    text=text1, author=author,
+                    comment=comment, parent=0)
+
+        self.repo.save_text(title=title,
+                    text=text2, author=author,
+                    comment=comment, parent=0)
+
         saved = self.repo.open_page(title).read()
-        
+
         # Other conflict markers placement can also be correct
         assert_equal(saved, u'''\
 text
@@ -105,20 +111,19 @@ text
 >>>>>>> other
 ''')
 
-
     def test_delete(self):
         text = u"text test"
         title = u"test title"
         author = u"test author"
         comment = u"test comment"
-        self.repo.save_text(title = title, 
-                    text = text, author = author, 
-                    comment = comment, parent=-1)
-        
+        self.repo.save_text(title=title,
+                    text=text, author=author,
+                    comment=comment, parent=NULL_PARENT)
+
         assert title in self.repo
-        
+
         self.repo.delete_page(title, author, comment)
-        
+
         assert title not in self.repo
 
     @raises(vstorage.DocumentNotFound)
@@ -126,90 +131,88 @@ text
         self.repo.open_page(u'unknown entity')
 
     def test_open_existing_repository(self):
-        self.repo.save_text(title = u'Python!', text = u'ham and spam')
+        self.repo.save_text(title=u'Python!', text=u'ham and spam')
         current_repo_revision = self.repo.repo_revision()
         same_repo = vstorage.VersionedStorage(self.repo_path)
         assert_equal(same_repo.repo_revision(), current_repo_revision)
-        
-        
+
     def test_history(self):
         COMMITS = [
-            {"author": "bunny", "text":"1", "comment": "Oh yeah!"}, 
+            {"author": "bunny", "text":"1", "comment": "Oh yeah!"},
             {"author": "frank", "text":"2", "comment": "Second is the best!"},
-            {"text":"3", "comment": "Third"}, # anonymous 
-            {"author": "welma", "text":"4", "comment": "Fourth"},            
+            {"text":"3", "comment": "Third"},
+            {"author": "welma", "text":"4", "comment": "Fourth"},
         ]
-        
+
         for commit in COMMITS:
-            self.repo.save_text(title = u"Sample", **commit)
-        
+            self.repo.save_text(title=u"Sample", **commit)
+
         for n, entry in enumerate(reversed(list(self.repo.page_history(u"Sample")))):
             assert_equal(entry["version"], n)
-            assert_equal(entry["author"], COMMITS[n].get("author", "anonymous") )
+            assert_equal(entry["author"], COMMITS[n].get("author", "anonymous"))
             assert_equal(entry["description"], COMMITS[n]["comment"])
-            assert_equal(entry["tag"], [])     
-            
-            
+            assert_equal(entry["tag"], [])
+
+
 class TestVSTags(object):
-    
+
     TITLE_1 = "Sample"
-    
+
     COMMITS = [
-        {"author": "bunny", "text":"1", "comment": "Oh yeah!"}, 
+        {"author": "bunny", "text":"1", "comment": "Oh yeah!"},
         {"author": "frank", "text":"2", "comment": "Second is the best!"},
-        {"text":"3", "comment": "Third"}, # anonymous 
-        {"author": "welma", "text":"4", "comment": "Fourth"},            
-    ]   
-    
+        {"text":"3", "comment": "Third"},
+        {"author": "welma", "text":"4", "comment": "Fourth"},
+    ]
+
     def setUp(self):
         self.repo_path = tempfile.mkdtemp()
         self.repo = vstorage.VersionedStorage(self.repo_path)
-        
+
         # generate some history
         for commit in self.COMMITS:
-            self.repo.save_text(title = u"Sample", **commit)
-                    
+            self.repo.save_text(title=u"Sample", **commit)
+
         # verify
         for n, entry in enumerate(reversed(list(self.repo.page_history(self.TITLE_1)))):
             assert_equal(entry["tag"], [])
-            
+
     def tearDown(self):
         clear_directory(self.repo_path)
-            
-    def test_add_tag(self):        
+
+    def test_add_tag(self):
         TAG_USER = "mike_the_tagger"
         TAG_NAME = "production"
         TAG_VERSION = 2
-            
+
         # Add tag
         self.repo.add_page_tag(self.TITLE_1, TAG_VERSION, TAG_NAME, TAG_USER)
-        
+
         # check history again
         history = list(self.repo.page_history(self.TITLE_1))
         for entry in reversed(history):
             if entry["version"] == TAG_VERSION:
                 assert_equal(entry["tag"], [TAG_NAME])
             else:
-                assert_equal(entry["tag"], []) 
-                
-    def test_add_many_tags(self):        
+                assert_equal(entry["tag"], [])
+
+    def test_add_many_tags(self):
         TAG_USER = "mike_the_tagger"
         tags = [
             (2, "production", "mike"),
             (2, "finished", "jeremy"),
             (0, "original", "jeremy"),
         ]
-            
-        
+
         for rev, name, user in tags:
             self.repo.add_page_tag(self.TITLE_1, rev, name, user)
-        
+
         # check history again
         history = list(self.repo.page_history(self.TITLE_1))
         for entry in reversed(history):
-            expected = [ tag[1] for tag in tags if tag[0] == entry["version"] ]
+            expected = [tag[1] for tag in tags if tag[0] == entry["version"]]
             assert_equal(set(entry["tag"]), set(expected))
 
 
 if __name__ == '__main__':
-    runmodule()
\ No newline at end of file
+    runmodule()
index 319a0f1..ae4d22f 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import os
 import tempfile
@@ -23,9 +23,9 @@ import mercurial.revlog
 import mercurial.util
 
 
-def urlquote(url, safe = '/'):
-    """Quotes URL 
-    
+def urlquote(url, safe='/'):
+    """Quotes URL
+
     >>> urlquote(u'Za\u017c\xf3\u0142\u0107 g\u0119\u015bl\u0105 ja\u017a\u0144')
     'Za%C5%BC%C3%B3%C5%82%C4%87_g%C4%99%C5%9Bl%C4%85_ja%C5%BA%C5%84'
     """
@@ -33,8 +33,8 @@ def urlquote(url, safe = '/'):
 
 
 def urlunquote(url):
-    """Unqotes URL 
-    
+    """Unqotes URL
+
     # >>> urlunquote('Za%C5%BC%C3%B3%C5%82%C4%87_g%C4%99%C5%9Bl%C4%85_ja%C5%BA%C5%84')
     # u'Za\u017c\xf3\u0142\u0107 g\u0119\u015bl\u0105 ja\u017a\u0144'
     """
@@ -59,10 +59,11 @@ def with_working_copy_locked(func):
         wlock = self.repo.wlock()
         try:
             return func(self, *args, **kwargs)
-        finally:            
+        finally:
             wlock.release()
     return wrapped
 
+
 def with_storage_locked(func):
     """A decorator for locking the repository when calling a method."""
 
@@ -72,10 +73,11 @@ def with_storage_locked(func):
         lock = self.repo.lock()
         try:
             return func(self, *args, **kwargs)
-        finally:            
+        finally:
             lock.release()
     return wrapped
 
+
 def guess_mime(file_name):
     """
     Guess file's mime type based on extension.
@@ -95,7 +97,7 @@ def guess_mime(file_name):
     'archive/gzip'
     """
 
-    mime, encoding = mimetypes.guess_type(file_name, strict = False)
+    mime, encoding = mimetypes.guess_type(file_name, strict=False)
     if encoding:
         mime = 'archive/%s' % encoding
     if mime is None:
@@ -113,7 +115,7 @@ class VersionedStorage(object):
     change history, using Mercurial repository as the storage method.
     """
 
-    def __init__(self, path, charset = None):
+    def __init__(self, path, charset=None):
         """
         Takes the path to the directory where the pages are to be kept.
         If the directory doen't exist, it will be created. If it's inside
@@ -126,38 +128,38 @@ class VersionedStorage(object):
         if not os.path.exists(self.path):
             os.makedirs(self.path)
         self.repo_path = find_repo_path(self.path)
-        
+
         self.ui = mercurial.ui.ui()
         self.ui.quiet = True
         self.ui._report_untrusted = False
         self.ui.setconfig('ui', 'interactive', False)
-        
+
         if self.repo_path is None:
             self.repo_path = self.path
             create = True
         else:
             create = False
-            
+
         self.repo_prefix = self.path[len(self.repo_path):].strip('/')
         self.repo = mercurial.hg.repository(self.ui, self.repo_path,
-                                            create = create)
+                                            create=create)
 
     def reopen(self):
         """Close and reopen the repo, to make sure we are up to date."""
         self.repo = mercurial.hg.repository(self.ui, self.repo_path)
 
     def _file_path(self, title):
-        return os.path.join(self.path, urlquote(title, safe = ''))
+        return os.path.join(self.path, urlquote(title, safe=''))
 
     def _title_to_file(self, title):
-        return os.path.join(self.repo_prefix, urlquote(title, safe = ''))
+        return os.path.join(self.repo_prefix, urlquote(title, safe=''))
 
     def _file_to_title(self, filename):
         assert filename.startswith(self.repo_prefix)
         name = filename[len(self.repo_prefix):].strip('/')
         return urlunquote(name)
 
-    def __contains__(self, title):                        
+    def __contains__(self, title):
         return urlquote(title) in self.repo['tip']
 
     def __iter__(self):
@@ -195,40 +197,39 @@ class VersionedStorage(object):
 
     @with_working_copy_locked
     @with_storage_locked
-    def save_file(self, title, file_name, author = u'', comment = u'', parent = None):
+    def save_file(self, title, file_name, author=u'', comment=u'', parent=None):
         """Save an existing file as specified page."""
         user = author.encode('utf-8') or u'anonymous'.encode('utf-8')
         text = comment.encode('utf-8') or u'comment'.encode('utf-8')
-        
+
         repo_file = self._title_to_file(title)
         file_path = self._file_path(title)
         mercurial.util.rename(file_name, file_path)
         changectx = self._changectx()
-        
+
         try:
             filectx_tip = changectx[repo_file]
             current_page_rev = filectx_tip.filerev()
         except mercurial.revlog.LookupError:
             self.repo.add([repo_file])
             current_page_rev = -1
-        
+
         if parent is not None and current_page_rev != parent:
             msg = self.merge_changes(changectx, repo_file, text, user, parent)
             user = '<wiki>'
             text = msg.encode('utf-8')
-            
+
         self._commit([repo_file], text, user)
-        
-        
+
     def save_data(self, title, data, **kwargs):
         """Save data as specified page."""
         try:
-            temp_path = tempfile.mkdtemp(dir = self.path)
+            temp_path = tempfile.mkdtemp(dir=self.path)
             file_path = os.path.join(temp_path, 'saved')
             f = open(file_path, "wb")
             f.write(data)
             f.close()
-            self.save_file(title = title, file_name = file_path, **kwargs)
+            self.save_file(title=title, file_name=file_path, **kwargs)
         finally:
             try:
                 os.unlink(file_path)
@@ -240,14 +241,13 @@ class VersionedStorage(object):
                 pass
 
     def save_text(self, text, **kwargs):
-        """Save text as specified page, encoded to charset.""" 
-        self.save_data(data = text.encode(self.charset), **kwargs)
-
+        """Save text as specified page, encoded to charset."""
+        self.save_data(data=text.encode(self.charset), **kwargs)
 
     def _commit(self, files, text, user):
         match = mercurial.match.exact(self.repo_path, '', list(files))
-        return self.repo.commit(match = match, text = text, user = user, force = True)
+        return self.repo.commit(match=match, text=text, user=user, force=True)
+
     def page_text(self, title):
         """Read unicode text of a page."""
         data = self.open_page(title).read()
@@ -260,7 +260,7 @@ class VersionedStorage(object):
 
     @with_working_copy_locked
     @with_storage_locked
-    def delete_page(self, title, author = u'', comment = u''):
+    def delete_page(self, title, author=u'', comment=u''):
         user = author.encode('utf-8') or 'anon'
         text = comment.encode('utf-8') or 'deleted'
         repo_file = self._title_to_file(title)
@@ -276,11 +276,11 @@ class VersionedStorage(object):
     def open_page(self, title):
         if title not in self:
             raise DocumentNotFound()
-        
+
         path = self._title_to_file(title)
-        logger.debug("Opening page %s", path)      
+        logger.debug("Opening page %s", path)
         try:
-            return self.repo.wfile(path, 'rb')            
+            return self.repo.wfile(path, 'rb')
         except IOError:
             logger.exception("Failed to open page %s", title)
             raise DocumentNotFound()
@@ -294,7 +294,7 @@ class VersionedStorage(object):
         except OSError:
             return 0, 0, 0
         return st_ino, st_size, st_mtime
-    
+
     @with_working_copy_locked
     def page_meta(self, title):
         """Get page's revision, date, last editor and his edit comment."""
@@ -314,7 +314,7 @@ class VersionedStorage(object):
 
     def repo_revision(self):
         return self.repo['tip'].rev()
-    
+
     def _changectx(self):
         return self.repo['tip']
 
@@ -325,7 +325,7 @@ class VersionedStorage(object):
         """
         return guess_mime(self._file_path(title))
 
-    def _find_filectx(self, title, rev = None):
+    def _find_filectx(self, title, rev=None):
         """Find the last revision in which the file existed."""
 
         repo_file = self._title_to_file(title)
@@ -338,9 +338,9 @@ class VersionedStorage(object):
             for parent in changectx.parents():
                 if parent != changectx:
                     stack.append(parent)
-        
+
         try:
-            fctx = changectx[repo_file]            
+            fctx = changectx[repo_file]
             return fctx if rev is None else fctx.filectx(rev)
         except IndexError, LookupError:
             raise DocumentNotFound()
@@ -349,7 +349,7 @@ class VersionedStorage(object):
         """Iterate over the page's history."""
 
         filectx_tip = self._find_filectx(title)
-        
+
         maxrev = filectx_tip.filerev()
         minrev = 0
         for rev in range(maxrev, minrev - 1, -1):
@@ -359,11 +359,11 @@ class VersionedStorage(object):
                              'replace').split('<')[0].strip()
             comment = unicode(filectx.description(), "utf-8", 'replace')
             tags = [t.rsplit('#', 1)[-1] for t in filectx.changectx().tags() if '#' in t]
-            
+
             yield {
-                "version": rev, 
-                "date": date, 
-                "author": author, 
+                "version": rev,
+                "date": date,
+                "author": author,
                 "description": comment,
                 "tag": tags,
             }
@@ -376,19 +376,19 @@ class VersionedStorage(object):
         data = self.page_revision(title, rev)
         text = unicode(data, self.charset, 'replace')
         return text
-    
+
     @with_working_copy_locked
-    def add_page_tag(self, title, rev, tag, user = "<wiki>", doctag = True):
+    def add_page_tag(self, title, rev, tag, user="<wiki>", doctag=True):
         if doctag:
             tag = "{title}#{tag}".format(**locals())
-            
+
         message = "Assigned tag {tag} to version {rev} of {title}".format(**locals())
-            
+
         fctx = self._find_filectx(title, rev)
         self.repo.tag(
-            names = tag, node = fctx.node(), local = False,
-            user = user, message = message, date = None
-        )        
+            names=tag, node=fctx.node(), local=False,
+            user=user, message=message, date=None,
+        )
 
     def history(self):
         """Iterate over the history of entire wiki."""
@@ -414,7 +414,7 @@ class VersionedStorage(object):
     def all_pages(self):
         tip = self.repo['tip']
         """Iterate over the titles of all pages in the wiki."""
-        return [ urlunquote(filename) for filename in tip ]        
+        return [urlunquote(filename) for filename in tip]
 
     def changed_since(self, rev):
         """Return all pages that changed since specified repository revision."""
index cc73596..ba1be14 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 """
    Abstraction over API for wolnelektury.pl
@@ -12,64 +12,63 @@ import django.utils.simplejson as json
 import logging
 logger = logging.getLogger("fnp.lib.wlapi")
 
+
 class APICallException(Exception):
-    pass 
+    pass
+
 
 def api_call(path, format="json"):
     def wrapper(func):
-        
+
         @functools.wraps(func)
-        def wrapped(self, *args, **kwargs):            
+        def wrapped(self, *args, **kwargs):
             generator = func(self, *args, **kwargs)
-            
+
             data = generator.next()
-            
+
             # prepare request
             rq = urllib2.Request(self.base_url + path + ".json")
-            
+
             # will send POST when there is data, GET otherwise
             if data is not None:
-                rq.add_data(json.dumps(data))    
+                rq.add_data(json.dumps(data))
                 rq.add_header("Content-Type", "application/json")
-                            
+
             try:
                 anwser = json.load(self.opener.open(rq))
                 return generator.send(anwser)
             except StopIteration:
                 # by default, just return the anwser as a shorthand
-                return anwser                            
+                return anwser
             except urllib2.HTTPError, error:
-                return self._http_error(error)         
+                return self._http_error(error)
             except Exception, error:
-                return self._error(error)               
+                return self._error(error)
         return wrapped
-    
+
     return wrapper
-         
-    
+
 
 class WLAPI(object):
-    
-    def __init__(self, config_dict):        
+
+    def __init__(self, config_dict):
         self.base_url = config_dict['URL']
         self.auth_realm = config_dict['AUTH_REALM']
-        self.auth_user = config_dict['AUTH_USER'] 
-        
-        auth_handler = urllib2.HTTPDigestAuthHandler();
+        self.auth_user = config_dict['AUTH_USER']
+
+        auth_handler = urllib2.HTTPDigestAuthHandler()
         auth_handler.add_password(
                     realm=self.auth_realm, uri=self.base_url,
                     user=self.auth_user, passwd=config_dict['AUTH_PASSWD'])
-        
+
         self.opener = urllib2.build_opener(auth_handler)
-        
+
     def _http_error(self, error):
         return self._error()
-    
+
     def _error(self, error):
-        raise APICallException(cause = error) 
-        
+        raise APICallException(cause=error)
+
     @api_call("books")
     def publish_book(self, document):
-        yield {"text": document.text, "compressed": False} 
-        
-    
\ No newline at end of file
+        yield {"text": document.text, "compressed": False}
index eff3032..db6c98b 100644 (file)
@@ -1,11 +1,8 @@
 # -*- coding: utf-8
-__author__="lreqc"
-__date__ ="$2009-09-03 08:34:10$"
+
 
 def settings(request):
     from django.conf import settings
-    return {'MEDIA_URL': settings.MEDIA_URL, 
+    return {'MEDIA_URL': settings.MEDIA_URL,
             'STATIC_URL': settings.STATIC_URL,
-            'REDMINE_URL': settings.REDMINE_URL }
-
-
+            'REDMINE_URL': settings.REDMINE_URL}
index 8e180f0..1fc25dd 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 from django.core.management import execute_manager
 try:
-    import settings # Assumed to be in the same directory.
+    import settings  # Assumed to be in the same directory.
 except ImportError:
     import sys
     sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
@@ -11,8 +11,8 @@ if __name__ == "__main__":
     # Append lib and apps directories to PYTHONPATH
     from os import path
     import sys
-    
+
     PROJECT_ROOT = path.realpath(path.dirname(__file__))
     sys.path += [PROJECT_ROOT + '/../apps', PROJECT_ROOT + '/../lib']
-    
+
     execute_manager(settings)
index 8814148..90ecd27 100644 (file)
@@ -84,7 +84,7 @@ MIDDLEWARE_CLASSES = (
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django_cas.middleware.CASMiddleware',
 
-    'django.middleware.doc.XViewMiddleware',    
+    'django.middleware.doc.XViewMiddleware',
     'maintenancemode.middleware.MaintenanceModeMiddleware',
     # 'debug_toolbar.middleware.DebugToolbarMiddleware' #
 )
@@ -104,7 +104,7 @@ TEMPLATE_DIRS = (
 #
 # Central Auth System
 #
-## Set this to where the CAS server lives 
+## Set this to where the CAS server lives
 # CAS_SERVER_URL = "http://cas.fnp.pl/
 CAS_ADMIN_PREFIX = "/admin/"
 CAS_LOGOUT_COMPLETELY = True
@@ -114,10 +114,10 @@ COMPRESS_CSS = {
     'detail': {
          'source_filenames': (
             'css/master.css',
-            'css/gallery.css',  
-            'css/history.css', 
+            'css/gallery.css',
+            'css/history.css',
             'css/summary.css',
-            'css/html.css',             
+            'css/html.css',
             'css/jquery.autocomplete.css',
             'css/dialogs.css',
         ),
@@ -125,53 +125,53 @@ COMPRESS_CSS = {
     },
     'listing': {
         'source_filenames': (
-            'css/filelist.css', 
-        ),             
+            'css/filelist.css',
+        ),
         'output_filename': 'compressed/listing_styles_?.css',
      }
 }
+
 COMPRESS_JS = {
     # everything except codemirror
     'detail': {
         'source_filenames': (
-                'js/jquery-1.4.2.min.js', 
-                'js/jquery.autocomplete.js', 
+                'js/jquery-1.4.2.min.js',
+                'js/jquery.autocomplete.js',
                 'js/jquery.blockui.js',
-                'js/jquery.elastic.js',                
+                'js/jquery.elastic.js',
                 'js/button_scripts.js',
                 'js/slugify.js',
-                
+
                 # wiki scripts
                 'js/wiki/wikiapi.js',
                 'js/wiki/base.js',
                 'js/wiki/xslt.js',
-                
+
                 # dialogs
                 'js/wiki/save_dialog.js',
-                
+
                 # views
                 'js/wiki/history_view.js',
                 'js/wiki/summary_view.js',
                 'js/wiki/source_editor.js',
                 'js/wiki/wysiwyg_editor.js',
-                'js/wiki/scan_gallery.js',                
+                'js/wiki/scan_gallery.js',
                 'js/wiki/diff_view.js',
-                
+
                 # bootstrap
                 'js/wiki/main.js',
-        ),             
+        ),
         'output_filename': 'compressed/detail_scripts_?.js',
      },
     'listing': {
         'source_filenames': (
-                'js/jquery-1.4.2.min.js', 
-                'js/slugify.js',                
-        ),             
+                'js/jquery-1.4.2.min.js',
+                'js/slugify.js',
+        ),
         'output_filename': 'compressed/listing_scripts_?.js',
      }
 }
+
 COMPRESS = True
 COMPRESS_CSS_FILTERS = None
 COMPRESS_JS_FILTERS = None
@@ -190,13 +190,13 @@ INSTALLED_APPS = (
 
     'django_nose',
     'debug_toolbar',
-    
+
     'compress',
     'south',
     'sorl.thumbnail',
     'filebrowser',
 
-    'wiki',    
+    'wiki',
     'toolbar',
 )
 
@@ -212,7 +212,7 @@ NOSE_ARGS = (
     '--cover-package=' + ','.join(TEST_MODULES),
     '-d',
     '--with-coverage',
-    '--with-doctest'
+    '--with-doctest',
 )
 
 
@@ -232,14 +232,14 @@ except ImportError:
     pass
 
 try:
-    LOGGING_CONFIG_FILE 
+    LOGGING_CONFIG_FILE
 except NameError:
-    LOGGING_CONFIG_FILE = os.path.join(PROJECT_ROOT, 'config', 
+    LOGGING_CONFIG_FILE = os.path.join(PROJECT_ROOT, 'config',
                                 ('logging.cfg' if not DEBUG else 'logging.cfg.dev'))
 try:
     import logging
     import logging.config
-    
-    logging.config.fileConfig(LOGGING_CONFIG_FILE)    
+
+    logging.config.fileConfig(LOGGING_CONFIG_FILE)
 except ImportError, exc:
-    raise
\ No newline at end of file
+    raise
index c31e145..d875a6e 100644 (file)
@@ -8,8 +8,8 @@ admin.autodiscover()
 
 urlpatterns = patterns('',
     # Auth
-    url(r'^accounts/login/$', 'django_cas.views.login', name = 'login'),
-    url(r'^accounts/logout/$', 'django_cas.views.logout', name = 'logout'),
+    url(r'^accounts/login/$', 'django_cas.views.login', name='login'),
+    url(r'^accounts/logout/$', 'django_cas.views.logout', name='logout'),
 
     # Admin panel
     (r'^admin/filebrowser/', include('filebrowser.urls')),
index 3266e09..764e8e5 100644 (file)
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import sys
 import os
@@ -20,13 +20,12 @@ def crop(image, top=0, right=0, bottom=0, left=0):
         bottom = int(height * bottom)
     if left < 1:
         left = int(width * left)
-    
+
     bounds = (int(left), int(top), int(width - right), int(height - bottom))
     image = image.crop(bounds)
     image.load()
     return image
 
-
 output_dir = realpath(os.getcwd()) + '/output'
 bounds = [float(i) for i in sys.argv[1].split(':')]
 
@@ -37,6 +36,6 @@ for file_name in sys.argv[2:]:
     except IOError, e:
         sys.stderr.write('\nerror:%s:%s\n' % (file_name, e.message))
         continue
-    
+
     image = crop(image, *bounds)
-    image.save(output_dir + '/' + basename(file_name))
\ No newline at end of file
+    image.save(output_dir + '/' + basename(file_name))
index 3a7cfa9..de2354e 100644 (file)
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 #
 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
-# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.  
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 import sys
 import os
@@ -36,7 +36,7 @@ def ratio(image):
     """Return width to height ratio of image."""
     width, height = image.size
     return float(width) / height
-    
+
 
 def try_creating(directory):
     try:
@@ -61,16 +61,16 @@ for file_name in sys.argv[1:]:
     except IOError, e:
         sys.stderr.write('\nerror:%s:%s\n' % (file_name, e.message))
         continue
-    
+
     # Check ratio
     if ratio(image) > 1:
         images = [crop(image, 0.6), crop(image, 0.6, from_right=True)]
     else:
         images = [image]
-    
+
     for i, image in enumerate(images):
         image_name = '%s.%d.png' % (basename(base_name), i)
-        
+
         # Save files
         small_image = resize(image, 640, 960)
         small_image = small_image.convert('L')
@@ -83,7 +83,7 @@ for file_name in sys.argv[1:]:
             tmp_output_dir + '/' + image_name,
         ))
         os.remove(tmp_output_dir + '/' + image_name)
-        
+
         # big_image = resize(image, 960, 1440)
         # big_image = big_image.convert('L')
         # big_image = big_image.filter(ImageFilter.SHARPEN)
@@ -93,7 +93,7 @@ for file_name in sys.argv[1:]:
         #     tmp_output_dir + '/' + image_name,
         # ))
         # os.remove(tmp_output_dir + '/' + image_name)
-        
+
     sys.stderr.write('.')
 
 shutil.rmtree(tmp_output_dir)
index 9c658b7..199329e 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -4,18 +4,20 @@
 import os
 from distutils.core import setup
 
+RESOURCE_PATHS = ('templates', 'static', 'media', 'locale', 'config')
+
+
 def is_package(path):
-    return (
-        os.path.isdir(path) and
-        os.path.isfile(os.path.join(path, '__init__.py'))
-        )
+    return os.path.isdir(path) \
+       and os.path.isfile(os.path.join(path, '__init__.py'))
 
-def find_packages(path, base="" ):
+
+def find_packages(path, base=""):
     """ Find all packages in path """
     packages = {}
     for item in os.listdir(path):
         dir = os.path.join(path, item)
-        if is_package( dir ):
+        if is_package(dir):
             if base:
                 module_name = "%(base)s.%(item)s" % vars()
             else:
@@ -24,50 +26,53 @@ def find_packages(path, base="" ):
             packages.update(find_packages(dir, module_name))
     return packages
 
+
 def files_from(*paths, **kwargs):
-    base = kwargs.pop('base')   
+    base = kwargs.pop('base')
+
     def generator():
         for path in paths:
-            path = os.path.join(base, path)            
-            if not os.path.isdir(path) or is_package(path): continue
-                        
-            for dir, _, files in os.walk(path):                            
-                for file in files:                                       
-                    yield os.path.relpath(os.path.join(dir, file),base)
-                    
+            path = os.path.join(base, path)
+            if not os.path.isdir(path) or is_package(path):
+                continue
+
+            for dir, _, files in os.walk(path):
+                for file in files:
+                    yield os.path.relpath(os.path.join(dir, file), base)
+
     return list(generator())
 
-RESOURCE_PATHS = ('templates', 'static', 'media', 'locale', 'config')
 
-def django_setup(project, apps=[], apps_dir='apps', package_dir = {}, packages = [], package_data = {}, **kwargs):
-    
+def django_setup(project, apps=[], apps_dir='apps', package_dir={}, packages=[], package_data={}, **kwargs):
+
     # directories
-    extra_dirs = dict( (app, os.path.join(apps_dir,app)) for app in apps )
+    extra_dirs = dict((app, os.path.join(apps_dir, app)) for app in apps)
     extra_dirs[project] = project
     package_dir.update(extra_dirs)
-    
+
     # applications
     packages.extend(apps)
-    # with all subpackages 
+    # with all subpackages
     for app in apps:
         packages.extend(find_packages(os.path.join(apps_dir, app), base=app))
     # and the project
     packages.append(project)
-    
-    # extra data        
+
+    # extra data
     extra_data = {}
     for app in apps:
-        extra_data[app] = files_from(*RESOURCE_PATHS, base=os.path.join(apps_dir, app))        
+        extra_data[app] = files_from(*RESOURCE_PATHS, base=os.path.join(apps_dir, app))
     extra_data[project] = files_from(*RESOURCE_PATHS, base=project)
-    package_data.update(extra_data)   
-    
+    package_data.update(extra_data)
+
     return setup(
-                package_dir = package_dir, 
-                packages = packages, 
-                package_data = package_data, **kwargs)
-    
+                package_dir=package_dir,
+                packages=packages,
+                package_data=package_data, **kwargs)
+
+
 #
-# The reald stuff :)
+# The real stuff :)
 #
 django_setup(
     name='fnp-redakcja',
@@ -76,31 +81,29 @@ django_setup(
     author="Fundacja Nowoczesna Polska",
     author_email='fundacja@nowoczesnapolska.org.pl',
     license="GNU Affero General Public License 3",
-    maintainer='Łukasz Rekucki',    
+    maintainer='Łukasz Rekucki',
     maintainer_email='lrekucki@gmail.com',
     url='http://github.com/fnp/redakcja',
-    package_dir = {'': 'lib'},           
-    py_modules = [ 
+    package_dir={'': 'lib'},
+    py_modules=[
         'wlapi',
-        'vstorage',    
-    ],      
+        'vstorage',
+    ],
     scripts=[
-        'scripts/crop.py', 
+        'scripts/crop.py',
         'scripts/imgconv.py',
-    ],             
+    ],
     # django applications
-    project = 'platforma',
-    apps_dir = 'apps',
-    apps = [
+    project='platforma',
+    apps_dir='apps',
+    apps=[
         'compress',
-        'django_cas',   
+        'django_cas',
         'filebrowser',
         'toolbar',
-        'wiki',        
+        'wiki',
     ],
-    requires = [
+    requires=[
         "librarian (>=1.3)",
-        "Django (>=1.1.1,<1.2)",        
-    ]
-    # data_files=[ ('', ['LICENSE', 'NOTICE', 'README.rst', 'AUTHORS.md', 'requirements.txt'])],
-)
+        "Django (>=1.1.1,<1.2)",
+    ])