From ac1e4cafb40903b6a8c4c9498b6331e49a82d419 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Tue, 16 Jan 2024 09:46:17 -0600 Subject: [PATCH 1/7] migrate docstring from _csv to csv --- Lib/csv.py | 65 ++++++++++++++++++++++++++++++++++++++++++-- Lib/test/test_csv.py | 2 +- Modules/_csv.c | 63 +----------------------------------------- 3 files changed, 64 insertions(+), 66 deletions(-) diff --git a/Lib/csv.py b/Lib/csv.py index 77f30c8d2b1f61..bbad70b6d8618a 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -1,6 +1,66 @@ """ csv.py - read/write/investigate CSV files + +This module provides classes that assist in the reading and writing +of Comma Separated Value (CSV) files, and implements the interface +described by PEP 305. Although many CSV files are simple to parse, +the format is not formally defined by a stable specification and +is subtle enough that parsing lines of a CSV file with something +like line.split(",") is bound to fail. The module supports three +basic APIs: reading, writing, and registration of dialects. + + +DIALECT REGISTRATION: + +Readers and writers support a dialect argument, which is a convenient +handle on a group of settings. When the dialect argument is a string, +it identifies one of the dialects previously registered with the module. +If it is a class or instance, the attributes of the argument are used as +the settings for the reader or writer: + + class excel: + delimiter = ',' + quotechar = '"' + escapechar = None + doublequote = True + skipinitialspace = False + lineterminator = '\r\n' + quoting = QUOTE_MINIMAL + +SETTINGS: + + * quotechar - specifies a one-character string to use as the + quoting character. It defaults to '"'. + * delimiter - specifies a one-character string to use as the + field separator. It defaults to ','. + * skipinitialspace - specifies how to interpret spaces which + immediately follow a delimiter. It defaults to False, which + means that spaces immediately following a delimiter is part + of the following field. + * lineterminator - specifies the character sequence which should + terminate rows. + * quoting - controls when quotes should be generated by the writer. + It can take on any of the following module constants: + + csv.QUOTE_MINIMAL means only when required, for example, when a + field contains either the quotechar or the delimiter + csv.QUOTE_ALL means that quotes are always placed around fields. + csv.QUOTE_NONNUMERIC means that quotes are always placed around + fields which do not parse as integers or floating point + numbers. + csv.QUOTE_STRINGS means that quotes are always placed around + fields which are strings. Note that the Python value None + is not a string. + csv.QUOTE_NOTNULL means that quotes are only placed around fields + that are not the Python value None. + csv.QUOTE_NONE means that quotes are never placed around fields. + * escapechar - specifies a one-character string used to escape + the delimiter when quoting is set to QUOTE_NONE. + * doublequote - controls the handling of quotes inside fields. When + True, two consecutive quotes are interpreted as one during read, + and when writing, each quote character embedded in the data is + written as two quotes """ import re @@ -9,15 +69,14 @@ unregister_dialect, get_dialect, list_dialects, \ field_size_limit, \ QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \ - QUOTE_STRINGS, QUOTE_NOTNULL, \ - __doc__ + QUOTE_STRINGS, QUOTE_NOTNULL from _csv import Dialect as _Dialect from io import StringIO __all__ = ["QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE", "QUOTE_STRINGS", "QUOTE_NOTNULL", - "Error", "Dialect", "__doc__", "excel", "excel_tab", + "Error", "Dialect", "excel", "excel_tab", "field_size_limit", "reader", "writer", "register_dialect", "get_dialect", "list_dialects", "Sniffer", "unregister_dialect", "__version__", "DictReader", "DictWriter", diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index 282cff4344b77f..c76f3bf37035fc 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -1416,7 +1416,7 @@ def test_ordered_dict_reader(self): class MiscTestCase(unittest.TestCase): def test__all__(self): - extra = {'__doc__', '__version__'} + extra = {'__version__'} support.check__all__(self, csv, ('csv', '_csv'), extra=extra) def test_subclassable(self): diff --git a/Modules/_csv.c b/Modules/_csv.c index d45a15aa8c255a..61fab52e778d10 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -1607,68 +1607,7 @@ PyType_Spec error_spec = { * MODULE */ -PyDoc_STRVAR(csv_module_doc, -"CSV parsing and writing.\n" -"\n" -"This module provides classes that assist in the reading and writing\n" -"of Comma Separated Value (CSV) files, and implements the interface\n" -"described by PEP 305. Although many CSV files are simple to parse,\n" -"the format is not formally defined by a stable specification and\n" -"is subtle enough that parsing lines of a CSV file with something\n" -"like line.split(\",\") is bound to fail. The module supports three\n" -"basic APIs: reading, writing, and registration of dialects.\n" -"\n" -"\n" -"DIALECT REGISTRATION:\n" -"\n" -"Readers and writers support a dialect argument, which is a convenient\n" -"handle on a group of settings. When the dialect argument is a string,\n" -"it identifies one of the dialects previously registered with the module.\n" -"If it is a class or instance, the attributes of the argument are used as\n" -"the settings for the reader or writer:\n" -"\n" -" class excel:\n" -" delimiter = ','\n" -" quotechar = '\"'\n" -" escapechar = None\n" -" doublequote = True\n" -" skipinitialspace = False\n" -" lineterminator = '\\r\\n'\n" -" quoting = QUOTE_MINIMAL\n" -"\n" -"SETTINGS:\n" -"\n" -" * quotechar - specifies a one-character string to use as the\n" -" quoting character. It defaults to '\"'.\n" -" * delimiter - specifies a one-character string to use as the\n" -" field separator. It defaults to ','.\n" -" * skipinitialspace - specifies how to interpret spaces which\n" -" immediately follow a delimiter. It defaults to False, which\n" -" means that spaces immediately following a delimiter is part\n" -" of the following field.\n" -" * lineterminator - specifies the character sequence which should\n" -" terminate rows.\n" -" * quoting - controls when quotes should be generated by the writer.\n" -" It can take on any of the following module constants:\n" -"\n" -" csv.QUOTE_MINIMAL means only when required, for example, when a\n" -" field contains either the quotechar or the delimiter\n" -" csv.QUOTE_ALL means that quotes are always placed around fields.\n" -" csv.QUOTE_NONNUMERIC means that quotes are always placed around\n" -" fields which do not parse as integers or floating point\n" -" numbers.\n" -" csv.QUOTE_STRINGS means that quotes are always placed around\n" -" fields which are strings. Note that the Python value None\n" -" is not a string.\n" -" csv.QUOTE_NOTNULL means that quotes are only placed around fields\n" -" that are not the Python value None.\n" -" csv.QUOTE_NONE means that quotes are never placed around fields.\n" -" * escapechar - specifies a one-character string used to escape\n" -" the delimiter when quoting is set to QUOTE_NONE.\n" -" * doublequote - controls the handling of quotes inside fields. When\n" -" True, two consecutive quotes are interpreted as one during read,\n" -" and when writing, each quote character embedded in the data is\n" -" written as two quotes\n"); +PyDoc_STRVAR(csv_module_doc, "CSV parsing and writing.\n"); PyDoc_STRVAR(csv_reader_doc, " csv_reader = reader(iterable [, dialect='excel']\n" From b2a5e6631cde63187bc2c70e2d8e78b9b1b04f69 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Tue, 16 Jan 2024 15:19:18 -0600 Subject: [PATCH 2/7] two suggestions by AA-Turner --- Lib/csv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/csv.py b/Lib/csv.py index bbad70b6d8618a..fec63e128dc2e5 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -1,5 +1,5 @@ -""" +r""" csv.py - read/write/investigate CSV files This module provides classes that assist in the reading and writing @@ -38,7 +38,7 @@ class excel: immediately follow a delimiter. It defaults to False, which means that spaces immediately following a delimiter is part of the following field. - * lineterminator - specifies the character sequence which should + * lineterminator - specifies the character sequence which should terminate rows. * quoting - controls when quotes should be generated by the writer. It can take on any of the following module constants: From 64301bd0d6e22f57ba0cc4074524b0ddc0976432 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Wed, 17 Jan 2024 11:50:21 -0600 Subject: [PATCH 3/7] move __version__ from _csv to csv, remove from csv.__all__ --- Lib/csv.py | 7 +++++-- Lib/test/test_csv.py | 4 ---- Modules/_csv.c | 8 -------- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/Lib/csv.py b/Lib/csv.py index fec63e128dc2e5..e4dc98154ee45f 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -65,7 +65,7 @@ class excel: import re import types -from _csv import Error, __version__, writer, reader, register_dialect, \ +from _csv import Error, writer, reader, register_dialect, \ unregister_dialect, get_dialect, list_dialects, \ field_size_limit, \ QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \ @@ -79,9 +79,12 @@ class excel: "Error", "Dialect", "excel", "excel_tab", "field_size_limit", "reader", "writer", "register_dialect", "get_dialect", "list_dialects", "Sniffer", - "unregister_dialect", "__version__", "DictReader", "DictWriter", + "unregister_dialect", "DictReader", "DictWriter", "unix_dialect"] +__version__ = "1.0" + + class Dialect: """Describe a CSV dialect. diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index c76f3bf37035fc..da5ac5dc026f2a 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -1415,10 +1415,6 @@ def test_ordered_dict_reader(self): class MiscTestCase(unittest.TestCase): - def test__all__(self): - extra = {'__version__'} - support.check__all__(self, csv, ('csv', '_csv'), extra=extra) - def test_subclassable(self): # issue 44089 class Foo(csv.Error): ... diff --git a/Modules/_csv.c b/Modules/_csv.c index 61fab52e778d10..8d941563025580 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -8,8 +8,6 @@ module instead. */ -#define MODULE_VERSION "1.0" - // clinic/_csv.c.h uses internal pycore_modsupport.h API #ifndef Py_BUILD_CORE_BUILTIN # define Py_BUILD_CORE_MODULE 1 @@ -1680,12 +1678,6 @@ csv_exec(PyObject *module) { return -1; } - /* Add version to the module. */ - if (PyModule_AddStringConstant(module, "__version__", - MODULE_VERSION) == -1) { - return -1; - } - /* Set the field limit */ module_state->field_limit = 128 * 1024; From 998a9442ca83a430d5cd778e56a2009d7743fe6f Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Wed, 17 Jan 2024 11:50:36 -0600 Subject: [PATCH 4/7] + NEWS item --- .../2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst diff --git a/Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst b/Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst new file mode 100644 index 00000000000000..00a422ff7bc7f1 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst @@ -0,0 +1,5 @@ +Moved `csv` module docstring from `Modules/_csv.c` to `Lib/csv.py` and +removed `__doc__` from `csv.__all__`. + +Moved `csv.__version__` from `Modules/_csv.c` to `Lib/csv.py` and removed +`__version__` from `csv.__all__`. From bef48111db18dee42710d6eb78dd039631f19804 Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Wed, 17 Jan 2024 13:41:10 -0600 Subject: [PATCH 5/7] markup --- .../2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst b/Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst index 00a422ff7bc7f1..1d93a422840077 100644 --- a/Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst +++ b/Misc/NEWS.d/next/Documentation/2024-01-17-11-40-03.gh-issue-114123.LuueXf.rst @@ -1,5 +1,7 @@ -Moved `csv` module docstring from `Modules/_csv.c` to `Lib/csv.py` and -removed `__doc__` from `csv.__all__`. +Move the :mod:`csv` module docstring to the :mod:`!csv` module +instead of reexporting it from the internal :mod:`!_csv` module, +and remove ``__doc__`` from ``csv.__all__``. -Moved `csv.__version__` from `Modules/_csv.c` to `Lib/csv.py` and removed -`__version__` from `csv.__all__`. +Move :attr:`!csv.__version__` to the :mod:`!csv` module +instead of reexporting it from the internal :mod:`!_csv` module, +and remove ``__version__`` from ``csv.__all__``. From 3e540c6e4ae973e5f5e182ccd2ba4202b43e3c6f Mon Sep 17 00:00:00 2001 From: Skip Montanaro Date: Wed, 17 Jan 2024 18:29:37 -0600 Subject: [PATCH 6/7] restore test__all__ --- Lib/test/test_csv.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index da5ac5dc026f2a..36da86e6a2c622 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -1415,6 +1415,9 @@ def test_ordered_dict_reader(self): class MiscTestCase(unittest.TestCase): + def test__all__(self): + support.check__all__(self, csv, ('csv', '_csv')) + def test_subclassable(self): # issue 44089 class Foo(csv.Error): ... From 4d4d2b44498b39bbd41364f68ec5bd25428c5955 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Date: Thu, 18 Jan 2024 19:21:57 +0000 Subject: [PATCH 7/7] Update the docstring title MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Éric --- Lib/csv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/csv.py b/Lib/csv.py index e4dc98154ee45f..a079279b8b8cbc 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -1,6 +1,6 @@ r""" -csv.py - read/write/investigate CSV files +CSV parsing and writing. This module provides classes that assist in the reading and writing of Comma Separated Value (CSV) files, and implements the interface