puremagic

repository·master·Indexed 42 days ago

https://github.com/cdgriffith/puremagic

A lightweight, zero-dependency, pure-Python module for identifying file types (MIME types and extensions) based on magic numbers. It provides a cross-platform alternative to python-magic/libmagic with a CLI and support for deep scanning of complex formats like ZIP, PDF, and JSON via the PUREMAGIC_DEEPSCAN environment variable. Supports Python 3.12+ (v2.x) and Python 3.7–3.11 (v1.x).

Tokens
2.7K
Snippets
15
Records
19
Agent score
52%

What's inside puremagic

  1. How Deep Scan works and how to disable it

    master

    Deep scan is a content-aware analysis system enabled by default in version 2.0+. It performs analysis beyond simple magic number matching to improve accuracy for complex formats like Office documents, CSV, MP3, Python source, and JSON.

    Included Scanners:

    • ZIP: Distinguishes Office (xlsx/docx/pptx) and OpenDocument formats.
    • MPEG Audio: Validates MP3/MPEG frames.
    • Text: Detects encodings, line endings, CSV delimiters, and email (.eml).
    • Python: Validates source via ast.parse().
    • PDF/JSON/HDF5: Format-specific validation.
    • Scientific/Bioinformatics: Recognizes formats like VCF, SAM, GFF, etc.

    To disable deep scan, set the PUREMAGIC_DEEPSCAN environment variable to 0.

    $ export PUREMAGIC_DEEPSCAN=0
  2. Install puremagic via pip

    master

    Install the puremagic package using pip. For Linux environments, it is recommended to use python3 -m pip to ensure it is installed for the correct Python version.

    Compatibility Note:

    • Python 3.12+: Use the current 2.x release.
    • Python 3.7–3.11: Use the 1.x release chain.
    $ pip install puremagic
    
    # On Linux
    $ python3 -m pip install puremagic
  3. Migrating from puremagic 1.x to 2.x

    master

    Version 2.0 introduced several breaking changes:

    • Python Version: Requires Python 3.12+. For 3.7–3.11, stay on the 1.x release chain.
    • Removed puremagic.what(): Use puremagic.from_file() instead.
    • Removed Public API members: magic_header_array, magic_footer_array, and multi_part_dict are no longer available.
    • Build System: setup.py has been removed in favor of pyproject.toml.
    • Internal Renaming: Some internal functions have been renamed from private (e.g., _magic_data) to public (e.g., magic_data).
  4. Use puremagic for file type identification

    master

    The puremagic package provides tools to identify file types (MIME types and names) by inspecting their magic bytes. The package exposes its primary functionality through the puremagic.main module. Common tasks include identifying a file's type from a path or performing a deep scan to find multiple potential matches based on byte patterns and confidence levels.

    import puremagic
    
    # Example usage (based on package capabilities):
    # result = puremagic.identify('/path/to/file')
    # print(result)
  5. PureMagic Data Structures

    master

    The library uses two primary namedtuple structures to represent file identification results:

    1. PureMagic: The base structure containing:

      • byte_match: The actual bytes matched.
      • offset: The position in the file where the match occurs.
      • extension: The file extension.
      • mime_type: The MIME type string.
      • name: The human-readable name.
    2. PureMagicWithConfidence: Extends PureMagic by adding:

      • confidence: A float representing the certainty of the match.
  6. Get detailed file identification with magic_file()

    master

    Use puremagic.magic_file(filename) to retrieve all possible matches found for a file. This method provides more detail than from_file(), including confidence scores and duplicate matches.

    Each match in the returned list is ordered by highest confidence first and contains:

    • Possible extension(s)
    • MIME type
    • Description
    • Confidence (based on header length/precision)
    import puremagic
    
    filename = "test/resources/images/test.gif"
    results = puremagic.magic_file(filename)
    # [['.gif', 'image/gif', 'Graphics interchange format file (GIF87a)', 0.7], 
    #  ['.gif', '', 'GIF file', 0.5]]
  7. Identify files from strings or streams

    master

    If you are working with raw bytes, open file handles, or strings, use the following functions:

    • from_string(string[, mime]): Identify from a byte string.
    • from_stream(stream[, mime]): Identify from a file-like stream object.
    • magic_string(string[, mime]): Detailed identification from a byte string.
    • magic_stream(stream[, mime]): Detailed identification from a file-like stream object.
    import puremagic
    
    # Using a stream
    with open(r"test\resources\video\test.mp4", "rb") as file:
        print(puremagic.magic_stream(file))
    
    # Returns a list of PureMagicWithConfidence objects
  8. Identify file extensions with from_file()

    master

    Use puremagic.from_file(filename[, mime]) to quickly retrieve the most likely file extension for a given file path. This is a minimalistic function designed to be a lightweight alternative to python-magic.

    import puremagic
    
    filename = "test/resources/images/test.gif"
    ext = puremagic.from_file(filename)
    # '.gif'
  9. Enable Deep Scanning via `PUREMAGIC_DEEPSCAN`

    master

    By default, puremagic performs a fast identification based on magic numbers (headers and footers). To enable more intensive scanning (e.g., using specialized scanners for ZIP, PDF, JSON, etc.), set the environment variable PUREMAGIC_DEEPSCAN to something other than '0'.

    When enabled, functions like magic_file(), magic_string(), and from_file() will attempt to use specialized scanners to verify the file type, which can significantly increase accuracy for complex formats.

  10. Use the puremagic CLI

    master

    You can run puremagic directly from the command line to scan files or directories.

    Command Syntax: python -m puremagic [options] filename <filename2>...

    Options:

    • -m, --mime: Return the MIME type instead of the file extension.
    • -v, --verbose: Print verbose output with all possible matches.
    • --version: Show program version.

    Examples:

    # Basic scan
    $ python -m puremagic test/resources/images/test.gif
    'test/resources/images/test.gif' : .gif
    
    # Scan with MIME type output
    $ python -m puremagic -m test/resources/images/test.gif test/resources/audio/test.mp3
    'test/resources/images/test.gif' : image/gif
    'test/resources/audio/test.mp3' : audio/mpeg
  11. Get detailed identification results from a string with `magic_string()`

    master

    Use magic_string(string, filename=None) to get a list of PureMagicWithConfidence objects for a given byte sequence or string. Similar to magic_file(), it provides detailed metadata and supports deep scanning if PUREMAGIC_DEEPSCAN is enabled.

    import puremagic
    
    matches = puremagic.magic_string(b'\x47\x49\x46\x38\x39\x61')
    for match in matches:
        print(f"Match: {match.name} ({match.mime_type})")
  12. Get detailed identification results with `magic_file()`

    master

    If you need more than just the extension (e.g., confidence scores, MIME types, or multiple possible matches), use magic_file(filename). It returns a list of PureMagicWithConfidence objects sorted by confidence descending.

    Note: If the environment variable PUREMAGIC_DEEPSCAN is not set to '0', this function will perform a deep scan using specialized scanners to improve accuracy.

    import puremagic
    
    matches = puremagic.magic_file('path/to/file')
    for match in matches:
        print(f"Name: {match.name}, Confidence: {match.confidence}, Extension: {match.extension}")