Back to index

system-config-printer  1.3.9+20120706
test-cups-driver.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 # -*- python -*-
00003 
00004 ## Copyright (C) 2008 Red Hat, Inc.
00005 ## Copyright (C) 2008 Tim Waugh <twaugh@redhat.com>
00006 
00007 ## This program is free software; you can redistribute it and/or modify
00008 ## it under the terms of the GNU General Public License as published by
00009 ## the Free Software Foundation; either version 2 of the License, or
00010 ## (at your option) any later version.
00011 
00012 ## This program is distributed in the hope that it will be useful,
00013 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 ## GNU General Public License for more details.
00016 
00017 ## You should have received a copy of the GNU General Public License
00018 ## along with this program; if not, write to the Free Software
00019 ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020 
00021 import sys
00022 
00023 import cups
00024 try:
00025     from cupshelpers import missingPackagesAndExecutables
00026 except ImportError:
00027     sys.path.append ('..')
00028     from cupshelpers import missingPackagesAndExecutables
00029 
00030 from getopt import getopt
00031 import os
00032 import posix
00033 import re
00034 import shlex
00035 import signal
00036 import subprocess
00037 import tempfile
00038 
00039 class TimedOut(Exception):
00040     def __init__ (self):
00041         Exception.__init__ (self, "Timed out")
00042 
00043 class MissingExecutables(Exception):
00044     def __init__ (self):
00045         Exception.__init__ (self, "Missing executables")
00046 
00047 class Driver:
00048     def __init__ (self, driver):
00049         self.exe = "/usr/lib/cups/driver/%s" % driver
00050        self.ppds = None
00051        self.files = {}
00052         signal.signal (signal.SIGALRM, self._alarm)
00053 
00054     def _alarm (self, sig, stack):
00055         raise TimedOut
00056 
00057     def list (self):
00058         if self.ppds:
00059               return self.ppds
00060 
00061         signal.alarm (60)
00062         p = subprocess.Popen ([self.exe, "list"],
00063                               stdout=subprocess.PIPE,
00064                               stderr=subprocess.PIPE)
00065         try:
00066             (stdout, stderr) = p.communicate ()
00067             signal.alarm (0)
00068         except TimedOut:
00069             posix.kill (p.pid, signal.SIGKILL)
00070             raise
00071 
00072        if stderr:
00073               print >> sys.stderr, stderr
00074 
00075        ppds = []
00076        lines = stdout.split ('\n')
00077        for line in lines:
00078               l = shlex.split (line)
00079               if len (l) < 1:
00080                      continue
00081               ppds.append (l[0])
00082 
00083        self.ppds = ppds
00084        return ppds
00085 
00086     def cat (self, name):
00087         try:
00088             return self.files[name]
00089        except KeyError:
00090             signal.alarm (10)
00091             p = subprocess.Popen ([self.exe, "cat", name],
00092                                   stdout=subprocess.PIPE,
00093                                   stderr=subprocess.PIPE)
00094             try:
00095                 (stdout, stderr) = p.communicate ()
00096                 signal.alarm (0)
00097             except TimedOut:
00098                 posix.kill (p.pid, signal.SIGKILL)
00099                 raise
00100 
00101             if stderr:
00102                 print >> sys.stderr, stderr
00103 
00104             self.files[name] = stdout
00105             return stdout
00106 
00107 opts, args = getopt (sys.argv[1:], "m:")
00108 if len (args) != 1:
00109     print "Syntax: test-cups-driver [-m REGEXP] DRIVER"
00110     sys.exit (1)
00111 
00112 match = None
00113 for opt, arg in opts:
00114     if opt == '-m':
00115         match = arg
00116         break
00117 
00118 bad = []
00119 ids = set()
00120 d = Driver (args[0])
00121 list = d.list ()
00122 
00123 if match:
00124     exp = re.compile (match)
00125     list = filter (lambda x: exp.match (x), list)
00126 
00127 n = len (list)
00128 i = 0
00129 for name in list:
00130     i += 1
00131     try:
00132         ppd = d.cat (name)
00133         (fd, fname) = tempfile.mkstemp ()
00134         f = os.fdopen (fd, "w")
00135         f.write (ppd)
00136         del f
00137         try:
00138             PPD = cups.PPD (fname)
00139         except:
00140             os.unlink (fname)
00141             raise
00142         os.unlink (fname)
00143 
00144         (pkgs, exes) = missingPackagesAndExecutables (PPD)
00145         if pkgs or exes:
00146             raise MissingExecutables
00147 
00148         attr = PPD.findAttr ('1284DeviceID')
00149         if attr:
00150             pieces = attr.value.split (';')
00151             mfg = mdl = None
00152             for piece in pieces:
00153                 s = piece.split (':', 1)
00154                 if len (s) < 2:
00155                     continue
00156                 key, value = s
00157                 key = key.upper ()
00158                 if key in ["MFG", "MANUFACTURER"]:
00159                     mfg = value
00160                 elif key in ["MDL", "MODEL"]:
00161                     mdl = value
00162             if mfg and mdl:
00163                 id = "MFG:%s;MDL:%s;" % (mfg, mdl)
00164                 ids.add (id)
00165         sys.stderr.write ("%3d%%\r" % (100 * i / n))
00166         sys.stderr.flush ()
00167     except KeyboardInterrupt:
00168         print "Keyboard interrupt\n"
00169         break
00170     except TimedOut, e:
00171         bad.append ((name, e))
00172         print "Timed out fetching %s" % name
00173     except Exception, e:
00174         bad.append ((name, e))
00175         print "Exception fetching %s: %s" % (name, e)
00176 
00177     sys.stdout.flush ()
00178 
00179 if len (bad) > 0:
00180     print "Bad PPDs:"
00181     for each in bad:
00182         print "  %s (%s)" % each
00183     print
00184 
00185 if len (ids) > 0:
00186     print "IEEE 1284 Device IDs:"
00187     for each in ids:
00188         print "  %s" % each
00189     print