1
from .Symtab import ModuleScope
2
from .PyrexTypes import *
3
from .UtilityCode import CythonUtilityCode
4
from .Errors import error
5
from .Scanning import StringSourceDescriptor
6
from . import MemoryView
7
from .StringEncoding import EncodedString
10
class CythonScope(ModuleScope):
12
_cythonscope_initialized = False
14
def __init__(self, context):
15
ModuleScope.__init__(self, 'cython', None, None)
16
self.pxd_file_loaded = True
17
self.populate_cython_scope()
18
# The Main.Context object
19
self.context = context
21
for fused_type in (cy_integral_type, cy_floating_type, cy_numeric_type):
22
entry = self.declare_typedef(fused_type.name,
26
entry.in_cinclude = True
29
# Allow C++ utility code in C++ contexts.
30
return self.context.cpp
32
def lookup_type(self, name):
33
# This function should go away when types are all first-level objects.
34
type = parse_basic_type(name)
38
return super().lookup_type(name)
40
def lookup(self, name):
41
entry = super().lookup(name)
43
if entry is None and not self._cythonscope_initialized:
44
self.load_cythonscope()
45
entry = super().lookup(name)
49
def find_module(self, module_name, pos):
50
error("cython.%s is not available" % module_name, pos)
52
def find_submodule(self, module_name, as_package=False):
53
entry = self.entries.get(module_name, None)
55
self.load_cythonscope()
56
entry = self.entries.get(module_name, None)
58
if entry and entry.as_module:
59
return entry.as_module
61
# TODO: fix find_submodule control flow so that we're not
62
# expected to create a submodule here (to protect CythonScope's
63
# possible immutability). Hack ourselves out of the situation
65
raise error((StringSourceDescriptor("cython", ""), 0, 0),
66
"cython.%s is not available" % module_name)
68
def lookup_qualified_name(self, qname):
69
# ExprNode.as_cython_attribute generates qnames and we untangle it here...
70
name_path = qname.split('.')
72
while len(name_path) > 1:
73
scope = scope.lookup_here(name_path[0])
75
scope = scope.as_module
80
return scope.lookup_here(name_path[0])
82
def populate_cython_scope(self):
83
# These are used to optimize isinstance in FinalOptimizePhase
84
type_object = self.declare_typedef(
86
base_type = c_void_type,
88
cname = 'PyTypeObject')
89
type_object.is_void = True
90
type_object_type = type_object.type
92
self.declare_cfunction(
94
CFuncType(c_bint_type, [CFuncTypeArg("o", py_object_type, None),
95
CFuncTypeArg("t", c_ptr_type(type_object_type), None)]),
98
cname = 'PyObject_TypeCheck')
100
def load_cythonscope(self):
102
Creates some entries for testing purposes and entries for
103
cython.array() and for cython.view.*.
105
if self._cythonscope_initialized:
108
self._cythonscope_initialized = True
109
cython_testscope_utility_code.declare_in_scope(
110
self, cython_scope=self)
111
cython_test_extclass_utility_code.declare_in_scope(
112
self, cython_scope=self)
117
self.viewscope = viewscope = ModuleScope('view', self, None)
118
self.declare_module('view', viewscope, None).as_module = viewscope
119
viewscope.is_cython_builtin = True
120
viewscope.pxd_file_loaded = True
122
cythonview_testscope_utility_code.declare_in_scope(
123
viewscope, cython_scope=self)
125
view_utility_scope = MemoryView.view_utility_code.declare_in_scope(
126
self.viewscope, cython_scope=self,
127
allowlist=MemoryView.view_utility_allowlist)
129
# Marks the types as being cython_builtin_type so that they can be
130
# extended from without Cython attempting to import cython.view
131
ext_types = [ entry.type
132
for entry in view_utility_scope.entries.values()
133
if entry.type.is_extension_type ]
134
for ext_type in ext_types:
135
ext_type.is_cython_builtin_type = 1
137
# self.entries["array"] = view_utility_scope.entries.pop("array")
140
dc_str = EncodedString('dataclasses')
141
dataclassesscope = ModuleScope(dc_str, self, context=None)
142
self.declare_module(dc_str, dataclassesscope, pos=None).as_module = dataclassesscope
143
dataclassesscope.is_cython_builtin = True
144
dataclassesscope.pxd_file_loaded = True
145
# doesn't actually have any contents
148
def create_cython_scope(context):
149
# One could in fact probably make it a singleton,
150
# but not sure yet whether any code mutates it (which would kill reusing
151
# it across different contexts)
152
return CythonScope(context)
154
# Load test utilities for the cython scope
156
def load_testscope_utility(cy_util_name, **kwargs):
157
return CythonUtilityCode.load(cy_util_name, "TestCythonScope.pyx", **kwargs)
160
undecorated_methods_protos = UtilityCode(proto="""
161
/* These methods are undecorated and have therefore no prototype */
162
static PyObject *__pyx_TestClass_cdef_method(
163
struct __pyx_TestClass_obj *self, int value);
164
static PyObject *__pyx_TestClass_cpdef_method(
165
struct __pyx_TestClass_obj *self, int value, int skip_dispatch);
166
static PyObject *__pyx_TestClass_def_method(
167
PyObject *self, PyObject *value);
170
cython_testscope_utility_code = load_testscope_utility("TestScope")
172
test_cython_utility_dep = load_testscope_utility("TestDep")
174
cython_test_extclass_utility_code = \
175
load_testscope_utility("TestClass", name="TestClass",
176
requires=[undecorated_methods_protos,
177
test_cython_utility_dep])
179
cythonview_testscope_utility_code = load_testscope_utility("View.TestScope")