Skip to content

OpenPrinting/pyppd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pyppd

pyppd is a CUPS PPD generator. It holds a compressed archive of PPDs, which can be listed and retrieved only when needed by CUPS, saving disk space.

Installation

To install pyppd, you can use:

# pip install pyppd

Or download the source package, uncompress, and run as root:

# python3 setup.py install

It depends on Python 3.x (http://www.python.org) and XZ Utils (http://tukaani.org/xz/).

Usage

At first, you have to create a PPD archive. For such, put all PPDs (they might be gzipped) you want to add in the archive inside a single folder (which can have subfolders), then run:

$ pyppd /path/to/your/ppd/folder

It'll create pyppd-ppdfile in your current folder. This executable only works with the same Python version that you used to generate it. You can test it by running:

$ ./pyppd-ppdfile list

And, for reading a PPD from the archive, simply do:

$ ./pyppd-ppdfile cat pyppd-ppdfile:MY-PPD-FILE.PPD

For CUPS to be able to use your newly-created archive, copy pyppd-ppdfile to /usr/lib/cups/driver/ and you're done.

The generated pyppd-ppdfile can be arbitrarily renamed, so that more than one packed repository can be installed on one system. This can be useful if you need better performance, be it in time or memory usage. Note that also the PPD URIs will follow the new name:

$ ./pyppd-ppdfile list
pyppd-ppdfile:LasterStar/LaserStar-XX100.ppd
$ mv pyppd-ppdfile laserstar
$ ./laserstar list
laserstar:LaserStar/LaserStar-XX100.ppd

Testing Framework

Overview

pyppd uses a comprehensive testing approach that includes unit tests, integration tests, and end-to-end functionality tests. The test suite verifies:

  1. Component functionality: Each module is tested in isolation to ensure it correctly performs its specific tasks
  2. Integration between components: Tests verify that modules work correctly together
  3. End-to-end functionality: Tests validate the complete workflow from archive creation to PPD extraction
  4. Command-line interface: Ensures the CLI works as expected with various arguments

Test Architecture

The test suite is organized as follows:

  • tests/test_archiver.py - Tests for the PPD archive creation functionality
  • tests/test_compressor.py - Tests for the compression and decompression functions
  • tests/test_ppd.py - Tests for PPD file parsing functionality
  • tests/test_cli.py - Tests for the command-line interface
  • tests/test_integration.py - End-to-end tests verifying the complete workflow

The tests use temporary directories and sample PPD files to create controlled environments for testing. This approach ensures that tests can run without affecting the system and can be executed in any environment.

Setting Up a Test Environment

For the best testing experience, we recommend using a virtual environment:

# Create a virtual environment
python -m venv pyppd-env

# Activate the virtual environment
# On Linux/macOS:
source pyppd-env/bin/activate
# On Windows:
pyppd-env\Scripts\activate

# Install development dependencies
pip install pytest

Running Tests

There are several ways to run the tests for pyppd. All methods allow you to run the tests without installing pyppd.

Method 1: Using the Makefile

The simplest way to run tests:

$ make -f Makefile.tests test

For verbose output:

$ make -f Makefile.tests test-verbose

To run just the unit tests:

$ make -f Makefile.tests test-unit

To clean test artifacts:

$ make -f Makefile.tests clean-test

Method 2: Using pytest directly

$ PYTHONPATH=. pytest tests/

For more detailed output:

$ PYTHONPATH=. pytest -v tests/

To run only specific test files:

$ PYTHONPATH=. pytest tests/test_archiver.py

Method 3: Using unittest

$ PYTHONPATH=. python3 -m unittest discover -s tests

To run specific test files:

$ PYTHONPATH=. python3 -m unittest tests/test_archiver.py

Running Tests Outside the Source Tree

You can also run tests from outside the source directory:

$ PYTHONPATH=/path/to/pyppd pytest /path/to/pyppd/tests/

Code Coverage

To check test coverage (requires the pytest-cov package):

$ pip install pytest-cov
$ PYTHONPATH=. pytest --cov=pyppd tests/

For a detailed HTML coverage report:

$ PYTHONPATH=. pytest --cov=pyppd --cov-report=html tests/

Implementation Design

pyppd follows a modular design with these core components:

  1. PPD Parser (ppd.py): Parses PPD files to extract printer model information and device IDs.

  2. Compression Engine (compressor.py): Handles compression and decompression using the XZ binary.

  3. Archive Generator (archiver.py): Creates self-extracting Python scripts that contain compressed PPD files with an index for quick access.

  4. Command Runner (runner.py): Provides the command-line interface and handles user input.

The system works as follows:

  1. During archive creation:

    • PPD files are collected from the specified directory
    • Each PPD is parsed to extract metadata
    • All PPDs are concatenated into a single byte array
    • The byte array is compressed with XZ
    • A JSON index is created mapping printer models to their position in the compressed archive
    • The compressed archive and index are embedded in a Python script template
  2. During PPD extraction:

    • The index is decompressed and loaded
    • The requested PPD's position is looked up in the index
    • Only the required portion of the archive is decompressed
    • The PPD is returned to standard output

This design minimizes memory usage while allowing fast access to individual PPD files without decompressing the entire archive.

Contributors

  • Till Kamppeter - Original idea, mentoring and feedback. User #0.
  • Hin-Tak Leung - Lots of technical suggestions.
  • Martin Pitt - Python 3 port.
  • Flávio Ribeiro and Diógenes Fernandes - Refactorings and general Python's best practices tips.
  • Didier Raboud - Make archives reproducible, by sorting the list of found PPDs and using JSON dumps instead of Pickle dumps.
  • Sambhav Dusad - Streaming decompression, to not need to hold the whole decompressed archive in memory.
  • Google's OSPO - Initial funding at GSoC 2010.

About

A CUPS PostScript Printer Driver's compressor and generator

Resources

License

Stars

Watchers

Forks

Packages

No packages published