Skip to content

Instantly share code, notes, and snippets.

@elmarco
Created September 13, 2019 17:11
Show Gist options
  • Save elmarco/c44d31a476554c88d8b34f468c4e438f to your computer and use it in GitHub Desktop.
Save elmarco/c44d31a476554c88d8b34f468c4e438f to your computer and use it in GitHub Desktop.
Generate depfile for python scripts
#! /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