Changeset 3444

Show
Ignore:
Timestamp:
10/26/08 20:39:19 (15 years ago)
Author:
jerome
Message:

Doesn't break when there's an error retrieving the login name (when run
through sudo). Fixes #29.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pykota/branches/1.26_fixes/pykota/storage.py

    r3133 r3444  
    1414# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1515# GNU General Public License for more details. 
    16 #  
     16# 
    1717# You should have received a copy of the GNU General Public License 
    1818# along with this program; if not, write to the Free Software 
     
    3737        return self.message 
    3838    __str__ = __repr__ 
    39          
    40          
     39 
     40 
    4141class StorageObject : 
    4242    """Object present in the database.""" 
     
    4848        self.isDirty = False 
    4949        self.Exists = False 
    50          
     50 
    5151    def setDescription(self, description=None) : 
    5252        """Sets the object's description.""" 
    5353        if description is not None : 
    5454            self.Description = str(description) 
    55             self.isDirty = True     
    56              
    57     def save(self) :         
     55            self.isDirty = True 
     56 
     57    def save(self) : 
    5858        """Saves the object to the database.""" 
    5959        if self.isDirty : 
    6060            getattr(self.parent, "save%s" % self.__class__.__name__[7:])(self) 
    6161            self.isDirty = False 
    62              
    63          
    64 class StorageUser(StorageObject) :         
     62 
     63 
     64class StorageUser(StorageObject) : 
    6565    """User class.""" 
    6666    def __init__(self, parent, name) : 
     
    7474        self.Payments = [] # TODO : maybe handle this smartly for SQL, for now just don't retrieve them 
    7575        self.PaymentsBacklog = [] 
    76          
    77     def consumeAccountBalance(self, amount) :      
     76 
     77    def consumeAccountBalance(self, amount) : 
    7878        """Consumes an amount of money from the user's account balance.""" 
    7979        self.parent.decreaseUserAccountBalance(self, amount) 
    8080        self.AccountBalance = float(self.AccountBalance or 0.0) - amount 
    81          
     81 
    8282    def setAccountBalance(self, balance, lifetimepaid, comment="") : 
    8383        """Sets the user's account balance in case he pays more money.""" 
     
    8888            self.PaymentsBacklog.append((diff, comment)) 
    8989        self.isDirty = True 
    90          
    91     def save(self) :     
     90 
     91    def save(self) : 
    9292        """Saves an user and flush its payments backlog.""" 
    9393        for (value, comment) in self.PaymentsBacklog : 
    9494            self.parent.writeNewPayment(self, value, comment) 
    95         self.PaymentsBacklog = []     
    96         StorageObject.save(self)     
    97          
    98     def setLimitBy(self, limitby) :     
     95        self.PaymentsBacklog = [] 
     96        StorageObject.save(self) 
     97 
     98    def setLimitBy(self, limitby) : 
    9999        """Sets the user's limiting factor.""" 
    100100        try : 
    101101            limitby = limitby.lower() 
    102         except AttributeError :     
     102        except AttributeError : 
    103103            limitby = "quota" 
    104104        if limitby in ["quota", "balance", \ 
     
    106106            self.LimitBy = limitby 
    107107            self.isDirty = True 
    108          
    109     def setOverChargeFactor(self, factor) :     
     108 
     109    def setOverChargeFactor(self, factor) : 
    110110        """Sets the user's overcharging coefficient.""" 
    111111        self.OverCharge = factor 
    112112        self.isDirty = True 
    113          
    114     def setEmail(self, email) :     
     113 
     114    def setEmail(self, email) : 
    115115        """Sets the user's email address.""" 
    116116        self.Email = email 
    117117        self.isDirty = True 
    118          
    119     def delete(self) :     
     118 
     119    def delete(self) : 
    120120        """Deletes an user from the database.""" 
    121121        self.parent.deleteUser(self) 
     
    126126                    self.parent.flushEntry("USERPQUOTAS", "%s@%s" % (v.User.Name, v.Printer.Name)) 
    127127        self.Exists = False 
    128         self.isDirty = False             
    129          
     128        self.isDirty = False 
     129 
    130130    def refund(self, amount, reason) : 
    131131        """Refunds a number of credits to an user.""" 
    132132        self.consumeAccountBalance(-amount) 
    133133        self.parent.writeNewPayment(self, -amount, reason) 
    134          
    135          
    136 class StorageGroup(StorageObject) :         
     134 
     135 
     136class StorageGroup(StorageObject) : 
    137137    """User class.""" 
    138138    def __init__(self, parent, name) : 
     
    142142        self.AccountBalance = None 
    143143        self.LifeTimePaid = None 
    144          
    145     def setLimitBy(self, limitby) :     
     144 
     145    def setLimitBy(self, limitby) : 
    146146        """Sets the user's limiting factor.""" 
    147147        try : 
    148148            limitby = limitby.lower() 
    149         except AttributeError :     
     149        except AttributeError : 
    150150            limitby = "quota" 
    151151        if limitby in ["quota", "balance", "noquota"] : 
    152152            self.LimitBy = limitby 
    153153            self.isDirty = True 
    154          
     154 
    155155    def addUserToGroup(self, user) : 
    156156        """Adds an user to an users group.""" 
    157157        self.parent.addUserToGroup(user, self) 
    158          
     158 
    159159    def delUserFromGroup(self, user) : 
    160160        """Removes an user from an users group.""" 
    161161        self.parent.delUserFromGroup(user, self) 
    162          
    163     def delete(self) :     
     162 
     163    def delete(self) : 
    164164        """Deletes a group from the database.""" 
    165165        self.parent.deleteGroup(self) 
     
    170170                    self.parent.flushEntry("GROUPPQUOTAS", "%s@%s" % (v.Group.Name, v.Printer.Name)) 
    171171        self.Exists = False 
    172         self.isDirty = False             
    173          
    174          
     172        self.isDirty = False 
     173 
     174 
    175175class StoragePrinter(StorageObject) : 
    176176    """Printer class.""" 
     
    182182        self.MaxJobSize = None 
    183183        self.PassThrough = None 
    184          
    185     def __getattr__(self, name) :     
     184 
     185    def __getattr__(self, name) : 
    186186        """Delays data retrieval until it's really needed.""" 
    187         if name == "LastJob" :  
     187        if name == "LastJob" : 
    188188            self.LastJob = self.parent.getPrinterLastJob(self) 
    189189            self.parent.tool.logdebug("Lazy retrieval of last job for printer %s" % self.Name) 
    190190            return self.LastJob 
    191         elif name == "Coefficients" :     
     191        elif name == "Coefficients" : 
    192192            self.Coefficients = self.parent.tool.config.getPrinterCoefficients(self.Name) 
    193193            self.parent.tool.logdebug("Lazy retrieval of coefficients for printer %s : %s" % (self.Name, self.Coefficients)) 
     
    195195        else : 
    196196            raise AttributeError, name 
    197              
     197 
    198198    def addJobToHistory(self, jobid, user, pagecounter, action, jobsize=None, jobprice=None, filename=None, title=None, copies=None, options=None, clienthost=None, jobsizebytes=None, jobmd5sum=None, jobpages=None, jobbilling=None, precomputedsize=None, precomputedprice=None) : 
    199199        """Adds a job to the printer's history.""" 
    200200        self.parent.writeJobNew(self, user, jobid, pagecounter, action, jobsize, jobprice, filename, title, copies, options, clienthost, jobsizebytes, jobmd5sum, jobpages, jobbilling, precomputedsize, precomputedprice) 
    201201        # TODO : update LastJob object ? Probably not needed. 
    202          
    203     def addPrinterToGroup(self, printer) :     
     202 
     203    def addPrinterToGroup(self, printer) : 
    204204        """Adds a printer to a printer group.""" 
    205205        if (printer not in self.parent.getParentPrinters(self)) and (printer.ident != self.ident) : 
    206206            self.parent.writePrinterToGroup(self, printer) 
    207207            # TODO : reset cached value for printer parents, or add new parent to cached value 
    208              
    209     def delPrinterFromGroup(self, printer) :     
     208 
     209    def delPrinterFromGroup(self, printer) : 
    210210        """Deletes a printer from a printer group.""" 
    211211        self.parent.removePrinterFromGroup(self, printer) 
    212212        # TODO : reset cached value for printer parents, or add new parent to cached value 
    213          
    214     def setPrices(self, priceperpage = None, priceperjob = None) :     
     213 
     214    def setPrices(self, priceperpage = None, priceperjob = None) : 
    215215        """Sets the printer's prices.""" 
    216216        if priceperpage is None : 
    217217            priceperpage = self.PricePerPage or 0.0 
    218         else :     
     218        else : 
    219219            self.PricePerPage = float(priceperpage) 
    220         if priceperjob is None :     
     220        if priceperjob is None : 
    221221            priceperjob = self.PricePerJob or 0.0 
    222         else :     
     222        else : 
    223223            self.PricePerJob = float(priceperjob) 
    224         self.isDirty = True     
    225          
     224        self.isDirty = True 
     225 
    226226    def setPassThrough(self, passthrough) : 
    227227        """Sets the printer's passthrough mode.""" 
    228228        self.PassThrough = passthrough 
    229229        self.isDirty = True 
    230          
     230 
    231231    def setMaxJobSize(self, maxjobsize) : 
    232232        """Sets the printer's maximal job size.""" 
    233233        self.MaxJobSize = maxjobsize 
    234234        self.isDirty = True 
    235          
    236     def delete(self) :     
     235 
     236    def delete(self) : 
    237237        """Deletes a printer from the database.""" 
    238238        self.parent.deletePrinter(self) 
     
    246246                    self.parent.flushEntry("GROUPPQUOTAS", "%s@%s" % (v.Group.Name, v.Printer.Name)) 
    247247        self.Exists = False 
    248         self.isDirty = False             
    249          
    250          
     248        self.isDirty = False 
     249 
     250 
    251251class StorageUserPQuota(StorageObject) : 
    252252    """User Print Quota class.""" 
     
    262262        self.WarnCount = None 
    263263        self.MaxJobSize = None 
    264          
    265     def __getattr__(self, name) :     
     264 
     265    def __getattr__(self, name) : 
    266266        """Delays data retrieval until it's really needed.""" 
    267         if name == "ParentPrintersUserPQuota" :  
     267        if name == "ParentPrintersUserPQuota" : 
    268268            self.ParentPrintersUserPQuota = (self.User.Exists and self.Printer.Exists and self.parent.getParentPrintersUserPQuota(self)) or [] 
    269269            return self.ParentPrintersUserPQuota 
    270270        else : 
    271271            raise AttributeError, name 
    272          
    273     def setDateLimit(self, datelimit) :     
     272 
     273    def setDateLimit(self, datelimit) : 
    274274        """Sets the date limit for this quota.""" 
    275275        datelimit = DateTime.ISO.ParseDateTime(str(datelimit)[:19]) 
     
    277277        self.parent.writeUserPQuotaDateLimit(self, date) 
    278278        self.DateLimit = date 
    279          
    280     def setLimits(self, softlimit, hardlimit) :     
     279 
     280    def setLimits(self, softlimit, hardlimit) : 
    281281        """Sets the soft and hard limit for this quota.""" 
    282282        self.SoftLimit = softlimit 
     
    285285        self.WarnCount = 0 
    286286        self.isDirty = True 
    287          
     287 
    288288    def setUsage(self, used) : 
    289289        """Sets the PageCounter and LifePageCounter to used, or if used is + or - prefixed, changes the values of {Life,}PageCounter by that amount.""" 
     
    302302        self.parent.increaseUserPQuotaWarnCount(self) 
    303303        self.WarnCount = (self.WarnCount or 0) + 1 
    304          
     304 
    305305    def resetDenyBannerCounter(self) : 
    306306        """Resets the deny banner counter for this user quota.""" 
    307307        self.parent.writeUserPQuotaWarnCount(self, 0) 
    308308        self.WarnCount = 0 
    309          
    310     def reset(self) :     
     309 
     310    def reset(self) : 
    311311        """Resets page counter to 0.""" 
    312312        self.PageCounter = 0 
    313313        self.DateLimit = None 
    314314        self.isDirty = True 
    315          
    316     def hardreset(self) :     
     315 
     316    def hardreset(self) : 
    317317        """Resets actual and life time page counters to 0.""" 
    318318        self.PageCounter = self.LifePageCounter = 0 
    319319        self.DateLimit = None 
    320320        self.isDirty = True 
    321          
    322     def computeJobPrice(self, jobsize, inkusage=[]) :     
     321 
     322    def computeJobPrice(self, jobsize, inkusage=[]) : 
    323323        """Computes the job price as the sum of all parent printers' prices + current printer's ones.""" 
    324         totalprice = 0.0     
     324        totalprice = 0.0 
    325325        if jobsize : 
    326326            if self.User.OverCharge != 0.0 :    # optimization, but TODO : beware of rounding errors 
     
    330330                    if not inkusage : 
    331331                        totalprice += (jobsize * pageprice) 
    332                     else :     
     332                    else : 
    333333                        for pageindex in range(jobsize) : 
    334334                            try : 
    335335                                usage = inkusage[pageindex] 
    336                             except IndexError :     
     336                            except IndexError : 
    337337                                self.parent.tool.logdebug("No ink usage information. Using base cost of %f credits for page %i." % (pageprice, pageindex+1)) 
    338338                                totalprice += pageprice 
    339                             else :     
     339                            else : 
    340340                                coefficients = self.Printer.Coefficients 
    341341                                for (ink, value) in usage.items() : 
     
    346346                                    totalprice += inkprice 
    347347        if self.User.OverCharge != 1.0 : # TODO : beware of rounding errors 
    348             overcharged = totalprice * self.User.OverCharge         
     348            overcharged = totalprice * self.User.OverCharge 
    349349            self.parent.tool.logdebug("Overcharging %s by a factor of %s ===> User %s will be charged for %s credits." % (totalprice, self.User.OverCharge, self.User.Name, overcharged)) 
    350350            return overcharged 
    351         else :     
     351        else : 
    352352            return totalprice 
    353              
     353 
    354354    def increasePagesUsage(self, jobsize, inkusage=[]) : 
    355355        """Increase the value of used pages and money.""" 
     
    363363                upq.LifePageCounter = int(upq.LifePageCounter or 0) + jobsize 
    364364        return jobprice 
    365          
    366     def delete(self) :     
     365 
     366    def delete(self) : 
    367367        """Deletes an user print quota entry from the database.""" 
    368368        self.parent.deleteUserPQuota(self) 
     
    371371        self.Exists = False 
    372372        self.isDirty = False 
    373          
    374     def refund(self, nbpages) :     
     373 
     374    def refund(self, nbpages) : 
    375375        """Refunds a number of pages to an user on a particular printer.""" 
    376376        self.parent.increaseUserPQuotaPagesCounters(self, -nbpages) 
    377377        self.PageCounter = int(self.PageCounter or 0) - nbpages 
    378378        self.LifePageCounter = int(self.LifePageCounter or 0) - nbpages 
    379          
    380          
     379 
     380 
    381381class StorageGroupPQuota(StorageObject) : 
    382382    """Group Print Quota class.""" 
     
    391391        self.DateLimit = None 
    392392        self.MaxJobSize = None 
    393          
    394     def __getattr__(self, name) :     
     393 
     394    def __getattr__(self, name) : 
    395395        """Delays data retrieval until it's really needed.""" 
    396         if name == "ParentPrintersGroupPQuota" :  
     396        if name == "ParentPrintersGroupPQuota" : 
    397397            self.ParentPrintersGroupPQuota = (self.Group.Exists and self.Printer.Exists and self.parent.getParentPrintersGroupPQuota(self)) or [] 
    398398            return self.ParentPrintersGroupPQuota 
    399399        else : 
    400400            raise AttributeError, name 
    401          
    402     def reset(self) :     
     401 
     402    def reset(self) : 
    403403        """Resets page counter to 0.""" 
    404404        for user in self.parent.getGroupMembers(self.Group) : 
     
    409409        self.DateLimit = None 
    410410        self.isDirty = True 
    411          
    412     def hardreset(self) :     
     411 
     412    def hardreset(self) : 
    413413        """Resets actual and life time page counters to 0.""" 
    414414        for user in self.parent.getGroupMembers(self.Group) : 
     
    419419        self.DateLimit = None 
    420420        self.isDirty = True 
    421          
    422     def setDateLimit(self, datelimit) :     
     421 
     422    def setDateLimit(self, datelimit) : 
    423423        """Sets the date limit for this quota.""" 
    424424        datelimit = DateTime.ISO.ParseDateTime(str(datelimit)[:19]) 
     
    431431        self.parent.writeGroupPQuotaDateLimit(self, date) 
    432432        self.DateLimit = date 
    433          
    434     def setLimits(self, softlimit, hardlimit) :     
     433 
     434    def setLimits(self, softlimit, hardlimit) : 
    435435        """Sets the soft and hard limit for this quota.""" 
    436436        self.SoftLimit = softlimit 
     
    438438        self.DateLimit = None 
    439439        self.isDirty = True 
    440          
    441     def delete(self) :     
     440 
     441    def delete(self) : 
    442442        """Deletes a group print quota entry from the database.""" 
    443443        self.parent.deleteGroupPQuota(self) 
     
    446446        self.Exists = False 
    447447        self.isDirty = False 
    448          
    449          
     448 
     449 
    450450class StorageJob(StorageObject) : 
    451451    """Printer's Job class.""" 
     
    471471        self.PrecomputedJobSize = None 
    472472        self.PrecomputedJobPrice = None 
    473          
    474     def __getattr__(self, name) :     
     473 
     474    def __getattr__(self, name) : 
    475475        """Delays data retrieval until it's really needed.""" 
    476         if name == "User" :  
     476        if name == "User" : 
    477477            self.User = self.parent.getUser(self.UserName) 
    478478            return self.User 
    479         elif name == "Printer" :     
     479        elif name == "Printer" : 
    480480            self.Printer = self.parent.getPrinter(self.PrinterName) 
    481481            return self.Printer 
    482482        else : 
    483483            raise AttributeError, name 
    484              
    485     def refund(self, reason) :         
     484 
     485    def refund(self, reason) : 
    486486        """Refund a particular print job.""" 
    487487        if (not self.JobSize) or (self.JobAction in ("DENY", "CANCEL", "REFUND")) : 
    488488            return 
    489              
     489        try : 
     490            loginname = os.getlogin() 
     491        except OSError : 
     492            import pwd 
     493            loginname = pwd.getpwuid(os.getuid()).pw_name 
    490494        basereason = _("Refunded %i pages and %.3f credits by %s (%s) on %s") \ 
    491495                        % (self.JobSize, 
    492496                           self.JobPrice, 
    493497                           self.parent.tool.originalUserName, 
    494                            os.getlogin(), 
     498                           loginname, 
    495499                           str(DateTime.now())[:19]) 
    496         if reason :                                                
     500        if reason : 
    497501            reason = "%s : %s" % (basereason, reason) 
    498         else :     
     502        else : 
    499503            reason = basereason 
    500         self.parent.tool.logdebug("Refunding job %s..." % self.ident)     
     504        self.parent.tool.logdebug("Refunding job %s..." % self.ident) 
    501505        self.parent.beginTransaction() 
    502506        try : 
     
    504508                bcode = self.parent.getBillingCode(self.JobBillingCode) 
    505509                bcode.refund(self.JobSize, self.JobPrice) 
    506                  
     510 
    507511            if self.User.Exists : 
    508512                self.User.refund(self.JobPrice, reason) 
    509                 if self.Printer.Exists :     
    510                     upq = self.parent.getUserPQuota(self.User, self.Printer)     
     513                if self.Printer.Exists : 
     514                    upq = self.parent.getUserPQuota(self.User, self.Printer) 
    511515                    if upq.Exists : 
    512516                        upq.refund(self.JobSize) 
    513517            self.parent.refundJob(self.ident) 
    514         except :         
     518        except : 
    515519            self.parent.rollbackTransaction() 
    516520            self.parent.tool.logdebug("Error while refunding job %s." % self.ident) 
    517521            raise 
    518         else :     
     522        else : 
    519523            self.parent.commitTransaction() 
    520524            self.parent.tool.logdebug("Job %s refunded." % self.ident) 
    521          
    522          
     525 
     526 
    523527class StorageLastJob(StorageJob) : 
    524528    """Printer's Last Job class.""" 
     
    527531        self.PrinterName = printer.Name # not needed 
    528532        self.Printer = printer 
    529          
    530          
     533 
     534 
    531535class StorageBillingCode(StorageObject) : 
    532536    """Billing code class.""" 
     
    536540        self.PageCounter = None 
    537541        self.Balance = None 
    538          
    539     def delete(self) :     
     542 
     543    def delete(self) : 
    540544        """Deletes the billing code from the database.""" 
    541545        self.parent.deleteBillingCode(self) 
     
    543547        self.isDirty = False 
    544548        self.Exists = False 
    545          
    546     def reset(self, balance=0.0, pagecounter=0) :     
     549 
     550    def reset(self, balance=0.0, pagecounter=0) : 
    547551        """Resets the pagecounter and balance for this billing code.""" 
    548552        self.Balance = balance 
    549553        self.PageCounter = pagecounter 
    550554        self.isDirty = True 
    551          
     555 
    552556    def consume(self, pages, price) : 
    553557        """Consumes some pages and credits for this billing code.""" 
     
    556560            self.PageCounter += pages 
    557561            self.Balance -= price 
    558             
     562 
    559563    def refund(self, pages, price) : 
    560564        """Refunds a particular billing code.""" 
    561565        self.consume(-pages, -price) 
    562          
    563          
     566 
     567 
    564568class BaseStorage : 
    565569    def __init__(self, pykotatool) : 
     
    582586                            "LASTJOBS" : {}, \ 
    583587                            "BILLINGCODES" : {} } 
    584          
    585     def close(self) :     
     588 
     589    def close(self) : 
    586590        """Must be overriden in children classes.""" 
    587591        raise RuntimeError, "BaseStorage.close() must be overriden !" 
    588          
    589     def __del__(self) :         
     592 
     593    def __del__(self) : 
    590594        """Ensures that the database connection is closed.""" 
    591595        self.close() 
    592          
     596 
    593597    def getFromCache(self, cachetype, key) : 
    594598        """Tries to extract something from the cache.""" 
     
    597601            if entry is not None : 
    598602                self.tool.logdebug("Cache hit (%s->%s)" % (cachetype, key)) 
    599             else :     
     603            else : 
    600604                self.tool.logdebug("Cache miss (%s->%s)" % (cachetype, key)) 
    601             return entry     
    602              
    603     def cacheEntry(self, cachetype, key, value) :         
     605            return entry 
     606 
     607    def cacheEntry(self, cachetype, key, value) : 
    604608        """Puts an entry in the cache.""" 
    605609        if self.usecache and getattr(value, "Exists", 0) : 
    606610            self.caches[cachetype][key] = value 
    607611            self.tool.logdebug("Cache store (%s->%s)" % (cachetype, key)) 
    608              
    609     def flushEntry(self, cachetype, key) :         
     612 
     613    def flushEntry(self, cachetype, key) : 
    610614        """Removes an entry from the cache.""" 
    611615        if self.usecache : 
    612616            try : 
    613617                del self.caches[cachetype][key] 
    614             except KeyError :     
     618            except KeyError : 
    615619                pass 
    616             else :     
     620            else : 
    617621                self.tool.logdebug("Cache flush (%s->%s)" % (cachetype, key)) 
    618              
    619     def getUser(self, username) :         
     622 
     623    def getUser(self, username) : 
    620624        """Returns the user from cache.""" 
    621625        user = self.getFromCache("USERS", username) 
     
    623627            user = self.getUserFromBackend(username) 
    624628            self.cacheEntry("USERS", username, user) 
    625         return user     
    626          
    627     def getGroup(self, groupname) :         
     629        return user 
     630 
     631    def getGroup(self, groupname) : 
    628632        """Returns the group from cache.""" 
    629633        group = self.getFromCache("GROUPS", groupname) 
     
    631635            group = self.getGroupFromBackend(groupname) 
    632636            self.cacheEntry("GROUPS", groupname, group) 
    633         return group     
    634          
    635     def getPrinter(self, printername) :         
     637        return group 
     638 
     639    def getPrinter(self, printername) : 
    636640        """Returns the printer from cache.""" 
    637641        printer = self.getFromCache("PRINTERS", printername) 
     
    639643            printer = self.getPrinterFromBackend(printername) 
    640644            self.cacheEntry("PRINTERS", printername, printer) 
    641         return printer     
    642          
    643     def getUserPQuota(self, user, printer) :         
     645        return printer 
     646 
     647    def getUserPQuota(self, user, printer) : 
    644648        """Returns the user quota information from cache.""" 
    645649        useratprinter = "%s@%s" % (user.Name, printer.Name) 
     
    648652            upquota = self.getUserPQuotaFromBackend(user, printer) 
    649653            self.cacheEntry("USERPQUOTAS", useratprinter, upquota) 
    650         return upquota     
    651          
    652     def getGroupPQuota(self, group, printer) :         
     654        return upquota 
     655 
     656    def getGroupPQuota(self, group, printer) : 
    653657        """Returns the group quota information from cache.""" 
    654658        groupatprinter = "%s@%s" % (group.Name, printer.Name) 
     
    657661            gpquota = self.getGroupPQuotaFromBackend(group, printer) 
    658662            self.cacheEntry("GROUPPQUOTAS", groupatprinter, gpquota) 
    659         return gpquota     
    660          
    661     def getPrinterLastJob(self, printer) :         
     663        return gpquota 
     664 
     665    def getPrinterLastJob(self, printer) : 
    662666        """Extracts last job information for a given printer from cache.""" 
    663667        lastjob = self.getFromCache("LASTJOBS", printer.Name) 
     
    665669            lastjob = self.getPrinterLastJobFromBackend(printer) 
    666670            self.cacheEntry("LASTJOBS", printer.Name, lastjob) 
    667         return lastjob     
    668          
    669     def getBillingCode(self, label) :         
     671        return lastjob 
     672 
     673    def getBillingCode(self, label) : 
    670674        """Returns the user from cache.""" 
    671675        code = self.getFromCache("BILLINGCODES", label) 
     
    674678            self.cacheEntry("BILLINGCODES", label, code) 
    675679        return code 
    676          
    677     def getParentPrinters(self, printer) :     
     680 
     681    def getParentPrinters(self, printer) : 
    678682        """Extracts parent printers information for a given printer from cache.""" 
    679683        if self.usecache : 
     
    684688            else : 
    685689                self.tool.logdebug("Cache hit (%s->Parents)" % printer.Name) 
    686         else :         
     690        else : 
    687691            printer.Parents = self.getParentPrintersFromBackend(printer) 
    688         for parent in printer.Parents[:] :     
     692        for parent in printer.Parents[:] : 
    689693            printer.Parents.extend(self.getParentPrinters(parent)) 
    690         uniquedic = {}     
     694        uniquedic = {} 
    691695        for parent in printer.Parents : 
    692696            uniquedic[parent.Name] = parent 
    693         printer.Parents = uniquedic.values()     
     697        printer.Parents = uniquedic.values() 
    694698        return printer.Parents 
    695          
    696     def getGroupMembers(self, group) :         
     699 
     700    def getGroupMembers(self, group) : 
    697701        """Returns the group's members list from in-group cache.""" 
    698702        if self.usecache : 
     
    703707            else : 
    704708                self.tool.logdebug("Cache hit (%s->Members)" % group.Name) 
    705         else :         
     709        else : 
    706710            group.Members = self.getGroupMembersFromBackend(group) 
    707         return group.Members     
    708          
    709     def getUserGroups(self, user) :         
     711        return group.Members 
     712 
     713    def getUserGroups(self, user) : 
    710714        """Returns the user's groups list from in-user cache.""" 
    711715        if self.usecache : 
     
    716720            else : 
    717721                self.tool.logdebug("Cache hit (%s->Groups)" % user.Name) 
    718         else :         
     722        else : 
    719723            user.Groups = self.getUserGroupsFromBackend(user) 
    720         return user.Groups    
    721          
    722     def getParentPrintersUserPQuota(self, userpquota) :      
     724        return user.Groups 
     725 
     726    def getParentPrintersUserPQuota(self, userpquota) : 
    723727        """Returns all user print quota on the printer and all its parents recursively.""" 
    724728        upquotas = [ ] 
     
    727731            if upq.Exists : 
    728732                upquotas.append(upq) 
    729         return upquotas         
    730          
    731     def getParentPrintersGroupPQuota(self, grouppquota) :      
     733        return upquotas 
     734 
     735    def getParentPrintersGroupPQuota(self, grouppquota) : 
    732736        """Returns all group print quota on the printer and all its parents recursively.""" 
    733737        gpquotas = [ ] 
     
    736740            if gpq.Exists : 
    737741                gpquotas.append(gpq) 
    738         return gpquotas         
    739          
     742        return gpquotas 
     743 
    740744    def databaseToUserCharset(self, text) : 
    741745        """Converts from database format (UTF-8) to user's charset.""" 
    742746        return self.tool.UTF8ToUserCharset(text) 
    743          
     747 
    744748    def userCharsetToDatabase(self, text) : 
    745749        """Converts from user's charset to database format (UTF-8).""" 
    746750        return self.tool.userCharsetToUTF8(text) 
    747          
    748     def cleanDates(self, startdate, enddate) :     
     751 
     752    def cleanDates(self, startdate, enddate) : 
    749753        """Clean the dates to create a correct filter.""" 
    750         if startdate :     
     754        if startdate : 
    751755            startdate = startdate.strip().lower() 
    752         if enddate :     
     756        if enddate : 
    753757            enddate = enddate.strip().lower() 
    754         if (not startdate) and (not enddate) :     
     758        if (not startdate) and (not enddate) : 
    755759            return (None, None) 
    756              
    757         now = DateTime.now()     
     760 
     761        now = DateTime.now() 
    758762        nameddates = ('yesterday', 'today', 'now', 'tomorrow') 
    759         datedict = { "start" : startdate, "end" : enddate }     
     763        datedict = { "start" : startdate, "end" : enddate } 
    760764        for limit in datedict.keys() : 
    761765            dateval = datedict[limit] 
     
    765769                        try : 
    766770                            offset = int(dateval[len(name):]) 
    767                         except :     
     771                        except : 
    768772                            offset = 0 
    769                         dateval = dateval[:len(name)]     
     773                        dateval = dateval[:len(name)] 
    770774                        if limit == "start" : 
    771775                            if dateval == "yesterday" : 
     
    787791                                dateval = (now + 1 + offset).Format("%Y%m%d235959") 
    788792                        break 
    789                          
     793 
    790794                if not dateval.isdigit() : 
    791795                    dateval = None 
    792                 else :     
     796                else : 
    793797                    lgdateval = len(dateval) 
    794798                    if lgdateval == 4 : 
    795                         if limit == "start" :  
     799                        if limit == "start" : 
    796800                            dateval = "%s0101 00:00:00" % dateval 
    797                         else :   
     801                        else : 
    798802                            dateval = "%s1231 23:59:59" % dateval 
    799803                    elif lgdateval == 6 : 
    800                         if limit == "start" :  
     804                        if limit == "start" : 
    801805                            dateval = "%s01 00:00:00" % dateval 
    802                         else :   
     806                        else : 
    803807                            mxdate = DateTime.ISO.ParseDateTime("%s01 00:00:00" % dateval) 
    804808                            dateval = "%s%02i 23:59:59" % (dateval, mxdate.days_in_month) 
    805809                    elif lgdateval == 8 : 
    806                         if limit == "start" :  
     810                        if limit == "start" : 
    807811                            dateval = "%s 00:00:00" % dateval 
    808                         else :   
     812                        else : 
    809813                            dateval = "%s 23:59:59" % dateval 
    810814                    elif lgdateval == 10 : 
    811                         if limit == "start" :  
     815                        if limit == "start" : 
    812816                            dateval = "%s %s:00:00" % (dateval[:8], dateval[8:]) 
    813                         else :   
     817                        else : 
    814818                            dateval = "%s %s:59:59" % (dateval[:8], dateval[8:]) 
    815819                    elif lgdateval == 12 : 
    816                         if limit == "start" :  
     820                        if limit == "start" : 
    817821                            dateval = "%s %s:%s:00" % (dateval[:8], dateval[8:10], dateval[10:]) 
    818                         else :   
     822                        else : 
    819823                            dateval = "%s %s:%s:59" % (dateval[:8], dateval[8:10], dateval[10:]) 
    820                     elif lgdateval == 14 :         
     824                    elif lgdateval == 14 : 
    821825                        dateval = "%s %s:%s:%s" % (dateval[:8], dateval[8:10], dateval[10:12], dateval[12:]) 
    822                     else :     
     826                    else : 
    823827                        dateval = None 
    824                     try :     
     828                    try : 
    825829                        DateTime.ISO.ParseDateTime(dateval[:19]) 
    826                     except :     
     830                    except : 
    827831                        dateval = None 
    828                 datedict[limit] = dateval     
     832                datedict[limit] = dateval 
    829833        (start, end) = (datedict["start"], datedict["end"]) 
    830834        if start and end and (start > end) : 
    831835            (start, end) = (end, start) 
    832         try :     
     836        try : 
    833837            if len(start) == 17 : 
    834838                start = "%s-%s-%s %s" % (start[0:4], start[4:6], start[6:8], start[9:]) 
    835         except TypeError :         
     839        except TypeError : 
    836840            pass 
    837              
    838         try :     
     841 
     842        try : 
    839843            if len(end) == 17 : 
    840844                end = "%s-%s-%s %s" % (end[0:4], end[4:6], end[6:8], end[9:]) 
    841         except TypeError :         
     845        except TypeError : 
    842846            pass 
    843              
    844         return (start, end)     
    845          
     847 
     848        return (start, end) 
     849 
    846850def openConnection(pykotatool) : 
    847851    """Returns a connection handle to the appropriate database.""" 
     
    849853    backend = backendinfo["storagebackend"] 
    850854    try : 
    851         storagebackend = imp.load_source("storagebackend",  
     855        storagebackend = imp.load_source("storagebackend", 
    852856                                         os.path.join(os.path.dirname(__file__), 
    853857                                                      "storages", 
     
    855859    except ImportError : 
    856860        raise PyKotaStorageError, _("Unsupported quota storage backend %s") % backend 
    857     else :     
     861    else : 
    858862        host = backendinfo["storageserver"] 
    859863        database = backendinfo["storagename"]