Show
Ignore:
Timestamp:
10/06/08 00:26:54 (16 years ago)
Author:
jerome
Message:

Removed trailing spaces.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • tea4cups/trunk/tea4cups

    r693 r3438  
    11#! /usr/bin/env python 
    2 # -*- coding: ISO-8859-15 -*- 
     2# -*- coding: utf-8 -*- 
    33 
    44# Tea4CUPS : Tee for CUPS 
     
    3535  the Free Software Foundation; either version 2 of the License, or 
    3636  (at your option) any later version. 
    37    
     37 
    3838  This program is distributed in the hope that it will be useful, 
    3939  but WITHOUT ANY WARRANTY; without even the implied warranty of 
    4040  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    4141  GNU General Public License for more details. 
    42    
     42 
    4343  You should have received a copy of the GNU General Public License 
    4444  along with this program; if not, write to the Free Software 
     
    4949 
    5050  Copy the different files where they belong : 
    51    
     51 
    5252    $ cp tea4cups /usr/lib/cups/backend/ 
    5353    $ chown root.root /usr/lib/cups/backend/tea4cups 
    5454    $ chmod 700 /usr/lib/cups/backend/tea4cups 
    5555    $ cp tea4cups.conf /etc/cupsd/ 
    56    
     56 
    5757  Now edit the configuration file to suit your needs : 
    58    
     58 
    5959    $ vi /etc/cupsd/tea4cups.conf 
    60      
     60 
    6161    NB : you can use emacs as well :-) 
    62      
     62 
    6363  Finally restart CUPS : 
    64    
     64 
    6565    $ /etc/init.d/cupsys restart 
    66    
     66 
    6767  You can now create "Tea4CUPS Managed" print queues from 
    6868  CUPS' web interface, or using lpadmin. 
    69    
    70 Send bug reports to : alet@librelogiciel.com   
    71 """         
     69 
     70Send bug reports to : alet@librelogiciel.com 
     71""" 
    7272 
    7373import sys 
     
    105105    """IPP related exceptions.""" 
    106106    pass 
    107      
     107 
    108108IPP_VERSION = "1.1"     # default version number 
    109109 
     
    314314IPP_MULTIPLE_JOBS_NOT_SUPPORTED = 0x0509 
    315315IPP_PRINTER_IS_DEACTIVATED = 0x50a 
    316    
     316 
    317317CUPS_PRINTER_LOCAL = 0x0000 
    318318CUPS_PRINTER_CLASS = 0x0001 
     
    341341CUPS_PRINTER_COMMANDS = 0x8000 
    342342CUPS_PRINTER_OPTIONS = 0xe6ff 
    343    
     343 
    344344class FakeAttribute : 
    345345    """Fakes an IPPRequest attribute to simplify usage syntax.""" 
     
    348348        self.request = request 
    349349        self.name = name 
    350          
     350 
    351351    def __setitem__(self, key, value) : 
    352352        """Appends the value to the real attribute.""" 
     
    359359                    attribute[j][1].append(value) 
    360360                    return 
    361             attribute.append((key, [value]))         
    362              
     361            attribute.append((key, [value])) 
     362 
    363363    def __getitem__(self, key) : 
    364364        """Returns an attribute's value.""" 
     
    373373        if answer : 
    374374            return answer 
    375         raise KeyError, key             
    376      
     375        raise KeyError, key 
     376 
    377377class IPPRequest : 
    378378    """A class for IPP requests.""" 
    379379    attributes_types = ("operation", "job", "printer", "unsupported", \ 
    380380                                     "subscription", "event_notification") 
    381     def __init__(self, data="", version=IPP_VERSION,  
     381    def __init__(self, data="", version=IPP_VERSION, 
    382382                                operation_id=None, \ 
    383383                                request_id=None, \ 
    384384                                debug=False) : 
    385385        """Initializes an IPP Message object. 
    386          
     386 
    387387           Parameters : 
    388             
     388 
    389389             data : the complete IPP Message's content. 
    390390             debug : a boolean value to output debug info on stderr. 
     
    393393        self._data = data 
    394394        self.parsed = False 
    395          
     395 
    396396        # Initializes message 
    397         self.setVersion(version)                 
     397        self.setVersion(version) 
    398398        self.setOperationId(operation_id) 
    399399        self.setRequestId(request_id) 
    400400        self.data = "" 
    401          
     401 
    402402        for attrtype in self.attributes_types : 
    403403            setattr(self, "_%s_attributes" % attrtype, [[]]) 
    404          
    405         # Initialize tags     
     404 
     405        # Initialize tags 
    406406        self.tags = [ None ] * 256 # by default all tags reserved 
    407          
     407 
    408408        # Delimiter tags 
    409409        self.tags[0x01] = "operation-attributes-tag" 
     
    414414        self.tags[0x06] = "subscription-attributes-tag" 
    415415        self.tags[0x07] = "event_notification-attributes-tag" 
    416          
     416 
    417417        # out of band values 
    418418        self.tags[0x10] = "unsupported" 
     
    423423        self.tags[0x16] = "delete-attribute" 
    424424        self.tags[0x17] = "admin-define" 
    425    
     425 
    426426        # integer values 
    427427        self.tags[0x20] = "generic-integer" 
     
    429429        self.tags[0x22] = "boolean" 
    430430        self.tags[0x23] = "enum" 
    431          
     431 
    432432        # octetString 
    433433        self.tags[0x30] = "octetString-with-an-unspecified-format" 
     
    439439        self.tags[0x36] = "nameWithLanguage" 
    440440        self.tags[0x37] = "endCollection" 
    441          
     441 
    442442        # character strings 
    443443        self.tags[0x40] = "generic-character-string" 
     
    451451        self.tags[0x49] = "mimeMediaType" 
    452452        self.tags[0x4a] = "memberAttrName" 
    453          
     453 
    454454        # Reverse mapping to generate IPP messages 
    455455        self.tagvalues = {} 
     
    458458            if value is not None : 
    459459                self.tagvalues[value] = i 
    460                                       
    461     def __getattr__(self, name) :                                  
     460 
     461    def __getattr__(self, name) : 
    462462        """Fakes attribute access.""" 
    463463        if name in self.attributes_types : 
     
    465465        else : 
    466466            raise AttributeError, name 
    467              
    468     def __str__(self) :         
     467 
     468    def __str__(self) : 
    469469        """Returns the parsed IPP message in a readable form.""" 
    470470        if not self.parsed : 
     
    480480                for (name, value) in attribute : 
    481481                    mybuffer.append("  %s : %s" % (name, value)) 
    482         if self.data :             
     482        if self.data : 
    483483            mybuffer.append("IPP datas : %s" % repr(self.data)) 
    484484        return "\n".join(mybuffer) 
    485          
    486     def logDebug(self, msg) :     
     485 
     486    def logDebug(self, msg) : 
    487487        """Prints a debug message.""" 
    488488        if self.debug : 
    489489            sys.stderr.write("%s\n" % msg) 
    490490            sys.stderr.flush() 
    491              
     491 
    492492    def setVersion(self, version) : 
    493493        """Sets the request's operation id.""" 
     
    498498                if len(version) == 2 : # 2-tuple 
    499499                    self.version = version 
    500                 else :     
     500                else : 
    501501                    try : 
    502502                        self.version = [int(p) for p in str(float(version)).split(".")] 
    503503                    except : 
    504504                        self.version = [int(p) for p in IPP_VERSION.split(".")] 
    505          
    506     def setOperationId(self, opid) :         
     505 
     506    def setOperationId(self, opid) : 
    507507        """Sets the request's operation id.""" 
    508508        self.operation_id = opid 
    509          
    510     def setRequestId(self, reqid) :         
     509 
     510    def setRequestId(self, reqid) : 
    511511        """Sets the request's request id.""" 
    512512        self.request_id = reqid 
    513          
    514     def dump(self) :     
     513 
     514    def dump(self) : 
    515515        """Generates an IPP Message. 
    516          
     516 
    517517           Returns the message as a string of text. 
    518         """     
     518        """ 
    519519        mybuffer = [] 
    520520        if None not in (self.version, self.operation_id) : 
     
    534534                                mybuffer.append(attrname) 
    535535                                nameprinted = 1 
    536                             else :      
     536                            else : 
    537537                                mybuffer.append(pack(">H", 0)) 
    538538                            if vtype in ("integer", "enum") : 
     
    542542                                mybuffer.append(pack(">H", 1)) 
    543543                                mybuffer.append(chr(val)) 
    544                             else :     
     544                            else : 
    545545                                mybuffer.append(pack(">H", len(val))) 
    546546                                mybuffer.append(val) 
    547547            mybuffer.append(chr(self.tagvalues["end-of-attributes-tag"])) 
    548         mybuffer.append(self.data)     
     548        mybuffer.append(self.data) 
    549549        return "".join(mybuffer) 
    550              
     550 
    551551    def parse(self) : 
    552552        """Parses an IPP Request. 
    553          
     553 
    554554           NB : Only a subset of RFC2910 is implemented. 
    555555        """ 
    556556        self._curname = None 
    557557        self._curattributes = None 
    558          
     558 
    559559        self.setVersion((ord(self._data[0]), ord(self._data[1]))) 
    560560        self.setOperationId(unpack(">H", self._data[2:4])[0]) 
     
    575575                        self.position -= 1 
    576576                        continue 
    577                 oldtag = tag         
     577                oldtag = tag 
    578578                tag = ord(self._data[self.position]) 
    579579                if tag == oldtag : 
     
    581581        except IndexError : 
    582582            raise IPPError, "Unexpected end of IPP message." 
    583              
    584         self.data = self._data[self.position+1:]             
     583 
     584        self.data = self._data[self.position+1:] 
    585585        self.parsed = True 
    586          
    587     def parseTag(self) :     
     586 
     587    def parseTag(self) : 
    588588        """Extracts information from an IPP tag.""" 
    589589        pos = self.position 
     
    594594        if not namelength : 
    595595            name = self._curname 
    596         else :     
     596        else : 
    597597            posend += namelength 
    598598            self._curname = name = self._data[pos2:posend] 
     
    603603        if tagtype in ("integer", "enum") : 
    604604            value = unpack(">I", value)[0] 
    605         elif tagtype == "boolean" :     
     605        elif tagtype == "boolean" : 
    606606            value = ord(value) 
    607         try :     
     607        try : 
    608608            (oldname, oldval) = self._curattributes[-1][-1] 
    609609            if oldname == name : 
    610610                oldval.append((tagtype, value)) 
    611             else :     
     611            else : 
    612612                raise IndexError 
    613         except IndexError :     
     613        except IndexError : 
    614614            self._curattributes[-1].append((name, [(tagtype, value)])) 
    615615        self.logDebug("%s(%s) : %s" % (name, tagtype, value)) 
    616616        return posend - self.position 
    617          
    618     def operation_attributes_tag(self) :  
     617 
     618    def operation_attributes_tag(self) : 
    619619        """Indicates that the parser enters into an operation-attributes-tag group.""" 
    620620        self._curattributes = self._operation_attributes 
    621621        return self.parseTag() 
    622          
    623     def job_attributes_tag(self) :  
     622 
     623    def job_attributes_tag(self) : 
    624624        """Indicates that the parser enters into a job-attributes-tag group.""" 
    625625        self._curattributes = self._job_attributes 
    626626        return self.parseTag() 
    627          
    628     def printer_attributes_tag(self) :  
     627 
     628    def printer_attributes_tag(self) : 
    629629        """Indicates that the parser enters into a printer-attributes-tag group.""" 
    630630        self._curattributes = self._printer_attributes 
    631631        return self.parseTag() 
    632          
    633     def unsupported_attributes_tag(self) :  
     632 
     633    def unsupported_attributes_tag(self) : 
    634634        """Indicates that the parser enters into an unsupported-attributes-tag group.""" 
    635635        self._curattributes = self._unsupported_attributes 
    636636        return self.parseTag() 
    637          
    638     def subscription_attributes_tag(self) :  
     637 
     638    def subscription_attributes_tag(self) : 
    639639        """Indicates that the parser enters into a subscription-attributes-tag group.""" 
    640640        self._curattributes = self._subscription_attributes 
    641641        return self.parseTag() 
    642          
    643     def event_notification_attributes_tag(self) :  
     642 
     643    def event_notification_attributes_tag(self) : 
    644644        """Indicates that the parser enters into an event-notification-attributes-tag group.""" 
    645645        self._curattributes = self._event_notification_attributes 
    646646        return self.parseTag() 
    647          
    648              
     647 
     648 
    649649class CUPS : 
    650650    """A class for a CUPS instance.""" 
     
    655655            if self.url.endswith("/") : 
    656656                self.url = self.url[:-1] 
    657         else :         
     657        else : 
    658658            self.url = self.getDefaultURL() 
    659659        self.username = username 
     
    665665        self.lastErrorMessage = None 
    666666        self.requestId = None 
    667          
    668     def getDefaultURL(self) :     
     667 
     668    def getDefaultURL(self) : 
    669669        """Builds a default URL.""" 
    670670        # TODO : encryption methods. 
     
    675675            # we can't handle this right now, so we use the default instead. 
    676676            return "http://localhost:%s" % port 
    677         else :     
     677        else : 
    678678            return "http://%s:%s" % (server, port) 
    679              
     679 
    680680    def identifierToURI(self, service, ident) : 
    681681        """Transforms an identifier into a particular URI depending on requested service.""" 
     
    683683                             service, 
    684684                             ident) 
    685          
    686     def nextRequestId(self) :         
     685 
     686    def nextRequestId(self) : 
    687687        """Increments the current request id and returns the new value.""" 
    688688        try : 
    689689            self.requestId += 1 
    690         except TypeError :     
     690        except TypeError : 
    691691            self.requestId = 1 
    692692        return self.requestId 
    693              
     693 
    694694    def newRequest(self, operationid=None) : 
    695695        """Generates a new empty request.""" 
     
    701701            req.operation["attributes-natural-language"] = ("naturalLanguage", self.language) 
    702702            return req 
    703      
     703 
    704704    def doRequest(self, req, url=None) : 
    705705        """Sends a request to the CUPS server. 
    706706           returns a new IPPRequest object, containing the parsed answer. 
    707         """    
     707        """ 
    708708        connexion = urllib2.Request(url=url or self.url, \ 
    709709                             data=req.dump()) 
     
    715715                                   self.username, \ 
    716716                                   self.password or "") 
    717             authhandler = urllib2.HTTPBasicAuthHandler(pwmanager)                        
     717            authhandler = urllib2.HTTPBasicAuthHandler(pwmanager) 
    718718            opener = urllib2.build_opener(authhandler) 
    719719            urllib2.install_opener(opener) 
    720         self.lastError = None     
     720        self.lastError = None 
    721721        self.lastErrorMessage = None 
    722         try :     
     722        try : 
    723723            response = urllib2.urlopen(connexion) 
    724         except (urllib2.URLError, urllib2.HTTPError, socket.error), error :     
     724        except (urllib2.URLError, urllib2.HTTPError, socket.error), error : 
    725725            self.lastError = error 
    726726            self.lastErrorMessage = str(error) 
    727727            return None 
    728         else :     
     728        else : 
    729729            datas = response.read() 
    730730            ippresponse = IPPRequest(datas) 
    731731            ippresponse.parse() 
    732732            return ippresponse 
    733      
    734     def getPPD(self, queuename) :     
     733 
     734    def getPPD(self, queuename) : 
    735735        """Retrieves the PPD for a particular queuename.""" 
    736736        req = self.newRequest(IPP_GET_PRINTER_ATTRIBUTES) 
     
    739739            req.operation["requested-attributes"] = ("nameWithoutLanguage", attrib) 
    740740        return self.doRequest(req)  # TODO : get the PPD from the actual print server 
    741          
     741 
    742742    def getDefault(self) : 
    743743        """Retrieves CUPS' default printer.""" 
    744744        return self.doRequest(self.newRequest(CUPS_GET_DEFAULT)) 
    745      
    746     def getJobAttributes(self, jobid) :     
     745 
     746    def getJobAttributes(self, jobid) : 
    747747        """Retrieves a print job's attributes.""" 
    748748        req = self.newRequest(IPP_GET_JOB_ATTRIBUTES) 
    749749        req.operation["job-uri"] = ("uri", self.identifierToURI("jobs", jobid)) 
    750750        return self.doRequest(req) 
    751          
    752     def getPrinters(self) :     
     751 
     752    def getPrinters(self) : 
    753753        """Returns the list of print queues names.""" 
    754754        req = self.newRequest(CUPS_GET_PRINTERS) 
     
    757757        req.operation["printer-type-mask"] = ("enum", CUPS_PRINTER_CLASS) 
    758758        return [printer[1] for printer in self.doRequest(req).printer["printer-name"]] 
    759          
    760     def getDevices(self) :     
     759 
     760    def getDevices(self) : 
    761761        """Returns a list of devices as (deviceclass, deviceinfo, devicemakeandmodel, deviceuri) tuples.""" 
    762762        answer = self.doRequest(self.newRequest(CUPS_GET_DEVICES)) 
     
    765765                   [d[1] for d in answer.printer["device-make-and-model"]], \ 
    766766                   [d[1] for d in answer.printer["device-uri"]]) 
    767                     
    768     def getPPDs(self) :     
     767 
     768    def getPPDs(self) : 
    769769        """Returns a list of PPDs as (ppdnaturallanguage, ppdmake, ppdmakeandmodel, ppdname) tuples.""" 
    770770        answer = self.doRequest(self.newRequest(CUPS_GET_PPDS)) 
     
    773773                   [d[1] for d in answer.printer["ppd-make-and-model"]], \ 
    774774                   [d[1] for d in answer.printer["ppd-name"]]) 
    775                     
     775 
    776776    def createSubscription(self, uri, events=["all"], 
    777777                                      userdata=None, 
     
    784784                                      jobid=None) : 
    785785        """Creates a job, printer or server subscription. 
    786           
     786 
    787787           uri : the subscription's uri, e.g. ipp://server 
    788788           events : a list of events to subscribe to, e.g. ["printer-added", "printer-deleted"] 
     
    794794           timeinterval : the interval of time during notifications 
    795795           jobid : the optional job id in case of a job subscription 
    796         """    
     796        """ 
    797797        if jobid is not None : 
    798798            opid = IPP_CREATE_JOB_SUBSCRIPTION 
     
    805805        for event in events : 
    806806            req.subscription["notify-events"] = ("keyword", event) 
    807         if userdata is not None :     
     807        if userdata is not None : 
    808808            req.subscription["notify-user-data"] = ("octetString-with-an-unspecified-format", userdata) 
    809         if recipient is not None :     
     809        if recipient is not None : 
    810810            req.subscription["notify-recipient"] = ("uri", recipient) 
    811811        if pullmethod is not None : 
     
    822822            req.subscription["notify-job-id"] = ("integer", jobid) 
    823823        return self.doRequest(req) 
    824              
    825     def cancelSubscription(self, uri, subscriptionid, jobid=None) :     
     824 
     825    def cancelSubscription(self, uri, subscriptionid, jobid=None) : 
    826826        """Cancels a subscription. 
    827          
     827 
    828828           uri : the subscription's uri. 
    829829           subscriptionid : the subscription's id. 
     
    838838        req.event_notification["notify-subscription-id"] = ("integer", subscriptionid) 
    839839        return self.doRequest(req) 
    840          
     840 
    841841 
    842842class FakeConfig : 
     
    879879        conffile.close() 
    880880    return dirvalues 
    881      
     881 
    882882class CupsBackend : 
    883883    """Base class for tools with no database access.""" 
     
    912912        self.LockFile = None 
    913913 
    914     def waitForLock(self) :     
     914    def waitForLock(self) : 
    915915        """Waits until we can acquire the lock file.""" 
    916916        lockfilename = self.DeviceURI.replace("/", ".") 
     
    926926                # open the lock file, optionally creating it if needed. 
    927927                self.LockFile = open(lockfilename, "a+") 
    928                  
     928 
    929929                # we wait indefinitely for the lock to become available. 
    930930                # works over NFS too. 
    931931                fcntl.lockf(self.LockFile, fcntl.LOCK_EX) 
    932932                haslock = True 
    933                  
     933 
    934934                self.logDebug("Lock %s acquired." % lockfilename) 
    935                  
     935 
    936936                # Here we save the PID in the lock file, but we don't use 
    937937                # it, because the lock file may be in a directory shared 
     
    942942                self.LockFile.write(str(self.pid)) 
    943943                self.LockFile.flush() 
    944             except IOError :             
     944            except IOError : 
    945945                self.logDebug("I/O Error while waiting for lock %s" % lockfilename) 
    946946                time.sleep(0.25) 
    947          
     947 
    948948    def readConfig(self) : 
    949949        """Reads the configuration file.""" 
     
    11041104        self.Directory = self.getPrintQueueOption(self.PrinterName, "directory", ignore=1) or tempfile.gettempdir() 
    11051105        self.DataFile = os.path.join(self.Directory, "%s-%s-%s-%s" % (self.myname, self.PrinterName, self.UserName, self.JobId)) 
    1106          
     1106 
    11071107        # check that the DEVICE_URI environment variable's value is 
    11081108        # prefixed with self.myname otherwise don't touch it. 
     
    11281128        self.RealBackend = backend 
    11291129        self.DeviceURI = device_uri 
    1130          
     1130 
    11311131        try : 
    11321132            cupsserver = CUPS() # TODO : username and password and/or encryption 
     
    11351135                raise ValueError # don't hande unix domain sockets yet. 
    11361136            self.ControlFile = "NotUsedAnymore" 
    1137         except :     
     1137        except : 
    11381138            (ippfilename, answer) = self.parseIPPRequestFile() 
    11391139            self.ControlFile = ippfilename 
    1140          
     1140 
    11411141        try : 
    11421142            john = answer.job["job-originating-host-name"] 
    1143         except (KeyError, AttributeError) :     
     1143        except (KeyError, AttributeError) : 
    11441144            try : 
    11451145                john = answer.operation["job-originating-host-name"] 
    1146             except (KeyError, AttributeError) :     
     1146            except (KeyError, AttributeError) : 
    11471147                john = (None, None) 
    1148         if type(john) == type([]) :                           
     1148        if type(john) == type([]) : 
    11491149            john = john[-1] 
    1150         (dummy, self.ClientHost) = john                           
    1151         try :         
     1150        (dummy, self.ClientHost) = john 
     1151        try : 
    11521152            jbing = answer.job["job-billing"] 
    1153         except (KeyError, AttributeError) :     
     1153        except (KeyError, AttributeError) : 
    11541154            jbing = (None, None) 
    1155         if type(jbing) == type([]) :  
     1155        if type(jbing) == type([]) : 
    11561156            jbing = jbing[-1] 
    11571157        (dummy, self.JobBilling) = jbing 
    1158          
     1158 
    11591159    def parseIPPRequestFile(self) : 
    11601160        """Parses the IPP message file and returns a tuple (filename, parsedvalue).""" 
     
    12121212        else : 
    12131213            infile = sys.stdin 
    1214              
     1214 
    12151215        filtercommand = self.getPrintQueueOption(self.PrinterName, "filter", \ 
    12161216                                                 ignore=1) 
    1217         if filtercommand :                                                  
     1217        if filtercommand : 
    12181218            self.logDebug("Data stream will be filtered through [%s]" % filtercommand) 
    12191219            filteroutput = "%s.filteroutput" % self.DataFile 
     
    12261226            infile = open(filteroutput, "rb") 
    12271227            mustclose = 1 
    1228         else :     
     1228        else : 
    12291229            self.logDebug("Data stream will be used as-is (no filter defined)") 
    1230              
     1230 
    12311231        CHUNK = 64*1024         # read 64 Kb at a time 
    12321232        dummy = 0 
     
    12451245            dummy += 1 
    12461246        outfile.close() 
    1247          
     1247 
    12481248        if filtercommand : 
    12491249            self.logDebug("Removing filter's output file %s" % filteroutput) 
    12501250            try : 
    12511251                os.remove(filteroutput) 
    1252             except :     
     1252            except : 
    12531253                pass 
    1254                  
     1254 
    12551255        if mustclose : 
    12561256            infile.close() 
    1257              
     1257 
    12581258        self.logDebug("%s bytes saved..." % sizeread) 
    12591259        self.JobSize = sizeread 
     
    12691269            try : 
    12701270                os.remove(self.DataFile) 
    1271             except OSError, msg :     
     1271            except OSError, msg : 
    12721272                self.logInfo("Problem when removing %s : %s" % (self.DataFile, msg), "error") 
    1273                  
     1273 
    12741274        if self.LockFile is not None : 
    12751275            self.logDebug("Removing lock...") 
     
    12771277                fcntl.lockf(self.LockFile, fcntl.LOCK_UN) 
    12781278                self.LockFile.close() 
    1279             except :     
     1279            except : 
    12801280                self.logInfo("Problem while unlocking.", "error") 
    1281             else :     
     1281            else : 
    12821282                self.logDebug("Lock removed.") 
    12831283        self.logDebug("Clean.") 
     
    13031303                        self.logDebug("Launching onfail script %s" % onfail) 
    13041304                        os.system(onfail) 
    1305                          
     1305 
    13061306            os.environ["TEASTATUS"] = str(retcode) 
    13071307            branches = self.enumBranches(self.PrinterName, "posthook") 
    13081308            if self.runCommands("posthook", branches, serialize) : 
    13091309                self.logInfo("An error occured during the execution of posthooks.", "warn") 
    1310                  
     1310 
    13111311        for p in [ (k, v) for (k, v) in self.pipes.items() if k != 0 ] : 
    13121312            os.close(p[1][0]) 
     
    14041404            try : 
    14051405                (number, delay) = [int(p) for p in retry.strip().split(",")] 
    1406             except (ValueError, AttributeError, TypeError) :     
     1406            except (ValueError, AttributeError, TypeError) : 
    14071407                self.logInfo("Invalid value '%s' for the 'retry' directive for printer %s in %s." % (retry, self.PrinterName, self.conffile), "error") 
    14081408                number = 1 
    14091409                delay = 0 
    1410                  
    1411         loopcount = 1  
    1412         while 1 :             
     1410 
     1411        loopcount = 1 
     1412        while 1 : 
    14131413            retcode = self.runOriginalBackend() 
    14141414            if not retcode : 
     
    14191419                    time.sleep(delay) 
    14201420                    loopcount += 1 
    1421                 else :     
     1421                else : 
    14221422                    break 
    1423         return retcode             
    1424          
     1423        return retcode 
     1424 
    14251425    def runOriginalBackend(self) : 
    14261426        """Launches the original backend.""" 
     
    14351435                os.dup2(f.fileno(), 0) 
    14361436                f.close() 
    1437             else :     
     1437            else : 
    14381438                arguments[6] = self.DataFile # in case a tea4cups filter was applied 
    14391439            try : 
     
    14851485            except SystemExit, e : 
    14861486                returncode = e.code 
    1487             except KeyboardInterrupt :     
     1487            except KeyboardInterrupt : 
    14881488                wrapper.logInfo("Job %s interrupted by the administrator !" % wrapper.JobId, "warn") 
    14891489            except : 
     
    14981498                sys.stderr.flush() 
    14991499                returncode = 1 
    1500         finally :         
     1500        finally : 
    15011501            wrapper.cleanUp() 
    15021502        sys.exit(returncode)