~ubuntu-branches/ubuntu/quantal/gutenprint/quantal

« back to all changes in this revision

Viewing changes to debian/local/pyppd/pyppd/archiver.py

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2010-08-31 11:01:53 UTC
  • Revision ID: james.westby@ubuntu.com-20100831110153-j8yhsaewp4ohj1q3
Tags: 5.2.6-0ubuntu2
* debian/control, debian/rules, debian/ijsgutenprint-ppds.postinst,
  debian/ijsgutenprint-ppds.install: Introduced the binary package
  ijsgutenprint-ppds. This package contains all PPDs which can be generated
  from the Foomatic XML database for ijsgutenprint in one compressed pyppd
  archive. This takes much less disk space than the XML database (1.1 MB vs.
  102 MB) and access (listing all PPDs, extracting the needed PPD) is also
  significantly faster.
* debian/local/pyppd/: Added pyppd scripts to generate compressed PPD
  archives.
* debian/rules: debian/install-stamp rule was executed twice during build.
  Corrected it to avoid duplicate pre-build of the PPD files for
  ijsgutenprint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import base64
 
2
import sys
 
3
import os
 
4
import fnmatch
 
5
import cPickle
 
6
import gzip
 
7
import logging
 
8
from random import randint
 
9
import compressor
 
10
import ppd
 
11
 
 
12
def archive(ppds_directory):
 
13
    """Returns a string with the decompressor, its dependencies and the archive.
 
14
 
 
15
    It reads the template at pyppd/pyppd-ppdfile.in, inserts the dependencies
 
16
    and the archive encoded in base64, and returns as a string.
 
17
 
 
18
    """
 
19
    logging.info('Compressing folder "%s".' % ppds_directory)
 
20
    ppds_compressed = compress(ppds_directory)
 
21
    if not ppds_compressed:
 
22
        return None
 
23
 
 
24
    ppds_compressed_b64 = base64.b64encode(ppds_compressed)
 
25
 
 
26
    logging.info('Populating template.')
 
27
    template = read_file_in_syspath("pyppd/pyppd-ppdfile.in")
 
28
    compressor_py = read_file_in_syspath("pyppd/compressor.py")
 
29
 
 
30
    template = template.replace("@compressor@", compressor_py)
 
31
    template = template.replace("@ppds_compressed_b64@", ppds_compressed_b64)
 
32
 
 
33
    return template
 
34
 
 
35
def compress(directory):
 
36
    """Compresses and indexes *.ppd and *.ppd.gz in directory returning a string.
 
37
 
 
38
    The directory is walked recursively, concatenating all ppds found in a string.
 
39
    For each, it tests if its filename ends in *.gz. If so, opens with gzip. If
 
40
    not, opens directly. Then, it parses and saves its name, description (in the
 
41
    format CUPS needs (which can be more than one)) and it's position in the ppds
 
42
    string (start position and length) into a dictionary, used as an index.
 
43
    Then, it compresses the string, adds into the dictionary as key ARCHIVE and
 
44
    returns a compressed pickle dump of it.
 
45
 
 
46
    """
 
47
    ppds = ""
 
48
    ppds_index = {}
 
49
    abs_directory = os.path.abspath(directory)
 
50
 
 
51
    for ppd_path in find_files(directory, ("*.ppd", "*.ppd.gz")):
 
52
        # Remove 'directory/' from the filename
 
53
        ppd_filename = ppd_path[len(abs_directory)+1:]
 
54
 
 
55
        if ppd_path.lower().endswith(".gz"):
 
56
            ppd_file = gzip.open(ppd_path).read()
 
57
            # We don't want the .gz extension in our filename
 
58
            ppd_filename = ppd_filename[:-3]
 
59
        else:
 
60
            ppd_file = open(ppd_path).read()
 
61
 
 
62
        start = len(ppds)
 
63
        length = len(ppd_file)
 
64
        logging.debug('Found %s (%d bytes).' % (ppd_path, length))
 
65
 
 
66
        ppd_parsed = ppd.parse(ppd_file, ppd_filename)
 
67
        ppd_descriptions = map(str, ppd_parsed)
 
68
        ppds_index[ppd_parsed[0].uri] = (start, length, ppd_descriptions)
 
69
        logging.debug('Adding %d entry(ies): %s.' % (len(ppd_descriptions), map(str, ppd_parsed)))
 
70
        ppds += ppd_file
 
71
 
 
72
    if not ppds:
 
73
        logging.error('No PPDs found in folder "%s".' % directory)
 
74
        return None
 
75
 
 
76
    logging.info('Compressing archive.')
 
77
    ppds_index['ARCHIVE'] = compressor.compress(ppds)
 
78
    logging.info('Generating and compressing pickle dump.')
 
79
    ppds_pickle = compressor.compress(cPickle.dumps(ppds_index))
 
80
 
 
81
 
 
82
    return ppds_pickle
 
83
 
 
84
 
 
85
def read_file_in_syspath(filename):
 
86
    """Reads the file in filename in each sys.path.
 
87
 
 
88
    If we couldn't find, throws the last IOError caught.
 
89
 
 
90
    """
 
91
    last_exception = None
 
92
    for path in sys.path:
 
93
        try:
 
94
            return open(path + "/" + filename).read()
 
95
        except IOError as ex:
 
96
            last_exception = ex
 
97
            continue
 
98
    raise last_exception
 
99
 
 
100
def find_files(directory, patterns):
 
101
    """Yields each file that matches any of patterns in directory."""
 
102
    logging.debug('Searching for "%s" files in folder "%s".' %
 
103
                  (", ".join(patterns), directory))
 
104
    abs_directory = os.path.abspath(directory)
 
105
    for root, dirnames, filenames in os.walk(abs_directory):
 
106
        for pattern in patterns:
 
107
            for filename in fnmatch.filter(filenames, pattern):
 
108
                yield os.path.join(root, filename)