Created
September 13, 2019 17:11
-
-
Save elmarco/c44d31a476554c88d8b34f468c4e438f to your computer and use it in GitHub Desktop.
Generate depfile for python scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/python3 | |
# coding: utf-8 | |
# Author: Marc-André Lureau <[email protected]> | |
import sys | |
import os | |
import atexit | |
from importlib import invalidate_caches | |
from importlib.machinery import FileFinder, SourceFileLoader | |
class DepLoader(SourceFileLoader): | |
loaded = set() | |
def get_code(self, fullname): | |
self.loaded.add(self.get_filename(fullname)) | |
return super().get_code(fullname) | |
def exit_handler(opts): | |
if not opts.depfile: | |
opts.depfile = os.path.basename(opts.filename) + '.d' | |
with open(opts.depfile, 'w') as out: | |
print('%s: %s' % (opts.filename, ' '.join(DepLoader.loaded)), file=out) | |
def main(): | |
import argparse | |
parser = argparse.ArgumentParser( | |
description='Generate depfile for python scripts') | |
parser.add_argument('-d', '--depfile', | |
help='depfile filename location (default to filename.d)') | |
parser.add_argument('filename', nargs='?', | |
help='file to run as main program') | |
parser.add_argument('arguments', nargs=argparse.REMAINDER, | |
help='arguments to the program') | |
opts = parser.parse_args() | |
if opts.filename is None: | |
parser.error('filename is missing: required with the main options') | |
sys.argv = [opts.filename, *opts.arguments] | |
sys.path[0] = os.path.dirname(opts.filename) | |
loader_details = DepLoader, [".py"] | |
# insert the path hook ahead of other path hooks | |
sys.path_hooks.insert(0, FileFinder.path_hook(loader_details)) | |
# clear any loaders that might already be in use by the FileFinder | |
sys.path_importer_cache.clear() | |
invalidate_caches() | |
atexit.register(exit_handler, opts) | |
try: | |
with open(opts.filename) as fp: | |
code = compile(fp.read(), opts.filename, 'exec') | |
# try to emulate __main__ namespace as much as possible | |
globs = { | |
'__file__': opts.filename, | |
'__name__': '__main__', | |
'__package__': None, | |
'__cached__': None, | |
} | |
exec(code, globs, globs) | |
except OSError as err: | |
sys.exit("Cannot run file %r because: %s" % (sys.argv[0], err)) | |
except SystemExit: | |
pass | |
if __name__=='__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment