Skip to content

Allow pystandalone to drop external modules to disk as distributions #4

@Schamper

Description

@Schamper

Sometimes we can't get around a C dependency, and I don't think it'll be possible to load those from memory any time soon... So in those cases we may want to drop them to a temporary directory on disk, and insert them into our search path for modules.

I've previously done that using this piece of code as run.py, but ideally it gets integrated into pystandalone itself:

import os
import sys
import runpy
import argparse
import tempfile
import zipimport
import subprocess

from pathlib import Path


def unpack_dist(tmpdir):
    tmppath = Path(tmpdir)

    # Find decrypted payload zip
    payload_zip = None
    for loader in sys.meta_path:
        if hasattr(loader, 'archive') and loader.archive == '<payload>':
            payload_zip = loader
            break

    if not payload_zip:
        sys.exit("No payload zip")

    for f, toc_entry in payload_zip._files.items():
        if f.endswith('/'):
            continue

        if f.startswith('dist'):
            out_path = tmppath.joinpath(os.path.normpath(f))
            if not out_path.parent.exists():
                out_path.parent.mkdir(parents=True)
            data = zipimport._get_data(payload_zip.archive, toc_entry, payload_zip._buf)
            out_path.write_bytes(data)

    return str(tmppath.joinpath('dist'))


def run_loader(key):
    with tempfile.TemporaryDirectory(prefix='thunderx-decrypt-') as tmpdir:
        dist_dir = unpack_dist(tmpdir)
        print('Unpacked dist to {}'.format(dist_dir))

        sys.argv.insert(1, key)
        subprocess.run(sys.argv + ['--lib', dist_dir])


if __name__ == '__main__':
    key = sys.argv.pop(1)
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument('--lib', help=argparse.SUPPRESS)
    args, remaining = parser.parse_known_args()

    if not args.lib:
        run_loader(key)
    else:
        sys.path.insert(0, args.lib)
        sys.argv = [sys.argv[0]] + remaining
        runpy._run_module_as_main('decrypt', alter_argv=False)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions