root / pkpgcounter / trunk / pkpgpdls / pdlparser.py @ 529

Revision 529, 5.7 kB (checked in by jerome, 16 years ago)

Finalized support for MS documents.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Auth Date Id Rev
RevLine 
[192]1#
2# pkpgcounter : a generic Page Description Language parser
3#
[443]4# (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet <alet@librelogiciel.com>
[463]5# This program is free software: you can redistribute it and/or modify
[192]6# it under the terms of the GNU General Public License as published by
[463]7# the Free Software Foundation, either version 3 of the License, or
[192]8# (at your option) any later version.
[463]9#
[192]10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
[463]16# along with this program.  If not, see <http://www.gnu.org/licenses/>.
[192]17#
18# $Id$
19#
20
[360]21"""This module defines the base class for all Page Description Language parsers."""
22
[199]23import sys
[428]24import os
[199]25
[220]26KILOBYTE = 1024   
27MEGABYTE = 1024 * KILOBYTE   
28FIRSTBLOCKSIZE = 16 * KILOBYTE
29LASTBLOCKSIZE = int(KILOBYTE / 4)
30
[193]31class PDLParserError(Exception):
32    """An exception for PDLParser related stuff."""
33    def __init__(self, message = ""):
34        self.message = message
35        Exception.__init__(self, message)
36    def __repr__(self):
37        return self.message
38    __str__ = __repr__
39       
[192]40class PDLParser :
41    """Generic PDL parser."""
[527]42    totiffcommands = None       # Default command to convert to TIFF
43    required = []               # Default list of required commands
44    openmode = "rb"             # Default file opening mode
[529]45    def __init__(self, parent, filename, (firstblock, lastblock)) :
[192]46        """Initialize the generic parser."""
[520]47        self.parent = parent
[522]48        # We need some copies for later inclusion of parsers which
49        # would modify the parent's values
[529]50        self.filename = filename[:]
[522]51        self.firstblock = firstblock[:]
52        self.lastblock = lastblock[:]
[491]53        self.infile = None
[220]54        if not self.isValid() :
55            raise PDLParserError, "Invalid file format !"
56        try :
57            import psyco 
58        except ImportError :   
59            pass # Psyco is not installed
60        else :   
61            # Psyco is installed, tell it to compile
62            # the CPU intensive methods : PCL and PCLXL
[432]63            # parsing will greatly benefit from this.
[220]64            psyco.bind(self.getJobSize)
[522]65        self.infile = open(self.filename, self.openmode)
66        # self.logdebug("Opened %s in '%s' mode." % (self.filename, self.openmode))
[220]67           
[491]68    def __del__(self) :
69        """Ensures the input file gets closed."""
70        if self.infile :
71            self.infile.close()
72           
[527]73    def findExecutable(self, command) :
74        """Finds an executable in the PATH and returns True if found else False."""
75        for cmd in [p.strip() for p in command.split("|")] : # | can separate alternatives for similar commands (e.g. a2ps|enscript)
76            for path in os.environ.get("PATH", "").split(":") :
77                fullname = os.path.abspath(os.path.join(os.path.expanduser(path), cmd))
78                if os.path.isfile(fullname) and os.access(fullname, os.X_OK) :
79                    return True
80        return False
81       
82    def isMissing(self, commands) :   
83        """Returns True if some required commands are missing, else False.""" 
84        howmanythere = 0
85        for command in commands :
86            if not self.findExecutable(command) :
87                sys.stderr.write("ERROR: %(command)s is missing or not executable. You MUST install it for pkpgcounter to be able to do what you want.\n" % locals())
88                sys.stderr.flush()
89            else :   
90                howmanythere += 1
91        if howmanythere == len(commands) :
92            return False
93        else :   
94            return True
95       
[252]96    def logdebug(self, message) :       
97        """Logs a debug message if needed."""
[520]98        if self.parent.options.debug :
[252]99            sys.stderr.write("%s\n" % message)
100           
[220]101    def isValid(self) :   
[387]102        """Returns True if data is in the expected format, else False."""
[192]103        raise RuntimeError, "Not implemented !"
[220]104       
105    def getJobSize(self) :   
106        """Counts pages in a document."""
107        raise RuntimeError, "Not implemented !"
[362]108       
[492]109    def convertToTiffMultiPage24NC(self, outfname, dpi) :
[362]110        """Converts the input file to TIFF format, X dpi, 24 bits per pixel, uncompressed.
[492]111           Writes TIFF datas to the file named by outfname.
[362]112        """   
[428]113        if self.totiffcommands :
[527]114            if self.isMissing(self.required) :
115                raise PDLParserError, "At least one of the following commands is missing and should be installed for the computation of ink coverage : %s" % repr(self.required)
[522]116            infname = self.filename
[492]117            for totiffcommand in self.totiffcommands :
118                error = False
119                commandline = totiffcommand % locals()
120                # self.logdebug("Executing '%s'" % commandline)
121                status = os.system(commandline)
122                if os.WIFEXITED(status) :
123                    if os.WEXITSTATUS(status) :
[428]124                        error = True
[492]125                else :       
126                    error = True
127                if not os.path.exists(outfname) :
128                    error = True
129                elif not os.stat(outfname).st_size :
130                    error = True
131                else :       
132                    break       # Conversion worked fine it seems.
133                sys.stderr.write("Command failed : %s\n" % repr(commandline))
[428]134            if error :
135                raise PDLParserError, "Problem during conversion to TIFF."
[371]136        else :       
137            raise PDLParserError, "Impossible to compute ink coverage for this file format."
Note: See TracBrowser for help on using the browser.