CythonScope.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. from __future__ import absolute_import
  2. from .Symtab import ModuleScope
  3. from .PyrexTypes import *
  4. from .UtilityCode import CythonUtilityCode
  5. from .Errors import error
  6. from .Scanning import StringSourceDescriptor
  7. from . import MemoryView
  8. class CythonScope(ModuleScope):
  9. is_cython_builtin = 1
  10. _cythonscope_initialized = False
  11. def __init__(self, context):
  12. ModuleScope.__init__(self, u'cython', None, None)
  13. self.pxd_file_loaded = True
  14. self.populate_cython_scope()
  15. # The Main.Context object
  16. self.context = context
  17. for fused_type in (cy_integral_type, cy_floating_type, cy_numeric_type):
  18. entry = self.declare_typedef(fused_type.name,
  19. fused_type,
  20. None,
  21. cname='<error>')
  22. entry.in_cinclude = True
  23. def is_cpp(self):
  24. # Allow C++ utility code in C++ contexts.
  25. return self.context.cpp
  26. def lookup_type(self, name):
  27. # This function should go away when types are all first-level objects.
  28. type = parse_basic_type(name)
  29. if type:
  30. return type
  31. return super(CythonScope, self).lookup_type(name)
  32. def lookup(self, name):
  33. entry = super(CythonScope, self).lookup(name)
  34. if entry is None and not self._cythonscope_initialized:
  35. self.load_cythonscope()
  36. entry = super(CythonScope, self).lookup(name)
  37. return entry
  38. def find_module(self, module_name, pos):
  39. error("cython.%s is not available" % module_name, pos)
  40. def find_submodule(self, module_name):
  41. entry = self.entries.get(module_name, None)
  42. if not entry:
  43. self.load_cythonscope()
  44. entry = self.entries.get(module_name, None)
  45. if entry and entry.as_module:
  46. return entry.as_module
  47. else:
  48. # TODO: fix find_submodule control flow so that we're not
  49. # expected to create a submodule here (to protect CythonScope's
  50. # possible immutability). Hack ourselves out of the situation
  51. # for now.
  52. raise error((StringSourceDescriptor(u"cython", u""), 0, 0),
  53. "cython.%s is not available" % module_name)
  54. def lookup_qualified_name(self, qname):
  55. # ExprNode.as_cython_attribute generates qnames and we untangle it here...
  56. name_path = qname.split(u'.')
  57. scope = self
  58. while len(name_path) > 1:
  59. scope = scope.lookup_here(name_path[0])
  60. if scope:
  61. scope = scope.as_module
  62. del name_path[0]
  63. if scope is None:
  64. return None
  65. else:
  66. return scope.lookup_here(name_path[0])
  67. def populate_cython_scope(self):
  68. # These are used to optimize isinstance in FinalOptimizePhase
  69. type_object = self.declare_typedef(
  70. 'PyTypeObject',
  71. base_type = c_void_type,
  72. pos = None,
  73. cname = 'PyTypeObject')
  74. type_object.is_void = True
  75. type_object_type = type_object.type
  76. self.declare_cfunction(
  77. 'PyObject_TypeCheck',
  78. CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
  79. CFuncTypeArg("t", c_ptr_type(type_object_type), None)]),
  80. pos = None,
  81. defining = 1,
  82. cname = 'PyObject_TypeCheck')
  83. def load_cythonscope(self):
  84. """
  85. Creates some entries for testing purposes and entries for
  86. cython.array() and for cython.view.*.
  87. """
  88. if self._cythonscope_initialized:
  89. return
  90. self._cythonscope_initialized = True
  91. cython_testscope_utility_code.declare_in_scope(
  92. self, cython_scope=self)
  93. cython_test_extclass_utility_code.declare_in_scope(
  94. self, cython_scope=self)
  95. #
  96. # The view sub-scope
  97. #
  98. self.viewscope = viewscope = ModuleScope(u'view', self, None)
  99. self.declare_module('view', viewscope, None).as_module = viewscope
  100. viewscope.is_cython_builtin = True
  101. viewscope.pxd_file_loaded = True
  102. cythonview_testscope_utility_code.declare_in_scope(
  103. viewscope, cython_scope=self)
  104. view_utility_scope = MemoryView.view_utility_code.declare_in_scope(
  105. self.viewscope, cython_scope=self,
  106. whitelist=MemoryView.view_utility_whitelist)
  107. # self.entries["array"] = view_utility_scope.entries.pop("array")
  108. def create_cython_scope(context):
  109. # One could in fact probably make it a singleton,
  110. # but not sure yet whether any code mutates it (which would kill reusing
  111. # it across different contexts)
  112. return CythonScope(context)
  113. # Load test utilities for the cython scope
  114. def load_testscope_utility(cy_util_name, **kwargs):
  115. return CythonUtilityCode.load(cy_util_name, "TestCythonScope.pyx", **kwargs)
  116. undecorated_methods_protos = UtilityCode(proto=u"""
  117. /* These methods are undecorated and have therefore no prototype */
  118. static PyObject *__pyx_TestClass_cdef_method(
  119. struct __pyx_TestClass_obj *self, int value);
  120. static PyObject *__pyx_TestClass_cpdef_method(
  121. struct __pyx_TestClass_obj *self, int value, int skip_dispatch);
  122. static PyObject *__pyx_TestClass_def_method(
  123. PyObject *self, PyObject *value);
  124. """)
  125. cython_testscope_utility_code = load_testscope_utility("TestScope")
  126. test_cython_utility_dep = load_testscope_utility("TestDep")
  127. cython_test_extclass_utility_code = \
  128. load_testscope_utility("TestClass", name="TestClass",
  129. requires=[undecorated_methods_protos,
  130. test_cython_utility_dep])
  131. cythonview_testscope_utility_code = load_testscope_utility("View.TestScope")