Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions Lib/test/clinic.test.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,19 +530,19 @@ test_char_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
{
PyObject *return_value = NULL;
char a = 'A';
char b = '\x07';
char c = '\x08';
char b = '\a';
char c = '\b';
char d = '\t';
char e = '\n';
char f = '\x0b';
char g = '\x0c';
char f = '\v';
char g = '\f';
char h = '\r';
char i = '"';
char j = '\'';
char k = '?';
char l = '\\';
char m = '\x00';
char n = '\xff';
char m = '\0';
char n = '\377';

if (!_PyArg_CheckPositional("test_char_converter", nargs, 0, 14)) {
goto exit;
Expand Down Expand Up @@ -936,7 +936,7 @@ static PyObject *
test_char_converter_impl(PyObject *module, char a, char b, char c, char d,
char e, char f, char g, char h, char i, char j,
char k, char l, char m, char n)
/*[clinic end generated code: output=ff11e203248582df input=e42330417a44feac]*/
/*[clinic end generated code: output=6503d15448e1d4c4 input=e42330417a44feac]*/


/*[clinic input]
Expand Down Expand Up @@ -1192,14 +1192,14 @@ test_int_converter

a: int = 12
b: int(accept={int}) = 34
c: int(accept={str}) = 45
c: int(accept={str}) = '-'
d: int(type='myenum') = 67
/

[clinic start generated code]*/

PyDoc_STRVAR(test_int_converter__doc__,
"test_int_converter($module, a=12, b=34, c=45, d=67, /)\n"
"test_int_converter($module, a=12, b=34, c=\'-\', d=67, /)\n"
"--\n"
"\n");

Expand All @@ -1215,7 +1215,7 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
PyObject *return_value = NULL;
int a = 12;
int b = 34;
int c = 45;
int c = '-';
myenum d = 67;

if (!_PyArg_CheckPositional("test_int_converter", nargs, 0, 4)) {
Expand Down Expand Up @@ -1266,7 +1266,7 @@ test_int_converter(PyObject *module, PyObject *const *args, Py_ssize_t nargs)

static PyObject *
test_int_converter_impl(PyObject *module, int a, int b, int c, myenum d)
/*[clinic end generated code: output=fbcfb7554688663d input=d20541fc1ca0553e]*/
/*[clinic end generated code: output=d5357b563bdb8789 input=5d8f4eb5899b24de]*/


/*[clinic input]
Expand Down
229 changes: 229 additions & 0 deletions Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,187 @@ def test_param_with_continuations(self):
p = function.parameters['follow_symlinks']
self.assertEqual(True, p.default)

def test_param_default_none(self):
function = self.parse_function(r"""
module test
test.func
obj: object = None
str: str(accept={str, NoneType}) = None
buf: Py_buffer(accept={str, buffer, NoneType}) = None
""")
p = function.parameters['obj']
self.assertIs(p.default, None)
self.assertEqual(p.converter.py_default, 'None')
self.assertEqual(p.converter.c_default, 'Py_None')

p = function.parameters['str']
self.assertIs(p.default, None)
self.assertEqual(p.converter.py_default, 'None')
self.assertEqual(p.converter.c_default, 'NULL')

p = function.parameters['buf']
self.assertIs(p.default, None)
self.assertEqual(p.converter.py_default, 'None')
self.assertEqual(p.converter.c_default, '{NULL, NULL}')

def test_param_default_null(self):
function = self.parse_function(r"""
module test
test.func
obj: object = NULL
str: str = NULL
buf: Py_buffer = NULL
fsencoded: unicode_fs_encoded = NULL
fsdecoded: unicode_fs_decoded = NULL
""")
p = function.parameters['obj']
self.assertIs(p.default, NULL)
self.assertEqual(p.converter.py_default, '<unrepresentable>')
self.assertEqual(p.converter.c_default, 'NULL')

p = function.parameters['str']
self.assertIs(p.default, NULL)
self.assertEqual(p.converter.py_default, '<unrepresentable>')
self.assertEqual(p.converter.c_default, 'NULL')

p = function.parameters['buf']
self.assertIs(p.default, NULL)
self.assertEqual(p.converter.py_default, '<unrepresentable>')
self.assertEqual(p.converter.c_default, '{NULL, NULL}')

p = function.parameters['fsencoded']
self.assertIs(p.default, NULL)
self.assertEqual(p.converter.py_default, '<unrepresentable>')
self.assertEqual(p.converter.c_default, 'NULL')

p = function.parameters['fsdecoded']
self.assertIs(p.default, NULL)
self.assertEqual(p.converter.py_default, '<unrepresentable>')
self.assertEqual(p.converter.c_default, 'NULL')

def test_param_default_str_literal(self):
function = self.parse_function(r"""
module test
test.func
str: str = ' \t\n\r\v\f\xa0'
buf: Py_buffer(accept={str, buffer}) = ' \t\n\r\v\f\xa0'
""")
p = function.parameters['str']
self.assertEqual(p.default, ' \t\n\r\v\f\xa0')
self.assertEqual(p.converter.py_default, r"' \t\n\r\x0b\x0c\xa0'")
self.assertEqual(p.converter.c_default, r'" \t\n\r\v\f\u00a0"')

p = function.parameters['buf']
self.assertEqual(p.default, ' \t\n\r\v\f\xa0')
self.assertEqual(p.converter.py_default, r"' \t\n\r\x0b\x0c\xa0'")
self.assertEqual(p.converter.c_default,
r'{.buf = " \t\n\r\v\f\302\240", .obj = NULL, .len = 8}')

def test_param_default_bytes_literal(self):
function = self.parse_function(r"""
module test
test.func
str: str(accept={robuffer}) = b' \t\n\r\v\f\xa0'
buf: Py_buffer = b' \t\n\r\v\f\xa0'
""")
p = function.parameters['str']
self.assertEqual(p.default, b' \t\n\r\v\f\xa0')
self.assertEqual(p.converter.py_default, r"b' \t\n\r\x0b\x0c\xa0'")
self.assertEqual(p.converter.c_default, r'" \t\n\r\v\f\240"')

p = function.parameters['buf']
self.assertEqual(p.default, b' \t\n\r\v\f\xa0')
self.assertEqual(p.converter.py_default, r"b' \t\n\r\x0b\x0c\xa0'")
self.assertEqual(p.converter.c_default,
r'{.buf = " \t\n\r\v\f\240", .obj = NULL, .len = 7}')

def test_param_default_byte_literal(self):
function = self.parse_function(r"""
module test
test.func
zero: char = b'\0'
one: char = b'\1'
lf: char = b'\n'
nbsp: char = b'\xa0'
""")
p = function.parameters['zero']
self.assertEqual(p.default, b'\0')
self.assertEqual(p.converter.py_default, r"b'\x00'")
self.assertEqual(p.converter.c_default, r"'\0'")

p = function.parameters['one']
self.assertEqual(p.default, b'\1')
self.assertEqual(p.converter.py_default, r"b'\x01'")
self.assertEqual(p.converter.c_default, r"'\001'")

p = function.parameters['lf']
self.assertEqual(p.default, b'\n')
self.assertEqual(p.converter.py_default, r"b'\n'")
self.assertEqual(p.converter.c_default, r"'\n'")

p = function.parameters['nbsp']
self.assertEqual(p.default, b'\xa0')
self.assertEqual(p.converter.py_default, r"b'\xa0'")
self.assertEqual(p.converter.c_default, r"'\240'")

def test_param_default_unicode_char(self):
function = self.parse_function(r"""
module test
test.func
zero: int(accept={str}) = '\0'
one: int(accept={str}) = '\1'
lf: int(accept={str}) = '\n'
nbsp: int(accept={str}) = '\xa0'
snake: int(accept={str}) = '\U0001f40d'
""")
p = function.parameters['zero']
self.assertEqual(p.default, '\0')
self.assertEqual(p.converter.py_default, r"'\x00'")
self.assertEqual(p.converter.c_default, '0')

p = function.parameters['one']
self.assertEqual(p.default, '\1')
self.assertEqual(p.converter.py_default, r"'\x01'")
self.assertEqual(p.converter.c_default, '0x01')

p = function.parameters['lf']
self.assertEqual(p.default, '\n')
self.assertEqual(p.converter.py_default, r"'\n'")
self.assertEqual(p.converter.c_default, r"'\n'")

p = function.parameters['nbsp']
self.assertEqual(p.default, '\xa0')
self.assertEqual(p.converter.py_default, r"'\xa0'")
self.assertEqual(p.converter.c_default, '0xa0')

p = function.parameters['snake']
self.assertEqual(p.default, '\U0001f40d')
self.assertEqual(p.converter.py_default, "'\U0001f40d'")
self.assertEqual(p.converter.c_default, '0x1f40d')

def test_param_default_bool(self):
function = self.parse_function(r"""
module test
test.func
bool: bool = True
intbool: bool(accept={int}) = True
intbool2: bool(accept={int}) = 2
""")
p = function.parameters['bool']
self.assertIs(p.default, True)
self.assertEqual(p.converter.py_default, 'True')
self.assertEqual(p.converter.c_default, '1')

p = function.parameters['intbool']
self.assertIs(p.default, True)
self.assertEqual(p.converter.py_default, 'True')
self.assertEqual(p.converter.c_default, '1')

p = function.parameters['intbool2']
self.assertEqual(p.default, 2)
self.assertEqual(p.converter.py_default, '2')
self.assertEqual(p.converter.c_default, '2')

def test_param_default_expr_named_constant(self):
function = self.parse_function("""
module os
Expand Down Expand Up @@ -4432,6 +4613,54 @@ def test_format_escape(self):
out = libclinic.format_escape(line)
self.assertEqual(out, expected)

def test_c_bytes_repr(self):
c_bytes_repr = libclinic.c_bytes_repr
self.assertEqual(c_bytes_repr(b''), '""')
self.assertEqual(c_bytes_repr(b'abc'), '"abc"')
self.assertEqual(c_bytes_repr(b'\a\b\f\n\r\t\v'), r'"\a\b\f\n\r\t\v"')
self.assertEqual(c_bytes_repr(b' \0\x7f'), r'" \000\177"')
self.assertEqual(c_bytes_repr(b'"'), r'"\""')
self.assertEqual(c_bytes_repr(b"'"), r'''"'"''')
self.assertEqual(c_bytes_repr(b'\\'), r'"\\"')
self.assertEqual(c_bytes_repr(b'??/'), r'"?\?/"')
self.assertEqual(c_bytes_repr(b'???/'), r'"?\?\?/"')
self.assertEqual(c_bytes_repr(b'\xa0'), r'"\240"')
self.assertEqual(c_bytes_repr(b'\xff'), r'"\377"')

def test_c_str_repr(self):
c_str_repr = libclinic.c_str_repr
self.assertEqual(c_str_repr(''), '""')
self.assertEqual(c_str_repr('abc'), '"abc"')
self.assertEqual(c_str_repr('\a\b\f\n\r\t\v'), r'"\a\b\f\n\r\t\v"')
self.assertEqual(c_str_repr(' \0\x7f'), r'" \000\177"')
self.assertEqual(c_str_repr('"'), r'"\""')
self.assertEqual(c_str_repr("'"), r'''"'"''')
self.assertEqual(c_str_repr('\\'), r'"\\"')
self.assertEqual(c_str_repr('??/'), r'"?\?/"')
self.assertEqual(c_str_repr('???/'), r'"?\?\?/"')
self.assertEqual(c_str_repr('\xa0'), r'"\u00a0"')
self.assertEqual(c_str_repr('\xff'), r'"\u00ff"')
self.assertEqual(c_str_repr('\u20ac'), r'"\u20ac"')
self.assertEqual(c_str_repr('\U0001f40d'), r'"\U0001f40d"')

def test_c_unichar_repr(self):
c_unichar_repr = libclinic.c_unichar_repr
self.assertEqual(c_unichar_repr('a'), "'a'")
self.assertEqual(c_unichar_repr('\n'), r"'\n'")
self.assertEqual(c_unichar_repr('\b'), r"'\b'")
self.assertEqual(c_unichar_repr('\0'), '0')
self.assertEqual(c_unichar_repr('\1'), '0x01')
self.assertEqual(c_unichar_repr('\x7f'), '0x7f')
self.assertEqual(c_unichar_repr(' '), "' '")
self.assertEqual(c_unichar_repr('"'), """'"'""")
self.assertEqual(c_unichar_repr("'"), r"'\''")
self.assertEqual(c_unichar_repr('\\'), r"'\\'")
self.assertEqual(c_unichar_repr('?'), "'?'")
self.assertEqual(c_unichar_repr('\xa0'), '0xa0')
self.assertEqual(c_unichar_repr('\xff'), '0xff')
self.assertEqual(c_unichar_repr('\u20ac'), '0x20ac')
self.assertEqual(c_unichar_repr('\U0001f40d'), '0x1f40d')

def test_indent_all_lines(self):
# Blank lines are expected to be unchanged.
self.assertEqual(libclinic.indent_all_lines("", prefix="bar"), "")
Expand Down
4 changes: 2 additions & 2 deletions Modules/_datetimemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6395,7 +6395,7 @@ datetime_str(PyObject *op)
/*[clinic input]
datetime.datetime.isoformat

sep: int(accept={str}, c_default="'T'", py_default="'T'") = ord('T')
sep: int(accept={str}) = 'T'
timespec: str(c_default="NULL") = 'auto'

Return the time formatted according to ISO.
Expand All @@ -6417,7 +6417,7 @@ terms of the time to include. Valid options are 'auto', 'hours',
static PyObject *
datetime_datetime_isoformat_impl(PyDateTime_DateTime *self, int sep,
const char *timespec)
/*[clinic end generated code: output=9b6ce1383189b0bf input=2fa2512172ccf5d5]*/
/*[clinic end generated code: output=9b6ce1383189b0bf input=db935a57fa697c5e]*/
{
char buffer[100];

Expand Down
7 changes: 4 additions & 3 deletions Modules/_testclinic.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,14 +334,14 @@ int_converter

a: int = 12
b: int(accept={int}) = 34
c: int(accept={str}) = 45
c: int(accept={str}) = '-'
/

[clinic start generated code]*/

static PyObject *
int_converter_impl(PyObject *module, int a, int b, int c)
/*[clinic end generated code: output=8e56b59be7d0c306 input=a1dbc6344853db7a]*/
/*[clinic end generated code: output=8e56b59be7d0c306 input=9a306d4dc907e339]*/
{
RETURN_PACKED_ARGS(3, PyLong_FromLong, long, a, b, c);
}
Expand Down Expand Up @@ -1365,14 +1365,15 @@ clone_f2_impl(PyObject *module, const char *path)
class custom_t_converter(CConverter):
type = 'custom_t'
converter = 'custom_converter'
c_init_default = "<placeholder>" # overridden in pre_render(()

def pre_render(self):
self.c_default = f'''{{
.name = "{self.function.name}",
}}'''

[python start generated code]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=b2fb801e99a06bf6]*/
/*[python end generated code: output=da39a3ee5e6b4b0d input=78fe84e5ecc0481b]*/


/*[clinic input]
Expand Down
Loading
Loading