Moved postscriptdriver RPM tagging machinery here. Fixed leading/trailing whitespace in tags as well.

This commit is contained in:
Tim Waugh 2011-01-20 10:46:14 +00:00
parent 92e5970e05
commit 7d3766acd5
3 changed files with 277 additions and 1 deletions

259
postscriptdriver.prov Executable file
View File

@ -0,0 +1,259 @@
#!/usr/bin/python
## Copyright (C) 2009, 2010 Red Hat, Inc.
## Author: Tim Waugh <twaugh@redhat.com>
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
import sys
try:
import cups
CAN_EXAMINE_PPDS = True
except:
CAN_EXAMINE_PPDS = False
from getopt import getopt
import errno
import os
import posix
import re
import shlex
import signal
import subprocess
import sys
import tempfile
if len (sys.argv) > 1:
RPM_BUILD_ROOT = sys.argv[1]
else:
RPM_BUILD_ROOT = None
class TimedOut(Exception):
def __init__ (self):
Exception.__init__ (self, "Timed out")
class DeviceIDs:
def __init__ (self):
self.ids = dict()
def get_dict (self):
return self.ids
def get_tags (self):
ret = []
for mfg, mdlset in self.ids.iteritems ():
mfgl = mfg.lower ().replace (" ", "_")
for mdl in mdlset:
mdll = mdl.lower ().replace (" ", "_")
ret.append ("postscriptdriver(%s;%s;)" % (mfgl,
mdll))
return ret
def __add__ (self, other):
if isinstance(other, DeviceIDs):
for omfg, omdlset in other.ids.iteritems ():
try:
mdlset = self.ids[omfg]
except KeyError:
mdlset = set()
self.ids[omfg] = mdlset
mdlset.update (omdlset)
return self
pieces = other.split (';')
mfg = mdl = None
for piece in pieces:
s = piece.split (":")
if len (s) != 2:
continue
key, value = s
key = key.upper ().strip ()
if key in ["MFG", "MANUFACTURER"]:
mfg = value.strip ()
elif key in ["MDL", "MODEL"]:
mdl = value.strip ()
if mfg and mdl:
try:
mdlset = self.ids[mfg]
except KeyError:
mdlset = set()
self.ids[mfg] = mdlset
mdlset.add (mdl)
return self
class Driver:
def __init__ (self):
self.ids = DeviceIDs()
def list (self):
return self.ids
class PPDDriver(Driver):
def __init__ (self, pathname=None):
Driver.__init__ (self)
self.pathname = pathname
def list (self):
if self.pathname != None:
self.examine_file (self.pathname)
return Driver.list (self)
def examine_file (self, path):
try:
ppd = cups.PPD (path)
except RuntimeError, e:
# Not a PPD file. Perhaps it's a drv file.
drv = DrvDriver (path)
self.ids += drv.list ()
return
attr = ppd.findAttr ('1284DeviceID')
while attr:
self.ids += attr.value
attr = ppd.findNextAttr ('1284DeviceID')
class DynamicDriver(Driver):
def __init__ (self, driver):
Driver.__init__ (self)
self.driver = driver
signal.signal (signal.SIGALRM, self._alarm)
def _alarm (self, sig, stack):
raise TimedOut
def list (self):
signal.alarm (60)
env = os.environ.copy ()
if RPM_BUILD_ROOT:
buildroot = RPM_BUILD_ROOT
if not buildroot.endswith (os.path.sep):
buildroot += os.path.sep
env["DESTDIR"] = RPM_BUILD_ROOT
env["LD_LIBRARY_PATH"] = "%susr/lib64:%susr/lib" % (buildroot,
buildroot)
p = subprocess.Popen ([self.driver, "list"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env)
try:
(stdout, stderr) = p.communicate ()
signal.alarm (0)
except TimedOut:
posix.kill (p.pid, signal.SIGKILL)
raise
if stderr:
print >> sys.stderr, stderr
ppds = []
lines = stdout.split ('\n')
for line in lines:
l = shlex.split (line)
if len (l) < 5:
continue
self.ids += l[4]
return Driver.list (self)
class DrvDriver(PPDDriver):
def __init__ (self, pathname):
PPDDriver.__init__ (self)
self.drv = pathname
def _alarm (self, sig, stack):
raise TimedOut
def list (self):
tmpdir = os.environ.get ("TMPDIR", "/tmp") + os.path.sep
outputdir = tempfile.mkdtemp (dir=tmpdir)
argv = [ "ppdc",
"-d", outputdir,
"-I", "/usr/share/cups/ppdc",
self.drv ]
signal.alarm (60)
try:
p = subprocess.Popen (argv,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError:
# ppdc not available.
os.rmdir (outputdir)
return Driver.list (self)
try:
(stdout, stderr) = p.communicate ()
signal.alarm (0)
except TimedOut:
posix.kill (p.pid, signal.SIGKILL)
raise
os.path.walk (outputdir, self.examine_directory, None)
os.rmdir (outputdir)
return Driver.list (self)
def examine_directory (self, unused, dirname, fnames):
for fname in fnames:
path = dirname + os.path.sep + fname
self.examine_file (path)
os.unlink (path)
class TagBuilder:
def __init__ (self, filelist=None):
if filelist == None:
filelist = sys.stdin
paths = map (lambda x: x.rstrip (), filelist.readlines ())
self.ids = DeviceIDs ()
for path in paths:
if path.find ("/usr/lib/cups/driver/") != -1:
try:
self.ids += DynamicDriver (path).list ()
except TimedOut:
pass
except OSError, (e, s):
if e == errno.EACCES or e == errno.ENOENT:
# Not executable
pass
else:
raise
if CAN_EXAMINE_PPDS:
for path in paths:
try:
self.ids += PPDDriver (path).list ()
except TimedOut:
pass
def get_tags (self):
return self.ids.get_tags ()
if __name__ == "__main__":
builder = TagBuilder ()
tags = builder.get_tags ()
for tag in tags:
print tag

3
psdriver.attr Normal file
View File

@ -0,0 +1,3 @@
%__psdriver_provides %{_rpmconfigdir}/postscriptdriver.prov
%__psdriver_path ^(/usr/lib/cups/driver/.*|%{_datadir}/cups/drv/.*\.drv)$
%__psdriver_magic ^PPD File.*$

View File

@ -6,15 +6,19 @@
Summary: Python bindings for CUPS
Name: python-cups
Version: 1.9.53
Release: 1%{?dist}
Release: 2%{?dist}
URL: http://cyberelk.net/tim/software/pycups/
Source: http://cyberelk.net/tim/data/pycups/pycups-%{version}.tar.bz2
Source2: psdriver.attr
Source3: postscriptdriver.prov
License: GPLv2+
Group: Development/Languages
BuildRequires: cups-devel
BuildRequires: python2-devel
BuildRequires: epydoc
Conflicts: rpm-build < 4.9.0
%description
This package provides Python bindings for the CUPS API,
known as pycups. It was written for use with
@ -40,17 +44,27 @@ epydoc -o html --html build/lib*/cups.so
%{__python} setup.py install -O1 --skip-build --root %{buildroot}
chmod 755 %{buildroot}%{python_sitearch}/cups.so
mkdir -p %{buildroot}%{_rpmconfigdir}/fileattrs
install -m644 %{SOURCE2} %{buildroot}%{_rpmconfigdir}/fileattrs/
install -m755 %{SOURCE3} %{buildroot}%{_rpmconfigdir}
%files
%defattr(-,root,root,-)
%doc COPYING ChangeLog README NEWS TODO
%{python_sitearch}/cups.so
%{python_sitearch}/pycups*.egg-info
/usr/lib/rpm/fileattrs/psdriver.attr
%{_rpmconfigdir}/postscriptdriver.prov
%files doc
%defattr(-,root,root,-)
%doc examples html
%changelog
* Thu Jan 20 2011 Tim Waugh <twaugh@redhat.com> - 1.9.53-2
- Moved postscriptdriver RPM tagging machinery here. Fixed
leading/trailing whitespace in tags as well.
* Wed Dec 15 2010 Tim Waugh <twaugh@redhat.com> - 1.9.53-1
- 1.9.53 fixing a thread-local storage issue (bug #662805).