Changeset 641 for tea4cups

Show
Ignore:
Timestamp:
06/11/05 19:05:00 (19 years ago)
Author:
stuge
Message:

Removed ~1k of trailing whitespace on 139 lines

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • tea4cups/trunk/tea4cups

    r640 r641  
    1515# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1616# GNU General Public License for more details. 
    17 #  
     17# 
    1818# You should have received a copy of the GNU General Public License 
    1919# along with this program; if not, write to the Free Software 
     
    4949        return self.message 
    5050    __str__ = __repr__ 
    51      
    52 class ConfigError(TeeError) :     
     51 
     52class ConfigError(TeeError) : 
    5353    """Configuration related exceptions.""" 
    54     pass  
    55      
    56 class IPPError(TeeError) :     
     54    pass 
     55 
     56class IPPError(TeeError) : 
    5757    """IPP related exceptions.""" 
    58     pass  
    59      
    60 # Some IPP constants     
     58    pass 
     59 
     60# Some IPP constants 
    6161OPERATION_ATTRIBUTES_TAG = 0x01 
    6262JOB_ATTRIBUTES_TAG = 0x02 
     
    6767class IPPMessage : 
    6868    """A class for IPP message files. 
    69      
     69 
    7070       Usage : 
    71         
     71 
    7272         fp = open("/var/spool/cups/c00001", "rb") 
    7373         message = IPPMessage(fp.read()) 
     
    8686    def __init__(self, data, debug=0) : 
    8787        """Initializes and parses IPP Message object. 
    88          
     88 
    8989           Parameters : 
    90             
     90 
    9191             data : the IPP Message's content. 
    9292             debug : a boolean value to output debug info on stderr. 
     
    9797            setattr(self, "%s_attributes" % attrtype, {}) 
    9898        self.tags = [ None ] * 256      # by default all tags reserved 
    99          
     99 
    100100        # Delimiter tags 
    101101        self.tags[OPERATION_ATTRIBUTES_TAG] = "operation-attributes-tag" 
     
    104104        self.tags[PRINTER_ATTRIBUTES_TAG] = "printer-attributes-tag" 
    105105        self.tags[UNSUPPORTED_ATTRIBUTES_TAG] = "unsupported-attributes-tag" 
    106          
     106 
    107107        # out of band values 
    108108        self.tags[0x10] = "unsupported" 
     
    110110        self.tags[0x12] = "unknown" 
    111111        self.tags[0x13] = "no-value" 
    112          
     112 
    113113        # integer values 
    114114        self.tags[0x20] = "generic-integer" 
     
    116116        self.tags[0x22] = "boolean" 
    117117        self.tags[0x23] = "enum" 
    118          
     118 
    119119        # octetString 
    120120        self.tags[0x30] = "octetString-with-an-unspecified-format" 
     
    125125        self.tags[0x35] = "textWithLanguage" 
    126126        self.tags[0x36] = "nameWithLanguage" 
    127          
     127 
    128128        # character strings 
    129129        self.tags[0x20] = "generic-character-string" 
     
    137137        self.tags[0x48] = "naturalLanguage" 
    138138        self.tags[0x49] = "mimeMediaType" 
    139          
     139 
    140140        # now parses the IPP message 
    141141        self.parse() 
    142          
    143     def printInfo(self, msg) :     
     142 
     143    def printInfo(self, msg) : 
    144144        """Prints a debug message.""" 
    145145        if self.debug : 
    146146            sys.stderr.write("%s\n" % msg) 
    147147            sys.stderr.flush() 
    148              
    149     def parseTag(self) :     
     148 
     149    def parseTag(self) : 
    150150        """Extracts information from an IPP tag.""" 
    151151        pos = self.position 
     
    156156        if not namelength : 
    157157            name = self._curname 
    158         else :     
     158        else : 
    159159            posend += namelength 
    160160            self._curname = name = self.data[pos2:posend] 
     
    169169        self.printInfo("%s(%s) %s" % (name, tagtype, value)) 
    170170        return posend - self.position 
    171          
    172     def operation_attributes_tag(self) :  
     171 
     172    def operation_attributes_tag(self) : 
    173173        """Indicates that the parser enters into an operation-attributes-tag group.""" 
    174174        self.printInfo("Start of operation_attributes_tag") 
    175175        self._curdict = self.operation_attributes 
    176176        return self.parseTag() 
    177          
    178     def job_attributes_tag(self) :  
     177 
     178    def job_attributes_tag(self) : 
    179179        """Indicates that the parser enters into a job-attributes-tag group.""" 
    180180        self.printInfo("Start of job_attributes_tag") 
    181181        self._curdict = self.job_attributes 
    182182        return self.parseTag() 
    183          
    184     def printer_attributes_tag(self) :  
     183 
     184    def printer_attributes_tag(self) : 
    185185        """Indicates that the parser enters into a printer-attributes-tag group.""" 
    186186        self.printInfo("Start of printer_attributes_tag") 
    187187        self._curdict = self.printer_attributes 
    188188        return self.parseTag() 
    189          
    190     def unsupported_attributes_tag(self) :  
     189 
     190    def unsupported_attributes_tag(self) : 
    191191        """Indicates that the parser enters into an unsupported-attributes-tag group.""" 
    192192        self.printInfo("Start of unsupported_attributes_tag") 
    193193        self._curdict = self.unsupported_attributes 
    194194        return self.parseTag() 
    195          
     195 
    196196    def parse(self) : 
    197197        """Parses an IPP Message. 
    198          
     198 
    199199           NB : Only a subset of RFC2910 is implemented. 
    200200        """ 
     
    220220        except IndexError : 
    221221            raise IPPError, "Unexpected end of IPP message." 
    222              
     222 
    223223        # Now transform all one-element lists into single values 
    224224        for attrtype in self.attributes_types : 
     
    227227                if len(value) == 1 : 
    228228                    attrdict[key] = value[0] 
    229                      
    230 class FakeConfig :     
     229 
     230class FakeConfig : 
    231231    """Fakes a configuration file parser.""" 
    232232    def get(self, section, option, raw=0) : 
    233233        """Fakes the retrieval of an option.""" 
    234234        raise ConfigError, "Invalid configuration file : no option %s in section [%s]" % (option, section) 
    235          
     235 
    236236class CupsBackend : 
    237237    """Base class for tools with no database access.""" 
     
    243243        self.myname = "tea4cups" 
    244244        self.pid = os.getpid() 
    245          
    246     def readConfig(self) :     
     245 
     246    def readConfig(self) : 
    247247        """Reads the configuration file.""" 
    248         confdir = os.environ.get("CUPS_SERVERROOT", ".")  
     248        confdir = os.environ.get("CUPS_SERVERROOT", ".") 
    249249        self.conffile = os.path.join(confdir, "%s.conf" % self.myname) 
    250250        if os.path.isfile(self.conffile) : 
     
    252252            self.config.read([self.conffile]) 
    253253            self.debug = self.isTrue(self.getGlobalOption("debug", ignore=1)) 
    254         else :     
     254        else : 
    255255            self.config = FakeConfig() 
    256256            self.debug = 1      # no config, so force debug mode ! 
    257              
    258     def logInfo(self, message, level="info") :         
     257 
     258    def logInfo(self, message, level="info") : 
    259259        """Logs a message to CUPS' error_log file.""" 
    260260        try : 
     
    263263        except IOError : 
    264264            pass 
    265          
    266     def logDebug(self, message) :     
     265 
     266    def logDebug(self, message) : 
    267267        """Logs something to debug output if debug is enabled.""" 
    268268        if self.debug : 
    269269            self.logInfo(message, level="debug") 
    270              
    271     def isTrue(self, option) :         
     270 
     271    def isTrue(self, option) : 
    272272        """Returns 1 if option is set to true, else 0.""" 
    273273        if (option is not None) and (option.upper().strip() in ['Y', 'YES', '1', 'ON', 'T', 'TRUE']) : 
    274274            return 1 
    275         else :     
     275        else : 
    276276            return 0 
    277                          
    278     def getGlobalOption(self, option, ignore=0) :     
     277 
     278    def getGlobalOption(self, option, ignore=0) : 
    279279        """Returns an option from the global section, or raises a ConfigError if ignore is not set, else returns None.""" 
    280280        try : 
    281281            return self.config.get("global", option, raw=1) 
    282         except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :     
     282        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) : 
    283283            if not ignore : 
    284284                raise ConfigError, "Option %s not found in section global of %s" % (option, self.conffile) 
    285                  
    286     def getPrintQueueOption(self, printqueuename, option, ignore=0) :     
     285 
     286    def getPrintQueueOption(self, printqueuename, option, ignore=0) : 
    287287        """Returns an option from the printer section, or the global section, or raises a ConfigError.""" 
    288288        globaloption = self.getGlobalOption(option, ignore=1) 
    289289        try : 
    290290            return self.config.get(printqueuename, option, raw=1) 
    291         except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) :     
     291        except (ConfigParser.NoSectionError, ConfigParser.NoOptionError) : 
    292292            if globaloption is not None : 
    293293                return globaloption 
    294294            elif not ignore : 
    295295                raise ConfigError, "Option %s not found in section [%s] of %s" % (option, printqueuename, self.conffile) 
    296                  
     296 
    297297    def enumBranches(self, printqueuename, branchtype="tee") : 
    298298        """Returns the list of branchtypes branches for a particular section's.""" 
     
    300300        try : 
    301301            globalbranches = [ (k, self.config.get("global", k)) for k in self.config.options("global") if k.startswith(branchbasename) ] 
    302         except ConfigParser.NoSectionError, msg :     
     302        except ConfigParser.NoSectionError, msg : 
    303303            raise ConfigError, "Invalid configuration file : %s" % msg 
    304304        try : 
    305305            sectionbranches = [ (k, self.config.get(printqueuename, k)) for k in self.config.options(printqueuename) if k.startswith(branchbasename) ] 
    306         except ConfigParser.NoSectionError, msg :     
     306        except ConfigParser.NoSectionError, msg : 
    307307            self.logInfo("No section for print queue %s : %s" % (printqueuename, msg)) 
    308308            sectionbranches = [] 
     
    312312            if value : 
    313313                branches[k] = value 
    314         for (k, v) in sectionbranches :     
     314        for (k, v) in sectionbranches : 
    315315            value = v.strip() 
    316316            if value : 
    317317                branches[k] = value # overwrite any global option or set a new value 
    318             else :     
     318            else : 
    319319                del branches[k] # empty value disables a global option 
    320320        return branches 
    321          
    322     def discoverOtherBackends(self) :     
     321 
     322    def discoverOtherBackends(self) : 
    323323        """Discovers the other CUPS backends. 
    324          
     324 
    325325           Executes each existing backend in turn in device enumeration mode. 
    326326           Returns the list of available backends. 
     
    342342                # see if the pid contained in the lock file is still running 
    343343                os.kill(pid, 0) 
    344             except OSError, e :     
     344            except OSError, e : 
    345345                if e.errno != errno.EPERM : 
    346346                    # process doesn't exist anymore 
    347347                    os.remove(lockfilename) 
    348              
     348 
    349349        if not os.path.exists(lockfilename) : 
    350350            lockfile = open(lockfilename, "w") 
     
    352352            lockfile.close() 
    353353            allbackends = [ os.path.join(directory, b) \ 
    354                                 for b in os.listdir(directory)  
     354                                for b in os.listdir(directory) 
    355355                                    if os.access(os.path.join(directory, b), os.X_OK) \ 
    356                                         and (b != myname)]  
    357             for backend in allbackends :                             
     356                                        and (b != myname)] 
     357            for backend in allbackends : 
    358358                answer = os.popen(backend, "r") 
    359359                try : 
    360360                    devices = [line.strip() for line in answer.readlines()] 
    361                 except :     
     361                except : 
    362362                    devices = [] 
    363363                status = answer.close() 
    364364                if status is None : 
    365365                    for d in devices : 
    366                         # each line is of the form :  
     366                        # each line is of the form : 
    367367                        # 'xxxx xxxx "xxxx xxx" "xxxx xxx"' 
    368368                        # so we have to decompose it carefully 
     
    381381                        try : 
    382382                            (devicetype, device, name, fullname) = arguments 
    383                         except ValueError :     
     383                        except ValueError : 
    384384                            pass    # ignore this 'bizarre' device 
    385                         else :     
     385                        else : 
    386386                            if name.startswith('"') and name.endswith('"') : 
    387387                                name = name[1:-1] 
     
    394394                             % (self.myname, self.MyName, self.MyName)) 
    395395        return available 
    396                          
    397     def initBackend(self) :     
     396 
     397    def initBackend(self) : 
    398398        """Initializes the backend's attributes.""" 
    399         # check that the DEVICE_URI environment variable's value is  
     399        # check that the DEVICE_URI environment variable's value is 
    400400        # prefixed with self.myname otherwise don't touch it. 
    401         # If this is the case, we have to remove the prefix from  
    402         # the environment before launching the real backend  
     401        # If this is the case, we have to remove the prefix from 
     402        # the environment before launching the real backend 
    403403        muststartwith = "%s:" % self.myname 
    404404        device_uri = os.environ.get("DEVICE_URI", "") 
     
    407407            device_uri = fulldevice_uri[len(muststartwith):] 
    408408            for i in range(2) : 
    409                 if device_uri.startswith("/") :   
     409                if device_uri.startswith("/") : 
    410410                    device_uri = device_uri[1:] 
    411411        try : 
    412             (backend, destination) = device_uri.split(":", 1)  
    413         except ValueError :     
     412            (backend, destination) = device_uri.split(":", 1) 
     413        except ValueError : 
    414414            if not device_uri : 
    415415                self.logDebug("Not attached to an existing print queue.") 
    416416                backend = "" 
    417             else :     
     417            else : 
    418418                raise TeeError, "Invalid DEVICE_URI : %s\n" % device_uri 
    419          
     419 
    420420        self.JobId = sys.argv[1].strip() 
    421421        self.UserName = sys.argv[2].strip() or pwd.getpwuid(os.geteuid())[0] # use CUPS' user when printing test pages from CUPS' web interface 
     
    425425        if len(sys.argv) == 7 : 
    426426            self.InputFile = sys.argv[6] # read job's datas from file 
    427         else :     
     427        else : 
    428428            self.InputFile = None        # read job's datas from stdin 
    429              
     429 
    430430        self.RealBackend = backend 
    431431        self.DeviceURI = device_uri 
     
    438438                                          ippmessage.job_attributes.get("job-originating-host-name", (None, None))) 
    439439        (jbtype, self.JobBilling) = ippmessage.job_attributes.get("job-billing", (None, None)) 
    440              
     440 
    441441    def getCupsConfigDirectives(self, directives=[]) : 
    442442        """Retrieves some CUPS directives from its configuration file. 
    443          
    444            Returns a mapping with lowercased directives as keys and  
     443 
     444           Returns a mapping with lowercased directives as keys and 
    445445           their setting as values. 
    446446        """ 
    447         dirvalues = {}  
     447        dirvalues = {} 
    448448        cupsroot = os.environ.get("CUPS_SERVERROOT", "/etc/cups") 
    449449        cupsdconf = os.path.join(cupsroot, "cupsd.conf") 
    450450        try : 
    451451            conffile = open(cupsdconf, "r") 
    452         except IOError :     
     452        except IOError : 
    453453            raise TeeError, "Unable to open %s" % cupsdconf 
    454         else :     
     454        else : 
    455455            for line in conffile.readlines() : 
    456456                linecopy = line.strip().lower() 
     
    459459                        try : 
    460460                            val = line.split()[1] 
    461                         except :     
     461                        except : 
    462462                            pass # ignore errors, we take the last value in any case. 
    463                         else :     
     463                        else : 
    464464                            dirvalues[di] = val 
    465             conffile.close()             
    466         return dirvalues        
    467              
    468     def parseIPPMessageFile(self) :         
     465            conffile.close() 
     466        return dirvalues 
     467 
     468    def parseIPPMessageFile(self) : 
    469469        """Parses the IPP message file and returns a tuple (filename, parsedvalue).""" 
    470470        cupsdconf = self.getCupsConfigDirectives(["RequestRoot"]) 
     
    472472        if (len(self.JobId) < 5) and self.JobId.isdigit() : 
    473473            ippmessagefile = "c%05i" % int(self.JobId) 
    474         else :     
     474        else : 
    475475            ippmessagefile = "c%s" % self.JobId 
    476476        ippmessagefile = os.path.join(requestroot, ippmessagefile) 
     
    478478        try : 
    479479            ippdatafile = open(ippmessagefile) 
    480         except :     
     480        except : 
    481481            self.logInfo("Unable to open IPP message file %s" % ippmessagefile, "warn") 
    482         else :     
     482        else : 
    483483            self.logDebug("Parsing of IPP message file %s begins." % ippmessagefile) 
    484484            try : 
    485485                ippmessage = IPPMessage(ippdatafile.read()) 
    486             except IPPError, msg :     
     486            except IPPError, msg : 
    487487                self.logInfo("Error while parsing %s : %s" % (ippmessagefile, msg), "warn") 
    488             else :     
     488            else : 
    489489                self.logDebug("Parsing of IPP message file %s ends." % ippmessagefile) 
    490490            ippdatafile.close() 
    491491        return (ippmessagefile, ippmessage) 
    492                  
    493     def exportAttributes(self) :     
     492 
     493    def exportAttributes(self) : 
    494494        """Exports our backend's attributes to the environment.""" 
    495495        os.environ["DEVICE_URI"] = self.DeviceURI       # WARNING ! 
     
    508508        os.environ["TEABILLING"] = self.JobBilling or "" 
    509509        os.environ["TEACONTROLFILE"] = self.ControlFile 
    510          
     510 
    511511    def saveDatasAndCheckSum(self) : 
    512512        """Saves the input datas into a static file.""" 
     
    516516            infile = open(self.InputFile, "rb") 
    517517            mustclose = 1 
    518         else :     
     518        else : 
    519519            infile = sys.stdin 
    520520        CHUNK = 64*1024         # read 64 Kb at a time 
     
    522522        sizeread = 0 
    523523        checksum = md5.new() 
    524         outfile = open(self.DataFile, "wb")     
     524        outfile = open(self.DataFile, "wb") 
    525525        while 1 : 
    526             data = infile.read(CHUNK)  
     526            data = infile.read(CHUNK) 
    527527            if not data : 
    528528                break 
    529             sizeread += len(data)     
     529            sizeread += len(data) 
    530530            outfile.write(data) 
    531             checksum.update(data)     
     531            checksum.update(data) 
    532532            if not (dummy % 32) : # Only display every 2 Mb 
    533533                self.logDebug("%s bytes saved..." % sizeread) 
    534             dummy += 1     
     534            dummy += 1 
    535535        outfile.close() 
    536         if mustclose :     
     536        if mustclose : 
    537537            infile.close() 
    538         self.JobSize = sizeread     
     538        self.JobSize = sizeread 
    539539        self.JobMD5Sum = checksum.hexdigest() 
    540540        self.logDebug("Job %s is %s bytes long." % (self.JobId, self.JobSize)) 
     
    545545        if not self.isTrue(self.getPrintQueueOption(self.PrinterName, "keepfiles", ignore=1)) : 
    546546            os.remove(self.DataFile) 
    547              
     547 
    548548    def sigtermHandler(self, signum, frame) : 
    549549        """Sets an attribute whenever SIGTERM is received.""" 
    550550        self.gotSigTerm = 1 
    551551        self.logInfo("SIGTERM received for Job %s." % self.JobId) 
    552          
    553     def runBranches(self) :          
     552 
     553    def runBranches(self) : 
    554554        """Launches each hook defined for the current print queue.""" 
    555555        self.isCancelled = 0    # did a prehook cancel the print job ? 
     
    577577        if not retcode : 
    578578            self.logInfo("OK") 
    579         else :     
     579        else : 
    580580            self.logInfo("An error occured, please check CUPS' error_log file.") 
    581581        return retcode 
    582          
     582 
    583583    def stdioRedirSystem(self, cmd, stdin=0, stdout=1) : 
    584584        """Launches a command with stdio redirected.""" 
     
    601601            return os.WEXITSTATUS(status) 
    602602        return -1 
    603          
     603 
    604604    def runCommand(self, branch, command) : 
    605605        """Runs a particular branch command.""" 
     
    614614            return self.stdioRedirSystem(command, self.pipes[bname][0]) 
    615615 
    616     def runCommands(self, btype, branches, serialize) :     
     616    def runCommands(self, btype, branches, serialize) : 
    617617        """Runs the commands for a particular branch type.""" 
    618         exitcode = 0  
     618        exitcode = 0 
    619619        btype = btype.lower() 
    620620        btypetitle = btype.title() 
    621         branchlist = branches.keys()     
     621        branchlist = branches.keys() 
    622622        branchlist.sort() 
    623623        if serialize : 
     
    628628                retcode = self.runCommand(branch, branches[branch]) 
    629629                self.logDebug("Exit code for %s %s on printer %s is %s" % (btype, branch, self.PrinterName, retcode)) 
    630                 if retcode :     
     630                if retcode : 
    631631                    if (btype == "prehook") and (retcode == 255) : # -1 
    632632                        self.logInfo("Job %s cancelled by prehook %s" % (self.JobId, branch)) 
    633633                        self.isCancelled = 1 
    634                     else :     
     634                    else : 
    635635                        self.logInfo("%s %s on printer %s didn't exit successfully." % (btypetitle, branch, self.PrinterName), "error") 
    636636                        exitcode = 1 
    637637            self.logDebug("End serialized %ss" % btypetitle) 
    638         else :         
     638        else : 
    639639            self.logDebug("Begin forked %ss" % btypetitle) 
    640640            pids = {} 
     
    645645                if pid : 
    646646                    pids[branch] = pid 
    647                 else :     
     647                else : 
    648648                    os._exit(self.runCommand(branch, branches[branch])) 
    649649            for (branch, pid) in pids.items() : 
     
    654654                    retcode = -1 
    655655                self.logDebug("Exit code for %s %s (PID %s) on printer %s is %s" % (btype, branch, pid, self.PrinterName, retcode)) 
    656                 if retcode :     
     656                if retcode : 
    657657                    if (btype == "prehook") and (retcode == 255) : # -1 
    658658                        self.logInfo("Job %s cancelled by prehook %s" % (self.JobId, branch)) 
    659659                        self.isCancelled = 1 
    660                     else :     
     660                    else : 
    661661                        self.logInfo("%s %s (PID %s) on printer %s didn't exit successfully." % (btypetitle, branch, pid, self.PrinterName), "error") 
    662662                        exitcode = 1 
    663663            self.logDebug("End forked %ss" % btypetitle) 
    664664        return exitcode 
    665          
    666     def runOriginalBackend(self) :     
     665 
     666    def runOriginalBackend(self) : 
    667667        """Launches the original backend.""" 
    668668        originalbackend = os.path.join(os.path.split(sys.argv[0])[0], self.RealBackend) 
     
    695695              self.logInfo("CUPS backend %s returned %d." % (originalbackend, status), "error") 
    696696            return status 
    697         elif not killed :     
     697        elif not killed : 
    698698            self.logInfo("CUPS backend %s died abnormally." % originalbackend, "error") 
    699699            return -1 
    700         else :     
     700        else : 
    701701            return 1 
    702          
    703 if __name__ == "__main__" :     
     702 
     703if __name__ == "__main__" : 
    704704    # This is a CUPS backend, we should act and die like a CUPS backend 
    705705    wrapper = CupsBackend() 
    706706    if len(sys.argv) == 1 : 
    707707        print "\n".join(wrapper.discoverOtherBackends()) 
    708         sys.exit(0)                 
    709     elif len(sys.argv) not in (6, 7) :     
     708        sys.exit(0) 
     709    elif len(sys.argv) not in (6, 7) : 
    710710        sys.stderr.write("ERROR: %s job-id user title copies options [file]\n"\ 
    711711                              % sys.argv[0]) 
    712712        sys.exit(1) 
    713     else :     
     713    else : 
    714714        try : 
    715715            wrapper.readConfig() 
     
    719719            retcode = wrapper.runBranches() 
    720720            wrapper.cleanUp() 
    721         except SystemExit, e :     
     721        except SystemExit, e : 
    722722            retcode = e.code 
    723         except :     
     723        except : 
    724724            import traceback 
    725725            lines = []