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
132 changes: 132 additions & 0 deletions Lib/test/test_clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,18 @@ def checkDocstring(self, fn, expected):
self.assertEqual(dedent(expected).strip(),
fn.docstring.strip())

def parse_warnings(self, block):
"""Parse a block and return what Argument Clinic warned about."""
with support.captured_stdout() as stdout:
self.parse(block)
return stdout.getvalue()

def too_long_warning(self, full_name, max_width):
"""The warning emitted for a too long docstring body line."""
return (f"Warning in file {'clinic_tests'!r}:\n"
f"Docstring lines for {full_name!r} are too long!\n"
f"Lines should be no longer than {max_width} characters.\n\n")

def test_trivial(self):
parser = DSLParser(_make_clinic())
block = Block("""
Expand Down Expand Up @@ -2499,6 +2511,126 @@ def test_docstring_explicit_params_placement(self):
(Note the added newline)
""")

def test_long_summary_line(self):
# The summary line must fit in 72 characters for a function.
block = f"""
module m
m.f
{'x' * 73}
"""
err = ("Summary line for 'm.f' is too long!\n"
"The summary line must be no longer than 72 characters.")
self.expect_failure(block, err)

def test_long_summary_line_permitted(self):
block = f"""
@permit_long_summary
module m
m.f
{'x' * 73}
"""
self.assertEqual(self.parse_warnings(block), "")

def test_long_parameter_docstring(self):
# gh-155228: a parameter description is part of the docstring body,
# even though it is only substituted for the {parameters} marker
# after the width check. Descriptions are indented by 4 spaces.
expected = self.too_long_warning('m.f', 72)
for length, warning in (68, ""), (69, expected):
with self.subTest(length=length):
block = f"""
module m
m.f
a: int
{'x' * length}
The summary line.
"""
self.assertEqual(self.parse_warnings(block), warning)

def test_long_parameter_docstring_method(self):
# Methods get 4 characters less than functions.
expected = self.too_long_warning('m.C.f', 68)
for length, warning in (64, ""), (65, expected):
with self.subTest(length=length):
block = f"""
module m
class m.C "void *" ""
m.C.f
a: int
{'x' * length}
The summary line.
"""
self.assertEqual(self.parse_warnings(block), warning)

def test_long_parameter_docstring_indented_marker(self):
# linear_format() indents the substituted parameters by the
# indentation of the {parameters} marker line, which counts
# towards the width as well.
expected = self.too_long_warning('m.f', 72)
for length, warning in (66, ""), (67, expected):
with self.subTest(length=length):
block = f"""
module m
m.f
a: int
{'x' * length}
The summary line.

{{parameters}}
"""
self.assertEqual(self.parse_warnings(block), warning)

def test_long_parameter_docstring_permitted(self):
block = f"""
@permit_long_docstring_body
module m
m.f
a: int
{'x' * 69}
The summary line.
"""
self.assertEqual(self.parse_warnings(block), "")

def test_permit_long_docstring_body_not_needed(self):
block = f"""
@permit_long_docstring_body
module m
m.f
a: int
{'x' * 68}
The summary line.
"""
expected = (
f"Warning in file {'clinic_tests'!r}:\n"
"Remove the @permit_long_docstring_body decorator from 'm.f'!\n\n\n"
)
self.assertEqual(self.parse_warnings(block), expected)

def test_long_parameter_docstring_cloned(self):
# gh-155228: a clone inherits the parameter descriptions of the
# function it clones, so it must be reported as well.
# The clone lives in its own block, as it does in the source tree.
blocks = (
f"""
module m
m.f
a: int
{'x' * 69}
The summary line.
""",
"""
m.g = m.f
The other summary line.
""",
)
parser = DSLParser(_make_clinic())
with support.captured_stdout() as stdout:
for text in blocks:
parser.parse(Block(text))
expected = "".join(self.too_long_warning(f'm.{name}', 72)
for name in ("f", "g"))
self.assertEqual(stdout.getvalue(), expected)

def test_indent_stack_no_tabs(self):
block = """
module foo
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Argument Clinic now checks the length of parameter descriptions, which were
previously left out of the docstring line width check. Too long parameter
descriptions of 30 functions were rewrapped.
22 changes: 11 additions & 11 deletions Modules/_lzmamodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,20 +1186,20 @@ _lzma.LZMADecompressor.__new__

format: int(c_default="FORMAT_AUTO") = FORMAT_AUTO
Specifies the container format of the input stream. If this is
FORMAT_AUTO (the default), the decompressor will automatically detect
whether the input is FORMAT_XZ or FORMAT_ALONE. Streams created with
FORMAT_RAW cannot be autodetected.
FORMAT_AUTO (the default), the decompressor will automatically
detect whether the input is FORMAT_XZ or FORMAT_ALONE. Streams
created with FORMAT_RAW cannot be autodetected.

memlimit: object = None
Limit the amount of memory used by the decompressor. This will cause
decompression to fail if the input cannot be decompressed within the
given limit.
Limit the amount of memory used by the decompressor. This will
cause decompression to fail if the input cannot be decompressed
within the given limit.

filters: object = None
A custom filter chain. This argument is required for FORMAT_RAW, and
not accepted with any other format. When provided, this should be a
sequence of dicts, each indicating the ID and options for a single
filter.
A custom filter chain. This argument is required for FORMAT_RAW,
and not accepted with any other format. When provided, this
should be a sequence of dicts, each indicating the ID and options
for a single filter.

Create a decompressor object for decompressing data incrementally.

Expand All @@ -1209,7 +1209,7 @@ For one-shot decompression, use the decompress() function instead.
static PyObject *
_lzma_LZMADecompressor_impl(PyTypeObject *type, int format,
PyObject *memlimit, PyObject *filters)
/*[clinic end generated code: output=2d46d5e70f10bc7f input=ca40cd1cb1202b0d]*/
/*[clinic end generated code: output=2d46d5e70f10bc7f input=a9b1c4db9f5acb69]*/
{
Decompressor *self;
const uint32_t decoder_flags = LZMA_TELL_ANY_CHECK | LZMA_TELL_NO_CHECK;
Expand Down
8 changes: 5 additions & 3 deletions Modules/_sqlite/clinic/connection.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions Modules/_sqlite/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -2539,7 +2539,8 @@ is_int_config(const int op)
_sqlite3.Connection.setconfig as setconfig

op: int
The configuration verb; one of the sqlite3.SQLITE_DBCONFIG codes.
The configuration verb;
one of the sqlite3.SQLITE_DBCONFIG codes.
enable: bool = True
/

Expand All @@ -2548,7 +2549,7 @@ Set a boolean connection configuration option.

static PyObject *
setconfig_impl(pysqlite_Connection *self, int op, int enable)
/*[clinic end generated code: output=c60b13e618aff873 input=a10f1539c2d7da6b]*/
/*[clinic end generated code: output=c60b13e618aff873 input=8f00e4c0d499abcb]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return NULL;
Expand All @@ -2574,15 +2575,16 @@ setconfig_impl(pysqlite_Connection *self, int op, int enable)
_sqlite3.Connection.getconfig as getconfig -> bool

op: int
The configuration verb; one of the sqlite3.SQLITE_DBCONFIG codes.
The configuration verb;
one of the sqlite3.SQLITE_DBCONFIG codes.
/

Query a boolean connection configuration option.
[clinic start generated code]*/

static int
getconfig_impl(pysqlite_Connection *self, int op)
/*[clinic end generated code: output=25ac05044c7b78a3 input=b0526d7e432e3f2f]*/
/*[clinic end generated code: output=25ac05044c7b78a3 input=835b01bdd9069c02]*/
{
if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {
return -1;
Expand Down
6 changes: 3 additions & 3 deletions Modules/_sre/clinic/sre.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Modules/_sre/sre.c
Original file line number Diff line number Diff line change
Expand Up @@ -1862,16 +1862,16 @@ _sre.template

pattern: object
template: object(subclass_of="&PyList_Type")
A list containing interleaved literal strings (str or bytes) and group
indices (int), as returned by re._parser.parse_template():
A list containing interleaved literal strings (str or bytes) and
group indices (int), as returned by re._parser.parse_template():
[literal1, group1, ..., literalN, groupN]
/

[clinic start generated code]*/

static PyObject *
_sre_template_impl(PyObject *module, PyObject *pattern, PyObject *template)
/*[clinic end generated code: output=d51290e596ebca86 input=af55380b27f02942]*/
/*[clinic end generated code: output=d51290e596ebca86 input=e015cbc1c71d0d20]*/
{
/* template is a list containing interleaved literal strings (str or bytes)
* and group indices (int), as returned by _parser.parse_template:
Expand Down
7 changes: 4 additions & 3 deletions Modules/_winapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3012,8 +3012,9 @@ _winapi_CopyFile2_impl(PyObject *module, LPCWSTR existing_file_name,
_winapi.RegisterEventSource -> HANDLE

unc_server_name: LPCWSTR(accept={str, NoneType})
The UNC name of the server on which the event source should be registered.
If None, registers the event source on the local computer.
The UNC name of the server on which the event source should be
registered. If None, registers the event source on the local
computer.
source_name: LPCWSTR
The name of the event source to register.
/
Expand All @@ -3024,7 +3025,7 @@ Retrieves a registered handle to the specified event log.
static HANDLE
_winapi_RegisterEventSource_impl(PyObject *module, LPCWSTR unc_server_name,
LPCWSTR source_name)
/*[clinic end generated code: output=e376c8950a89ae8f input=9d01059ac2156d0c]*/
/*[clinic end generated code: output=e376c8950a89ae8f input=ca9cb7b8959582dd]*/
{
HANDLE handle;

Expand Down
5 changes: 3 additions & 2 deletions Modules/_zstd/_zstdmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ _zstd.finalize_dict
dict_size: Py_ssize_t
The size of the dictionary.
compression_level: int
Optimize for a specific Zstandard compression level, 0 means default.
Optimize for a specific Zstandard compression level,
0 means default.
/

Finalize a Zstandard dictionary.
Expand All @@ -353,7 +354,7 @@ _zstd_finalize_dict_impl(PyObject *module, PyBytesObject *custom_dict_bytes,
PyBytesObject *samples_bytes,
PyObject *samples_sizes, Py_ssize_t dict_size,
int compression_level)
/*[clinic end generated code: output=f91821ba5ae85bda input=3c7e2480aa08fb56]*/
/*[clinic end generated code: output=f91821ba5ae85bda input=954d58d6f20c85c2]*/
{
Py_ssize_t chunks_number;
size_t *chunk_sizes = NULL;
Expand Down
5 changes: 3 additions & 2 deletions Modules/_zstd/clinic/_zstdmodule.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Modules/_zstd/clinic/compressor.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Modules/_zstd/compressor.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,8 @@ _zstd_ZstdCompressor_flush_impl(ZstdCompressor *self, int mode)
_zstd.ZstdCompressor.set_pledged_input_size

size: zstd_contentsize
The size of the uncompressed data to be provided to the compressor.
The size of the uncompressed data to be provided to the
compressor.
/

Set the uncompressed content size to be written into the frame header.
Expand All @@ -714,7 +715,7 @@ may be corrupted and the final chunk written may be lost.
static PyObject *
_zstd_ZstdCompressor_set_pledged_input_size_impl(ZstdCompressor *self,
unsigned long long size)
/*[clinic end generated code: output=3a09e55cc0e3b4f9 input=714cd7a9aa10e2a8]*/
/*[clinic end generated code: output=3a09e55cc0e3b4f9 input=2996f63a521943dc]*/
{
// Error occurred while converting argument, should be unreachable
assert(size != ZSTD_CONTENTSIZE_ERROR);
Expand Down
Loading
Loading