Skip to content

Commit e8afde6

Browse files
authored
[mypyc] Add missing header declaration for CPyStr_IsTrue (python#10440)
Also add test that will find things missing in headers, as long as they follow our naming convention (CPy*).
1 parent ce98118 commit e8afde6

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

mypyc/lib-rt/CPy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ PyObject *CPyStr_Append(PyObject *o1, PyObject *o2);
390390
PyObject *CPyStr_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end);
391391
bool CPyStr_Startswith(PyObject *self, PyObject *subobj);
392392
bool CPyStr_Endswith(PyObject *self, PyObject *subobj);
393+
bool CPyStr_IsTrue(PyObject *obj);
393394

394395

395396
// Set operations

mypyc/test/test_cheader.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""Test that C functions used in primitives are declared in a header such as CPy.h."""
2+
3+
import glob
4+
import os
5+
import re
6+
import unittest
7+
8+
from mypyc.primitives import registry
9+
from mypyc.primitives.registry import CFunctionDescription
10+
11+
12+
class TestHeaderInclusion(unittest.TestCase):
13+
def test_primitives_included_in_header(self) -> None:
14+
base_dir = os.path.join(os.path.dirname(__file__), '..', 'lib-rt')
15+
with open(os.path.join(base_dir, 'CPy.h')) as f:
16+
header = f.read()
17+
with open(os.path.join(base_dir, 'pythonsupport.h')) as f:
18+
header += f.read()
19+
20+
def check_name(name: str) -> None:
21+
if name.startswith('CPy'):
22+
assert re.search(r'\b{}\b'.format(name), header), (
23+
'"{}" is used in mypyc.primitives but not declared in CPy.h'.format(name))
24+
25+
for values in [registry.method_call_ops.values(),
26+
registry.function_ops.values(),
27+
registry.binary_ops.values(),
28+
registry.unary_ops.values()]:
29+
for ops in values:
30+
if isinstance(ops, CFunctionDescription):
31+
ops = [ops]
32+
for op in ops:
33+
check_name(op.c_function_name)
34+
35+
primitives_path = os.path.join(os.path.dirname(__file__), '..', 'primitives')
36+
for fnam in glob.glob('{}/*.py'.format(primitives_path)):
37+
with open(fnam) as f:
38+
content = f.read()
39+
for name in re.findall(r'c_function_name=["\'](CPy[A-Z_a-z0-9]+)', content):
40+
check_name(name)

0 commit comments

Comments
 (0)