_build_tlz.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import sys
  2. import types
  3. import toolz
  4. from importlib import import_module
  5. from importlib.machinery import ModuleSpec
  6. class TlzLoader:
  7. """ Finds and loads ``tlz`` modules when added to sys.meta_path"""
  8. def __init__(self):
  9. self.always_from_toolz = {
  10. toolz.pipe,
  11. }
  12. def _load_toolz(self, fullname):
  13. rv = {}
  14. package, dot, submodules = fullname.partition('.')
  15. try:
  16. module_name = ''.join(['cytoolz', dot, submodules])
  17. rv['cytoolz'] = import_module(module_name)
  18. except ImportError:
  19. pass
  20. try:
  21. module_name = ''.join(['toolz', dot, submodules])
  22. rv['toolz'] = import_module(module_name)
  23. except ImportError:
  24. pass
  25. if not rv:
  26. raise ImportError(fullname)
  27. return rv
  28. def find_module(self, fullname, path=None): # pragma: py3 no cover
  29. package, dot, submodules = fullname.partition('.')
  30. if package == 'tlz':
  31. return self
  32. def load_module(self, fullname): # pragma: py3 no cover
  33. if fullname in sys.modules: # pragma: no cover
  34. return sys.modules[fullname]
  35. spec = ModuleSpec(fullname, self)
  36. module = self.create_module(spec)
  37. sys.modules[fullname] = module
  38. self.exec_module(module)
  39. return module
  40. def find_spec(self, fullname, path, target=None): # pragma: no cover
  41. package, dot, submodules = fullname.partition('.')
  42. if package == 'tlz':
  43. return ModuleSpec(fullname, self)
  44. def create_module(self, spec):
  45. return types.ModuleType(spec.name)
  46. def exec_module(self, module):
  47. toolz_mods = self._load_toolz(module.__name__)
  48. fast_mod = toolz_mods.get('cytoolz') or toolz_mods['toolz']
  49. slow_mod = toolz_mods.get('toolz') or toolz_mods['cytoolz']
  50. module.__dict__.update(toolz.merge(fast_mod.__dict__, module.__dict__))
  51. package = fast_mod.__package__
  52. if package is not None:
  53. package, dot, submodules = package.partition('.')
  54. module.__package__ = ''.join(['tlz', dot, submodules])
  55. if not module.__doc__:
  56. module.__doc__ = fast_mod.__doc__
  57. # show file from toolz during introspection
  58. try:
  59. module.__file__ = slow_mod.__file__
  60. except AttributeError:
  61. pass
  62. for k, v in fast_mod.__dict__.items():
  63. tv = slow_mod.__dict__.get(k)
  64. try:
  65. hash(tv)
  66. except TypeError:
  67. tv = None
  68. if tv in self.always_from_toolz:
  69. module.__dict__[k] = tv
  70. elif (
  71. isinstance(v, types.ModuleType)
  72. and v.__package__ == fast_mod.__name__
  73. ):
  74. package, dot, submodules = v.__name__.partition('.')
  75. module_name = ''.join(['tlz', dot, submodules])
  76. submodule = import_module(module_name)
  77. module.__dict__[k] = submodule
  78. tlz_loader = TlzLoader()
  79. sys.meta_path.append(tlz_loader)
  80. tlz_loader.exec_module(sys.modules['tlz'])