Question

So I am attempting to monkeypatch the shutil module in order to use a recent fix to their make_archive function that allows the creation fo large zip files.

I am proof of concepting something so figured a quick hack to get this issue out of the way would allow me to get on with what I want to do.

My code:

import shutil
import os

def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
    zip_filename = base_name + ".zip"
    archive_dir = os.path.dirname(base_name)

    if not os.path.exists(archive_dir):
        if logger is not None:
            logger.info("creating %s", archive_dir)
        if not dry_run:
            os.makedirs(archive_dir)

    # If zipfile module is not available, try spawning an external 'zip'
    # command.
    try:
        import zipfile
    except ImportError:
        zipfile = None

    if zipfile is None:
        shutil._call_external_zip(base_dir, zip_filename, verbose, dry_run)
    else:
        if logger is not None:
            logger.info("creating '%s' and adding '%s' to it",
                        zip_filename, base_dir)

        if not dry_run:
            zip = zipfile.ZipFile(zip_filename, "w",
                                  compression=zipfile.ZIP_DEFLATED,
                                  allowZip64=True) # this is the extra argument

            for dirpath, dirnames, filenames in os.walk(base_dir):
                for name in filenames:
                    path = os.path.normpath(os.path.join(dirpath, name))
                    if os.path.isfile(path):
                        zip.write(path, path)
                        if logger is not None:
                            logger.info("adding '%s'", path)
            zip.close()

shutil._make_zipfile = _make_zipfile

# This function calls _make_zipfile when it runs
shutil.make_archive('blah', someargs)

So the issue is... it doesn't do anything. I am clearly doing something stupid, but for the life of me I can not see what it is. I am assuming there is something obvious that I have become blind to after looking at it for so long, so need some fresh eyes. I have tried following methods/checking against answers described in these:

Monkey-patch Python class Python monkey patch private function and What is a monkey patch?

plus some others. No joy

Was it helpful?

Solution

You'll have to update the _ARCHIVE_FORMATS mapping; it stores a reference to the function on import, so before you can patch it. shutil.make_archive() uses that mapping, and not the _make_zipfile function directly.

You can use the public shutil.register_archive_format() function to re-define the zip archiver:

shutil.register_archive_format('zip', _make_zipfile, description='ZIP file')

This replaces the existing callable registered for the zip format.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top