Coverage for dirimport/gen.py : 92%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import os
2import sys
3import types
4import difflib
5import importlib
6from jinja2 import Template
7from logging import getLogger
9log = getLogger(__name__)
11tmpl = Template("""# Code generated by dirimport - DO NOT EDIT.
12{%- for d in dirs %}
13from . import {{d}} # noqa
14{%- endfor %}
15{%- for f in files %}
16from .{{f}} import * # noqa
17{%- endfor %}
18""")
21def dig(dirname):
22 resd = {}
23 resf = []
24 for f in sorted(os.listdir(dirname)):
25 if f.startswith("_") or f.startswith("."):
26 continue
27 fpath = os.path.join(dirname, f)
28 if os.path.isdir(fpath):
29 x = dig(fpath)
30 if len(x[0]) == 0 and len(x[1]) == 0:
31 continue
32 resd[f] = x
33 elif os.path.isfile(fpath) and f.endswith(".py"):
34 resf.append(f[:-3])
35 return resd, resf
38def generate(data, basename, filename="__init__.py"):
39 dirs, files = data
40 ofn = os.path.join(basename, filename)
41 if len(dirs) == 0 and len(files) == 0:
42 return
43 with open(ofn, "w") as ofp:
44 print(tmpl.render(dirs=dirs.keys(), files=files).strip(), file=ofp)
45 for k, v in dirs.items():
46 generate(v, os.path.join(basename, k), filename)
49def diff(data, basename, filename="__init__.py"):
50 dirs, files = data
51 ofn = os.path.join(basename, filename)
52 if os.path.exists(ofn):
53 orig = list(filter(lambda f: f != "", map(
54 lambda f: f.strip(), open(ofn).readlines())))
55 else:
56 orig = []
57 newtxt = tmpl.render(dirs=dirs.keys(), files=files)
58 newdata = list(filter(lambda f: f.strip() != "", newtxt.split("\n")))
59 res = list(difflib.unified_diff(orig, newdata,
60 fromfile=ofn + ".orig", tofile=ofn))
61 for k, v in dirs.items():
62 res.extend(diff(v, os.path.join(basename, k), filename))
63 return res
66def clear(basename, filename="__init__.py"):
67 for root, dirs, files in os.walk(basename):
68 if filename in files:
69 os.unlink(os.path.join(root, filename))
72def importdata(data, basename, rootdir="."):
73 dirs, files = data
74 res = types.ModuleType(basename)
75 sys.path.insert(0, rootdir)
76 log.debug("path %s", rootdir)
77 for f in files:
78 # from .f import *
79 log.debug("loading(f) %s %s", basename, f)
80 tmp = importlib.import_module(basename + "." + f)
81 log.debug("loaded: %s, file=%s", tmp, tmp.__file__)
82 for v in dir(tmp):
83 if v.startswith("_"):
84 continue
85 if hasattr(res, v):
86 log.info("duplicate symbol %s %s %s", basename, f, v)
87 continue
88 obj = getattr(tmp, v)
89 log.debug("set attribute: %s.%s = %s", res, v, obj)
90 setattr(res, v, obj)
91 sys.path.pop(0)
92 for k, v in dirs.items():
93 log.debug("loading(d) %s %s %s", basename, k, v)
94 setattr(res, k, importdata(v, basename + "." + k, rootdir))
95 return res
98def importall(basename):
99 data = dig(basename)
100 log.debug("dig %s: %s", basename, data)
101 return importdata(data, os.path.basename(basename), os.path.dirname(basename))