@@ -2096,17 +2096,6 @@ def create_default_cimports(self):
20962096 |import numpy as np
20972097 |cimport numpy as numpy
20982098 |import numpy as numpy
2099- |from ArrayWrappers cimport (
2100- | ArrayWrapperFloat, ArrayWrapperDouble,
2101- | ArrayWrapperInt8, ArrayWrapperInt16, ArrayWrapperInt32, ArrayWrapperInt64,
2102- | ArrayWrapperUInt8, ArrayWrapperUInt16, ArrayWrapperUInt32, ArrayWrapperUInt64,
2103- | ArrayViewFloat, ArrayViewDouble,
2104- | ArrayViewInt8, ArrayViewInt16, ArrayViewInt32, ArrayViewInt64,
2105- | ArrayViewUInt8, ArrayViewUInt16, ArrayViewUInt32, ArrayViewUInt64,
2106- | _create_view_float, _create_view_double,
2107- | _create_view_int8, _create_view_int16, _create_view_int32, _create_view_int64,
2108- | _create_view_uint8, _create_view_uint16, _create_view_uint32, _create_view_uint64
2109- |)
21102099 """
21112100 )
21122101
@@ -2119,7 +2108,71 @@ def create_std_cimports(self):
21192108 code .add (stmt )
21202109
21212110 self .top_level_code .append (code )
2111+
2112+ # If numpy is enabled, inline the ArrayWrapper/ArrayView classes
2113+ if self .include_numpy :
2114+ self .inline_array_wrappers ()
2115+
21222116 return code
2117+
2118+ def inline_array_wrappers (self ):
2119+ """Inline ArrayWrapper and ArrayView class definitions for buffer protocol support."""
2120+ # Read both the .pyx and .pxd files
2121+ autowrap_dir = os .path .dirname (os .path .abspath (__file__ ))
2122+ array_wrappers_pyx = os .path .join (autowrap_dir , "data_files" , "autowrap" , "ArrayWrappers.pyx" )
2123+ array_wrappers_pxd = os .path .join (autowrap_dir , "data_files" , "autowrap" , "ArrayWrappers.pxd" )
2124+
2125+ if not os .path .exists (array_wrappers_pyx ):
2126+ L .warning ("ArrayWrappers.pyx not found, skipping inline array wrappers" )
2127+ return
2128+
2129+ with open (array_wrappers_pyx , 'r' ) as f :
2130+ pyx_content = f .read ()
2131+
2132+ # Read .pxd to get attribute declarations
2133+ attribute_declarations = {}
2134+ if os .path .exists (array_wrappers_pxd ):
2135+ with open (array_wrappers_pxd , 'r' ) as f :
2136+ pxd_content = f .read ()
2137+
2138+ # Parse .pxd to extract attribute declarations for each class
2139+ import re
2140+ # Pattern to match class declarations with their attributes
2141+ # Match: "cdef class ClassName:\n cdef type attr\n cdef type attr\n..."
2142+ class_pattern = r'cdef class (\w+):\s*\n((?:\s+cdef .+\n)+)'
2143+ for match in re .finditer (class_pattern , pxd_content ):
2144+ class_name = match .group (1 )
2145+ attrs = match .group (2 )
2146+ # Attrs already has proper indentation from .pxd
2147+ attribute_declarations [class_name ] = attrs .rstrip ()
2148+
2149+ # Now inject the attribute declarations into the .pyx content
2150+ # For each class, add the cdef attributes right after the docstring
2151+ for class_name , attrs in attribute_declarations .items ():
2152+ # Find "cdef class ClassName:" and its docstring, then add attributes after
2153+ pattern = rf'(cdef class { class_name } :\s+""".*?""")\s*\n'
2154+ replacement = rf'\1\n{ attrs } \n '
2155+ pyx_content = re .sub (pattern , replacement , pyx_content , flags = re .DOTALL )
2156+
2157+ # Remove the first few lines (cython directives and module docstring)
2158+ # Keep everything from the first import onward
2159+ lines = pyx_content .split ('\n ' )
2160+ start_idx = 0
2161+ for i , line in enumerate (lines ):
2162+ if line .strip ().startswith ('from cpython.buffer' ):
2163+ start_idx = i
2164+ break
2165+
2166+ wrapper_code_str = '\n ' .join (lines [start_idx :])
2167+
2168+ code = Code ()
2169+ code .add ("""
2170+ |# Inlined ArrayWrapper and ArrayView classes for buffer protocol support
2171+ """ )
2172+ # Add the wrapper code directly
2173+ code .add (wrapper_code_str )
2174+
2175+ self .top_level_code .append (code )
21232176
21242177 def create_includes (self ):
21252178 code = Code ()
0 commit comments