__init__.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. '''
  2. This package provides several entry points
  3. * spec_parser looks for code annotations in the form of formatted comments
  4. * functions defined in toolchain.py:
  5. * generate_cxx: python (str) to c++ code, returns a PythonModule
  6. * compile_cxxfile: c++ (file) to DLL, returns DLL filename
  7. * compile_cxxcode: c++ (str) to DLL, returns DLL filename
  8. * compile_pythrancode: python (str) to so/cpp, returns output filename
  9. * compile_pythranfile: python (file) to so/cpp, returns output filename
  10. * import_pythrancode: python (str) to module, returns loaded module
  11. * import_pythranfile: python (file) to module, returns loaded module
  12. * test_compile: passthrough compile test, raises PythranCompileError Exception.
  13. Basic scenario is to turn a Python AST into C++ code:
  14. >>> code = "def foo(x): return x * 2"
  15. >>> cxx_generator, error_checker = generate_cxx('my_module', code)
  16. >>> cxx = cxx_generator.generate()
  17. To generate a native module, one need to add type information:
  18. >>> cxx = generate_cxx('my_module', code, {'foo':([int],)})
  19. Eventually, the type information can be translated from a string:
  20. >>> spec = spec_parser('#pythran export foo(int)')
  21. >>> cxx = generate_cxx('my_module', code, spec)
  22. Higher level entry points include:
  23. >>> export = '#pythran export foo(int)\\n'
  24. >>> with open('my_module.py', 'w') as fd:
  25. ... _ = fd.write(export + code)
  26. >>> dll_file = compile_pythranfile("my_module.py")
  27. >>> cpp_file = compile_pythranfile("my_module.py",cpponly=True)
  28. >>> dll_file = compile_pythrancode("my_module", export + code)
  29. >>> dll_file = compile_cxxfile("my_module", cpp_file)
  30. It is possible to directly turn pythran code into an imported module:
  31. >>> code = '#pythran export greet()\\ndef greet(): return "demat"'
  32. >>> greeter = import_pythrancode(code)
  33. >>> greeter.greet()
  34. 'demat'
  35. Cleanup
  36. >>> import os, glob
  37. >>> for target in glob.glob('my_module.*'):
  38. ... os.remove(target)
  39. '''
  40. import importlib as _importlib
  41. import pythran.log
  42. from pythran.version import __version__
  43. _submodules = [
  44. 'analyses',
  45. 'backend',
  46. 'config',
  47. 'conversion',
  48. 'cxxgen',
  49. 'cxxtypes',
  50. 'dist',
  51. 'errors',
  52. 'frontend',
  53. 'graph',
  54. 'interval',
  55. 'intrinsic',
  56. 'log',
  57. 'metadata',
  58. 'middlend',
  59. 'openmp',
  60. 'optimizations',
  61. 'passmanager',
  62. 'spec',
  63. 'syntax',
  64. 'tables',
  65. 'toolchain',
  66. 'transformations',
  67. 'types',
  68. 'typing',
  69. 'unparse',
  70. 'utils',
  71. 'version'
  72. ]
  73. _toplevel_objects = [
  74. '__version__',
  75. 'PythranExtension',
  76. 'compile_cxxcode',
  77. 'compile_cxxfile',
  78. 'compile_pythrancode',
  79. 'compile_pythranfile',
  80. 'generate_cxx',
  81. 'get_include',
  82. 'import_pythrancode',
  83. 'import_pythranfile',
  84. 'load_specfile',
  85. 'spec_parser',
  86. 'test_compile',
  87. ]
  88. __all__ = _submodules + _toplevel_objects
  89. def __dir__():
  90. return __all__
  91. def __getattr__(name):
  92. if name in _submodules:
  93. return _importlib.import_module(f'pythran.{name}')
  94. else:
  95. if name == 'PythranExtension':
  96. from pythran.dist import PythranExtension
  97. return PythranExtension
  98. elif name == 'get_include':
  99. from pythran.config import get_include
  100. return get_include
  101. elif name == 'load_specfile':
  102. from pythran.spec import load_specfile
  103. return load_specfile
  104. elif name == 'spec_parser':
  105. from pythran.spec import spec_parser
  106. return spec_parser
  107. elif name in _toplevel_objects:
  108. import pythran.toolchain
  109. return getattr(pythran.toolchain, name)
  110. else:
  111. try:
  112. return globals()[name]
  113. except KeyError:
  114. raise AttributeError(
  115. f"Module 'pythran' has no attribute '{name}'"
  116. )