Show
Ignore:
Timestamp:
04/04/05 14:18:36 (19 years ago)
Author:
jerome
Message:

More file splits

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • pkpgcounter/trunk/pdlanalyzer/pdlparser.py

    r199 r200  
    2121 
    2222import sys 
    23 import tempfile 
    24  
    25 from pdlanalyzer.postscript import PostScriptParser 
    26 from pdlanalyzer.pdf import PDFParser 
    27 from pdlanalyzer.pcl345 import PCL345Parser 
    28 from pdlanalyzer.pclxl import PCLXLParser 
    29 from pdlanalyzer.escp2 import ESCP2Parser 
    30  
    31 KILOBYTE = 1024     
    32 MEGABYTE = 1024 * KILOBYTE     
    33 LASTBLOCKSIZE = int(KILOBYTE / 4) 
    3423 
    3524class PDLParserError(Exception): 
     
    5241        """Counts pages in the document.""" 
    5342        raise RuntimeError, "Not implemented !" 
    54          
    55 class PDLAnalyzer :     
    56     """Class for PDL autodetection.""" 
    57     def __init__(self, filename, debug=0) : 
    58         """Initializes the PDL analyzer. 
    59          
    60            filename is the name of the file or '-' for stdin. 
    61            filename can also be a file-like object which  
    62            supports read() and seek(). 
    63         """ 
    64         self.debug = debug 
    65         self.filename = filename 
    66         try : 
    67             import psyco  
    68         except ImportError :     
    69             sys.stderr.write("pkpgcounter : you should install psyco if possible, this would greatly speedup parsing.\n") 
    70             pass # Psyco is not installed 
    71         else :     
    72             # Psyco is installed, tell it to compile 
    73             # the CPU intensive methods : PCL and PCLXL 
    74             # parsing will greatly benefit from this,  
    75             # for PostScript and PDF the difference is 
    76             # barely noticeable since they are already 
    77             # almost optimal, and much more speedy anyway. 
    78             psyco.bind(PostScriptParser.getJobSize) 
    79             psyco.bind(PDFParser.getJobSize) 
    80             psyco.bind(ESCP2Parser.getJobSize) 
    81             psyco.bind(PCLParser.getJobSize) 
    82             psyco.bind(PCLXLParser.getJobSize) 
    83          
    84     def getJobSize(self) :     
    85         """Returns the job's size.""" 
    86         self.openFile() 
    87         try : 
    88             pdlhandler = self.detectPDLHandler() 
    89         except PDLParserError, msg :     
    90             self.closeFile() 
    91             raise PDLParserError, "ERROR : Unknown file format for %s (%s)" % (self.filename, msg) 
    92         else : 
    93             try : 
    94                 size = pdlhandler(self.infile, self.debug).getJobSize() 
    95             finally :     
    96                 self.closeFile() 
    97             return size 
    98          
    99     def openFile(self) :     
    100         """Opens the job's data stream for reading.""" 
    101         self.mustclose = 0  # by default we don't want to close the file when finished 
    102         if hasattr(self.filename, "read") and hasattr(self.filename, "seek") : 
    103             # filename is in fact a file-like object  
    104             infile = self.filename 
    105         elif self.filename == "-" : 
    106             # we must read from stdin 
    107             infile = sys.stdin 
    108         else :     
    109             # normal file 
    110             self.infile = open(self.filename, "rb") 
    111             self.mustclose = 1 
    112             return 
    113              
    114         # Use a temporary file, always seekable contrary to standard input. 
    115         self.infile = tempfile.TemporaryFile(mode="w+b") 
    116         while 1 : 
    117             data = infile.read(MEGABYTE)  
    118             if not data : 
    119                 break 
    120             self.infile.write(data) 
    121         self.infile.flush()     
    122         self.infile.seek(0) 
    123              
    124     def closeFile(self) :         
    125         """Closes the job's data stream if we can close it.""" 
    126         if self.mustclose : 
    127             self.infile.close()     
    128         else :     
    129             # if we don't have to close the file, then 
    130             # ensure the file pointer is reset to the  
    131             # start of the file in case the process wants 
    132             # to read the file again. 
    133             try : 
    134                 self.infile.seek(0) 
    135             except :     
    136                 pass    # probably stdin, which is not seekable 
    137          
    138     def isPostScript(self, sdata, edata) :     
    139         """Returns 1 if data is PostScript, else 0.""" 
    140         if sdata.startswith("%!") or \ 
    141            sdata.startswith("\004%!") or \ 
    142            sdata.startswith("\033%-12345X%!PS") or \ 
    143            ((sdata[:128].find("\033%-12345X") != -1) and \ 
    144              ((sdata.find("LANGUAGE=POSTSCRIPT") != -1) or \ 
    145               (sdata.find("LANGUAGE = POSTSCRIPT") != -1) or \ 
    146               (sdata.find("LANGUAGE = Postscript") != -1))) or \ 
    147               (sdata.find("%!PS-Adobe") != -1) : 
    148             if self.debug :   
    149                 sys.stderr.write("%s is a PostScript file\n" % str(self.filename)) 
    150             return 1 
    151         else :     
    152             return 0 
    153          
    154     def isPDF(self, sdata, edata) :     
    155         """Returns 1 if data is PDF, else 0.""" 
    156         if sdata.startswith("%PDF-") or \ 
    157            sdata.startswith("\033%-12345X%PDF-") or \ 
    158            ((sdata[:128].find("\033%-12345X") != -1) and (sdata.upper().find("LANGUAGE=PDF") != -1)) or \ 
    159            (sdata.find("%PDF-") != -1) : 
    160             if self.debug :   
    161                 sys.stderr.write("%s is a PDF file\n" % str(self.filename)) 
    162             return 1 
    163         else :     
    164             return 0 
    165          
    166     def isPCL(self, sdata, edata) :     
    167         """Returns 1 if data is PCL, else 0.""" 
    168         if sdata.startswith("\033E\033") or \ 
    169            (sdata.startswith("\033*rbC") and (not edata[-3:] == "\f\033@")) or \ 
    170            sdata.startswith("\033%8\033") or \ 
    171            (sdata.find("\033%-12345X") != -1) : 
    172             if self.debug :   
    173                 sys.stderr.write("%s is a PCL3/4/5 file\n" % str(self.filename)) 
    174             return 1 
    175         else :     
    176             return 0 
    177          
    178     def isPCLXL(self, sdata, edata) :     
    179         """Returns 1 if data is PCLXL aka PCL6, else 0.""" 
    180         if ((sdata[:128].find("\033%-12345X") != -1) and \ 
    181              (sdata.find(" HP-PCL XL;") != -1) and \ 
    182              ((sdata.find("LANGUAGE=PCLXL") != -1) or \ 
    183               (sdata.find("LANGUAGE = PCLXL") != -1))) : 
    184             if self.debug :   
    185                 sys.stderr.write("%s is a PCLXL (aka PCL6) file\n" % str(self.filename)) 
    186             return 1 
    187         else :     
    188             return 0 
    189              
    190     def isESCP2(self, sdata, edata) :         
    191         """Returns 1 if data is ESC/P2, else 0.""" 
    192         if sdata.startswith("\033@") or \ 
    193            sdata.startswith("\033*") or \ 
    194            sdata.startswith("\n\033@") or \ 
    195            sdata.startswith("\0\0\0\033\1@EJL") : # ESC/P Raster ??? Seen on Stylus Photo 1284 
    196             if self.debug :   
    197                 sys.stderr.write("%s is an ESC/P2 file\n" % str(self.filename)) 
    198             return 1 
    199         else :     
    200             return 0 
    201      
    202     def detectPDLHandler(self) :     
    203         """Tries to autodetect the document format. 
    204          
    205            Returns the correct PDL handler class or None if format is unknown 
    206         """    
    207         # Try to detect file type by reading first block of datas     
    208         self.infile.seek(0) 
    209         firstblock = self.infile.read(4 * KILOBYTE) 
    210         try : 
    211             self.infile.seek(-LASTBLOCKSIZE, 2) 
    212             lastblock = self.infile.read(LASTBLOCKSIZE) 
    213         except IOError :     
    214             lastblock = "" 
    215         self.infile.seek(0) 
    216         if self.isPostScript(firstblock, lastblock) : 
    217             return PostScriptParser 
    218         elif self.isPCLXL(firstblock, lastblock) :     
    219             return PCLXLParser 
    220         elif self.isPDF(firstblock, lastblock) :     
    221             return PDFParser 
    222         elif self.isPCL(firstblock, lastblock) :     
    223             return PCLParser 
    224         elif self.isESCP2(firstblock, lastblock) :     
    225             return ESCP2Parser 
    226         else :     
    227             raise PDLParserError, "Analysis of first data block failed." 
    228              
    229 def main() :     
    230     """Entry point for PDL Analyzer.""" 
    231     if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) : 
    232         sys.argv.append("-") 
    233          
    234     if ("-h" in sys.argv[1:]) or ("--help" in sys.argv[1:]) : 
    235         print "usage : pkpgcounter file1 file2 ... fileN" 
    236     elif ("-v" in sys.argv[1:]) or ("--version" in sys.argv[1:]) : 
    237         print "%s" % version.__version__ 
    238     else : 
    239         totalsize = 0     
    240         debug = 0 
    241         minindex = 1 
    242         if sys.argv[1] == "--debug" : 
    243             minindex = 2 
    244             debug = 1 
    245         for arg in sys.argv[minindex:] : 
    246             try : 
    247                 parser = PDLAnalyzer(arg, debug) 
    248                 totalsize += parser.getJobSize() 
    249             except PDLParserError, msg :     
    250                 sys.stderr.write("ERROR: %s\n" % msg) 
    251                 sys.stderr.flush() 
    252         print "%s" % totalsize 
    253      
    254 if __name__ == "__main__" :     
    255     main()