Hide keyboard shortcuts

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 

8 

9log = getLogger(__name__) 

10 

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""") 

19 

20 

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 

36 

37 

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) 

47 

48 

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 

64 

65 

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)) 

70 

71 

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 

96 

97 

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))