From 4103bc09a4326a4ffd8d2dbc60a01d256d18b1f7 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Wed, 3 Nov 2010 18:18:43 +0000 Subject: Issue #10281: nntplib now returns None for absent fields in the OVER/XOVER response, instead of raising an exception. --- Doc/library/nntplib.rst | 2 ++ Lib/nntplib.py | 7 ++++--- Lib/test/test_nntplib.py | 27 ++++++++++++++++++++++++++- Misc/NEWS | 3 +++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst index 69adffb..0f0b7d2 100644 --- a/Doc/library/nntplib.rst +++ b/Doc/library/nntplib.rst @@ -252,6 +252,8 @@ response indicates an error, the method raises one of the above exceptions. (including headers and body) * the ``:lines`` metadata: the number of lines in the article body + The value of each item is either a string, or :const:`None` if not present. + It is advisable to use the :func:`decode_header` function on header values when they may contain non-ASCII characters:: diff --git a/Lib/nntplib.py b/Lib/nntplib.py index b067d6b..fde339a 100644 --- a/Lib/nntplib.py +++ b/Lib/nntplib.py @@ -205,11 +205,12 @@ def _parse_overview(lines, fmt, data_process_func=None): is_metadata = field_name.startswith(':') if i >= n_defaults and not is_metadata: # Non-default header names are included in full in the response - h = field_name + ":" - if token[:len(h)].lower() != h: + # (unless the field is totally empty) + h = field_name + ": " + if token and token[:len(h)].lower() != h: raise NNTPDataError("OVER/XOVER response doesn't include " "names of additional headers") - token = token[len(h):].lstrip(" ") + token = token[len(h):] if token else None fields[fmt[i]] = token overview.append((article_number, fields)) return overview diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py index e62b240..8da901f1 100644 --- a/Lib/test/test_nntplib.py +++ b/Lib/test/test_nntplib.py @@ -457,7 +457,7 @@ class NNTPv1Handler: "\tThu, 22 Jul 2010 09:14:14 -0400" "\t" "\t\t6683\t16" - "\tXref: news.gmane.org gmane.comp.python.authors:58" + "\t" "\n" # An UTF-8 overview line from fr.comp.lang.python "59\tRe: Message d'erreur incompréhensible (par moi)" @@ -824,6 +824,8 @@ class NNTPv1v2TestsMixin: ":lines": "16", "xref": "news.gmane.org gmane.comp.python.authors:57" }) + art_num, over = overviews[1] + self.assertEqual(over["xref"], None) art_num, over = overviews[2] self.assertEqual(over["subject"], "Re: Message d'erreur incompréhensible (par moi)") @@ -1028,6 +1030,29 @@ class MiscTests(unittest.TestCase): ':lines': '17', 'xref': 'news.example.com misc.test:3000363', }) + # Second example; here the "Xref" field is totally absent (including + # the header name) and comes out as None + lines = [ + '3000234\tI am just a test article\t"Demo User" ' + '\t6 Oct 1998 04:38:40 -0500\t' + '<45223423@example.com>\t<45454@example.net>\t1234\t' + '17\t\t', + ] + overview = nntplib._parse_overview(lines, fmt) + (art_num, fields), = overview + self.assertEqual(fields['xref'], None) + # Third example; the "Xref" is an empty string, while "references" + # is a single space. + lines = [ + '3000234\tI am just a test article\t"Demo User" ' + '\t6 Oct 1998 04:38:40 -0500\t' + '<45223423@example.com>\t \t1234\t' + '17\tXref: \t', + ] + overview = nntplib._parse_overview(lines, fmt) + (art_num, fields), = overview + self.assertEqual(fields['references'], ' ') + self.assertEqual(fields['xref'], '') def test_parse_datetime(self): def gives(a, b, *c): diff --git a/Misc/NEWS b/Misc/NEWS index adc3157..ba5ba38 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -59,6 +59,9 @@ Core and Builtins Library ------- +- Issue #10281: nntplib now returns None for absent fields in the OVER/XOVER + response, instead of raising an exception. + - wsgiref now implements and validates PEP 3333, rather than an experimental extension of PEP 333. (Note: earlier versions of Python 3.x may have incorrectly validated some non-compliant applications as WSGI compliant; -- cgit v0.12