/Demo/imputil/knee.py

http://unladen-swallow.googlecode.com/ · Python · 126 lines · 106 code · 13 blank · 7 comment · 35 complexity · ef683a99aa1cd68d9f8297eb44584a52 MD5 · raw file

  1. """An Python re-implementation of hierarchical module import.
  2. This code is intended to be read, not executed. However, it does work
  3. -- all you need to do to enable it is "import knee".
  4. (The name is a pun on the klunkier predecessor of this module, "ni".)
  5. """
  6. import sys, imp, __builtin__
  7. # Replacement for __import__()
  8. def import_hook(name, globals=None, locals=None, fromlist=None):
  9. parent = determine_parent(globals)
  10. q, tail = find_head_package(parent, name)
  11. m = load_tail(q, tail)
  12. if not fromlist:
  13. return q
  14. if hasattr(m, "__path__"):
  15. ensure_fromlist(m, fromlist)
  16. return m
  17. def determine_parent(globals):
  18. if not globals or not globals.has_key("__name__"):
  19. return None
  20. pname = globals['__name__']
  21. if globals.has_key("__path__"):
  22. parent = sys.modules[pname]
  23. assert globals is parent.__dict__
  24. return parent
  25. if '.' in pname:
  26. i = pname.rfind('.')
  27. pname = pname[:i]
  28. parent = sys.modules[pname]
  29. assert parent.__name__ == pname
  30. return parent
  31. return None
  32. def find_head_package(parent, name):
  33. if '.' in name:
  34. i = name.find('.')
  35. head = name[:i]
  36. tail = name[i+1:]
  37. else:
  38. head = name
  39. tail = ""
  40. if parent:
  41. qname = "%s.%s" % (parent.__name__, head)
  42. else:
  43. qname = head
  44. q = import_module(head, qname, parent)
  45. if q: return q, tail
  46. if parent:
  47. qname = head
  48. parent = None
  49. q = import_module(head, qname, parent)
  50. if q: return q, tail
  51. raise ImportError, "No module named " + qname
  52. def load_tail(q, tail):
  53. m = q
  54. while tail:
  55. i = tail.find('.')
  56. if i < 0: i = len(tail)
  57. head, tail = tail[:i], tail[i+1:]
  58. mname = "%s.%s" % (m.__name__, head)
  59. m = import_module(head, mname, m)
  60. if not m:
  61. raise ImportError, "No module named " + mname
  62. return m
  63. def ensure_fromlist(m, fromlist, recursive=0):
  64. for sub in fromlist:
  65. if sub == "*":
  66. if not recursive:
  67. try:
  68. all = m.__all__
  69. except AttributeError:
  70. pass
  71. else:
  72. ensure_fromlist(m, all, 1)
  73. continue
  74. if sub != "*" and not hasattr(m, sub):
  75. subname = "%s.%s" % (m.__name__, sub)
  76. submod = import_module(sub, subname, m)
  77. if not submod:
  78. raise ImportError, "No module named " + subname
  79. def import_module(partname, fqname, parent):
  80. try:
  81. return sys.modules[fqname]
  82. except KeyError:
  83. pass
  84. try:
  85. fp, pathname, stuff = imp.find_module(partname,
  86. parent and parent.__path__)
  87. except ImportError:
  88. return None
  89. try:
  90. m = imp.load_module(fqname, fp, pathname, stuff)
  91. finally:
  92. if fp: fp.close()
  93. if parent:
  94. setattr(parent, partname, m)
  95. return m
  96. # Replacement for reload()
  97. def reload_hook(module):
  98. name = module.__name__
  99. if '.' not in name:
  100. return import_module(name, name, None)
  101. i = name.rfind('.')
  102. pname = name[:i]
  103. parent = sys.modules[pname]
  104. return import_module(name[i+1:], name, parent)
  105. # Save the original hooks
  106. original_import = __builtin__.__import__
  107. original_reload = __builtin__.reload
  108. # Now install our hooks
  109. __builtin__.__import__ = import_hook
  110. __builtin__.reload = reload_hook