Skip to content

Commit 912aaef

Browse files
committed
Solve minor bug in python port with __import__ function.
1 parent 4afeb15 commit 912aaef

File tree

3 files changed

+53
-21
lines changed

3 files changed

+53
-21
lines changed

source/ports/py_port/metacall/api.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def metacall_inspect():
7979
# Save the original Python import
8080
__python_import__ = builtins.__import__
8181

82-
def __metacall_import__(self, name, globals=None, locals=None, fromlist=(), level=0):
82+
def __metacall_import__(name, globals=None, locals=None, fromlist=(), level=0):
8383
def find_handle(handle_name):
8484
metadata = metacall_inspect()
8585

@@ -144,13 +144,22 @@ def generate_module(handle_name, handle):
144144
# Probably in the future we can differenciate between them, but it is not trivial
145145
}
146146

147+
# Try to load it as a Python module
148+
mod = None
149+
150+
with suppress(ImportError):
151+
mod = __python_import__(name, globals, locals, fromlist, level)
152+
153+
if mod:
154+
return mod
155+
147156
# Obtain the extension of the module if any
148-
extension = None if self.count('.') == 0 else self.split('.')[-1]
157+
extension = None if name.count('.') == 0 else name.split('.')[-1]
149158

150159
# Load by extension if there is any (import puppeteer.js)
151160
if extension and extension in extensions_to_tag.keys():
152161
# Get handle name without extension
153-
handle_name = self.split('.')[-2]
162+
handle_name = name.split('.')[-2]
154163

155164
# Check if it is already loaded in MetaCall
156165
handle = find_handle(handle_name)
@@ -159,38 +168,28 @@ def generate_module(handle_name, handle):
159168
# Generate the module from cached handle
160169
return generate_module(handle_name, handle)
161170

162-
if metacall_load_from_file(extensions_to_tag[extension], [self]):
171+
if metacall_load_from_file(extensions_to_tag[extension], [name]):
163172
handle = find_handle(handle_name)
164173
if handle != None:
165174
# Generate the module from cached handle
166175
return generate_module(handle_name, handle)
167176
else:
168-
# Try to load it as a Python module
169-
mod = None
170-
171-
with suppress(ImportError):
172-
# TODO: Why level is not needed? Does it depend on the Python version?
173-
mod = __python_import__(self, name, globals, locals, fromlist) #, level)
174-
175-
if mod:
176-
return mod
177-
178177
# Check if it is already loaded in MetaCall
179-
handle = find_handle(self)
178+
handle = find_handle(name)
180179

181180
if handle != None:
182181
# Generate the module from cached handle
183-
return generate_module(self, handle)
182+
return generate_module(name, handle)
184183

185184
# Otherwhise, try to load it by guessing the loader
186185
for tag in list(set(extensions_to_tag.values())):
187-
if metacall_load_from_file(tag, [self]):
188-
handle = find_handle(self)
186+
if metacall_load_from_file(tag, [name]):
187+
handle = find_handle(name)
189188
if handle != None:
190189
# Generate the module from cached handle
191-
return generate_module(self, handle)
190+
return generate_module(name, handle)
192191

193-
raise ImportError('MetaCall could not import:', self)
192+
raise ImportError('MetaCall could not import:', name)
194193

195194
# Override Python import
196195
builtins.__import__ = __metacall_import__

source/tests/metacall_python_port_test/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ target_compile_definitions(${target}
9696
PRIVATE
9797
${DEFAULT_COMPILE_DEFINITIONS}
9898

99+
# NodeJS Port path
100+
METACALL_PYTHON_PORT_PATH="${CMAKE_SOURCE_DIR}/source/ports/py_port"
101+
99102
# NodeJS Port Test path
100103
METACALL_PYTHON_PORT_TEST_PATH="${CMAKE_SOURCE_DIR}/source/ports/py_port/run_tests.py"
101104
)

source/tests/metacall_python_port_test/source/metacall_python_port_test.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ TEST_F(metacall_python_port_test, DefaultConstructor)
4040
/* Python */
4141
#if defined(OPTION_BUILD_LOADERS_PY)
4242
{
43-
const char * py_scripts[] =
43+
// Run port test
44+
static const char * py_scripts[] =
4445
{
4546
METACALL_PYTHON_PORT_TEST_PATH
4647
};
@@ -52,6 +53,35 @@ TEST_F(metacall_python_port_test, DefaultConstructor)
5253
EXPECT_EQ((int) 0, (int) strcmp(metacall_value_to_string(ret), "Tests passed without errors"));
5354

5455
metacall_value_destroy(ret);
56+
57+
// Test import bug (__metacall_import__() missing 1 required positional argument: 'name')
58+
static const char buffer[] =
59+
"import sys\n"
60+
"from http import client\n"
61+
"def fetch_http_py(url: str):\n"
62+
" try:\n"
63+
" conn = client.HTTPSConnection(url, 443)\n"
64+
" conn.request('GET', '/')\n"
65+
" response = conn.getresponse()\n"
66+
" data = response.read()\n"
67+
" conn.close()\n"
68+
" return data\n"
69+
" except Exception as e:\n"
70+
" print(e)\n"
71+
" sys.stdout.flush()\n"
72+
" return b'<!doctype invalid>'\n";
73+
74+
ASSERT_EQ((int) 0, (int) metacall_load_from_memory("py", buffer, sizeof(buffer), NULL));
75+
76+
ret = metacall("fetch_http_py", "www.google.com");
77+
78+
static const char prefix[] = "<!doctype html>";
79+
80+
ASSERT_EQ((enum metacall_value_id) METACALL_BUFFER, (enum metacall_value_id) metacall_value_id(ret));
81+
82+
EXPECT_EQ((int) 0, (int) strncmp((const char *)metacall_value_to_buffer(ret), prefix, sizeof(prefix) - 1));
83+
84+
metacall_value_destroy(ret);
5585
}
5686
#endif /* OPTION_BUILD_LOADERS_PY */
5787

0 commit comments

Comments
 (0)