From e91a493ce8ec90e6591af0c327f60af8f5d4a44d Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 16:25:39 +0200 Subject: [PATCH 01/14] nntp_write and nntp_read --- src/nntp_io.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100755 src/nntp_io.py diff --git a/src/nntp_io.py b/src/nntp_io.py new file mode 100755 index 0000000..f73f592 --- /dev/null +++ b/src/nntp_io.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +import json +import nntplib # Removed from the Standard Library in Python 3.13. + +# import pathlib +import uuid + +FMT = """\ +From: GitHub Actions +Newsgroups: {} +Subject: inews test +Message-ID: + +{} +""" + + +def nntp_write(payload: dict, newsgroup: str = "local.test") -> int: + """ + Write a payload dict as json to a InterNet News newsgroup. + """ + msg = FMT.format(newsgroup, uuid.uuid4().hex, json.dumps(payload, indent=2)) + # print(f"{msg = }") + with nntplib.NNTP("localhost", readermode=True) as nntp_server: + _response = nntp_server.post(msg.encode("utf-8")) + print(f"{_response = }") + print(f"{nntp_server.stat()}") + return nntp_server.stat()[2] + # Verify that the article is there. + _resp, _count, _first, last, _name = nntp_server.group(newsgroup) + return last + + +def nntp_read(article_id: int, newsgroup: str = "local.test") -> dict: + """ + Read an article from a InterNet News newsgroup and return it as a dict. + """ + with nntplib.NNTP("localhost", readermode=True) as nntp_server: + _resp, _count, _first, _last, _name = nntp_server.group(newsgroup) + _stat = nntp_server.stat(article_id) + _article = nntp_server.article(article_id) + return json.loads(_article[1].lines[0].decode("utf-8")) + + +if __name__ == "__main__": + payload = {"key": "value"} + article_id = nntp_write(payload) + print(f"{article_id = }") + print(nntp_read(article_id)) From 81a6d67959ad2c3d330f5cb9e83b687c6c7ef32c Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 16:27:09 +0200 Subject: [PATCH 02/14] nntp_write and nntp_read --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5ec6536..abf810d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,6 +29,7 @@ jobs: with: python-version: 3.12 # nntplib was removed from the Standard Library in Python 3.13. - run: python src/nntplib_tests.py + - run: python src/nntp_io.py pre-commit: runs-on: ubuntu-latest From 6a803d1b00fcabdd15f0870118aa5f44d5e7dec0 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 16:41:18 +0200 Subject: [PATCH 03/14] nntp_write and nntp_read --- src/nntp_io.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index f73f592..7badbdb 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -16,31 +16,29 @@ """ -def nntp_write(payload: dict, newsgroup: str = "local.test") -> int: +def nntp_write(payload: dict, newsgroup: str = "local.test") -> str: """ Write a payload dict as json to a InterNet News newsgroup. + + Return: test.inews.a253222105b64597b9afd10e4f4c6740@inn2.packages.debian.org """ msg = FMT.format(newsgroup, uuid.uuid4().hex, json.dumps(payload, indent=2)) # print(f"{msg = }") with nntplib.NNTP("localhost", readermode=True) as nntp_server: - _response = nntp_server.post(msg.encode("utf-8")) - print(f"{_response = }") - print(f"{nntp_server.stat()}") - return nntp_server.stat()[2] - # Verify that the article is there. - _resp, _count, _first, last, _name = nntp_server.group(newsgroup) - return last + response = nntp_server.post(msg.encode("utf-8")).split() + assert response.startswith("240 "), f"{response = }" + return response.split()[-1][1:-1] # strip off the <> -def nntp_read(article_id: int, newsgroup: str = "local.test") -> dict: +def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: """ Read an article from a InterNet News newsgroup and return it as a dict. """ with nntplib.NNTP("localhost", readermode=True) as nntp_server: - _resp, _count, _first, _last, _name = nntp_server.group(newsgroup) - _stat = nntp_server.stat(article_id) - _article = nntp_server.article(article_id) - return json.loads(_article[1].lines[0].decode("utf-8")) + article = nntp_server.article(article_id) + print(f"{article = }") + print(f"{article.decode("utf-8") = }") + return {} # json.loads(article[1].lines[0].decode("utf-8")) if __name__ == "__main__": From 77b32d58c60ccbb397d336246756a6ef2428d169 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 16:46:08 +0200 Subject: [PATCH 04/14] nntp_write and nntp_read --- src/nntp_io.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index 7badbdb..017ebad 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -25,9 +25,9 @@ def nntp_write(payload: dict, newsgroup: str = "local.test") -> str: msg = FMT.format(newsgroup, uuid.uuid4().hex, json.dumps(payload, indent=2)) # print(f"{msg = }") with nntplib.NNTP("localhost", readermode=True) as nntp_server: - response = nntp_server.post(msg.encode("utf-8")).split() + response = nntp_server.post(msg.encode("utf-8")) assert response.startswith("240 "), f"{response = }" - return response.split()[-1][1:-1] # strip off the <> + return response.split("<")[-1][:-1] # strip off the <> def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: From 93638d814a4c0b886e4076b2de9e031105568d48 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 16:52:59 +0200 Subject: [PATCH 05/14] nntp_write and nntp_read --- src/nntp_io.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nntp_io.py b/src/nntp_io.py index 017ebad..bcc8442 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -35,6 +35,8 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: Read an article from a InterNet News newsgroup and return it as a dict. """ with nntplib.NNTP("localhost", readermode=True) as nntp_server: + stat = nntp_server.stat() # last() and next() both fail + print(f"{stat = } vs. {article_id = }") article = nntp_server.article(article_id) print(f"{article = }") print(f"{article.decode("utf-8") = }") From fb4e46a9dce3c1f98fe2b102936bc52012fbea1b Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:03:45 +0200 Subject: [PATCH 06/14] nntp_write and nntp_read --- src/nntp_io.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index bcc8442..09c83d4 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -35,7 +35,9 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: Read an article from a InterNet News newsgroup and return it as a dict. """ with nntplib.NNTP("localhost", readermode=True) as nntp_server: - stat = nntp_server.stat() # last() and next() both fail + resp, count, first, last, name = nntp_server.group(newsgroup) + assert last, f"{newsgroup = } has no articles." + stat = nntp_server.stat() print(f"{stat = } vs. {article_id = }") article = nntp_server.article(article_id) print(f"{article = }") From 135c50de088aafaad7184fbda0f5656eaf971809 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:19:42 +0200 Subject: [PATCH 07/14] nntp_write and nntp_read --- src/nntp_io.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index 09c83d4..f404125 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -25,9 +25,9 @@ def nntp_write(payload: dict, newsgroup: str = "local.test") -> str: msg = FMT.format(newsgroup, uuid.uuid4().hex, json.dumps(payload, indent=2)) # print(f"{msg = }") with nntplib.NNTP("localhost", readermode=True) as nntp_server: - response = nntp_server.post(msg.encode("utf-8")) - assert response.startswith("240 "), f"{response = }" - return response.split("<")[-1][:-1] # strip off the <> + response = nntp_server.post(msg.encode("utf-8")).split() + assert response[0] == "240", " ".join(response) + return response[-1] def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: @@ -37,8 +37,8 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: with nntplib.NNTP("localhost", readermode=True) as nntp_server: resp, count, first, last, name = nntp_server.group(newsgroup) assert last, f"{newsgroup = } has no articles." - stat = nntp_server.stat() - print(f"{stat = } vs. {article_id = }") + # stat = nntp_server.stat() + # print(f"{stat = } vs. {article_id = }") article = nntp_server.article(article_id) print(f"{article = }") print(f"{article.decode("utf-8") = }") From 2f01ad5687ec8cbd66dde0c5995306e5b656b69d Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:23:59 +0200 Subject: [PATCH 08/14] nntp_write and nntp_read --- src/nntp_io.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index f404125..ce6e954 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -40,8 +40,10 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: # stat = nntp_server.stat() # print(f"{stat = } vs. {article_id = }") article = nntp_server.article(article_id) - print(f"{article = }") - print(f"{article.decode("utf-8") = }") + lines = article[1].lines + print("\n".join(line.decode("utf-8") for line in lines)) + # print(f"{article = }") + # print(f"{article.decode("utf-8") = }") return {} # json.loads(article[1].lines[0].decode("utf-8")) From 09126572ed9722a8e9a6d0bf47f979b399ffcc62 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:34:43 +0200 Subject: [PATCH 09/14] nntp_write and nntp_read --- src/nntp_io.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index ce6e954..1d1d8f9 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -40,8 +40,8 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: # stat = nntp_server.stat() # print(f"{stat = } vs. {article_id = }") article = nntp_server.article(article_id) - lines = article[1].lines - print("\n".join(line.decode("utf-8") for line in lines)) + body_lines = article[1].lines[11] + print("\n".join(line.decode("utf-8") for line in body_lines)) # print(f"{article = }") # print(f"{article.decode("utf-8") = }") return {} # json.loads(article[1].lines[0].decode("utf-8")) From 7c41b3441e464548c209a8e16584ae1ee863e710 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:39:04 +0200 Subject: [PATCH 10/14] nntp_write and nntp_read --- src/nntp_io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index 1d1d8f9..e33a52c 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -40,7 +40,7 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: # stat = nntp_server.stat() # print(f"{stat = } vs. {article_id = }") article = nntp_server.article(article_id) - body_lines = article[1].lines[11] + body_lines = article[1].lines[11:] # Skip the header lines. print("\n".join(line.decode("utf-8") for line in body_lines)) # print(f"{article = }") # print(f"{article.decode("utf-8") = }") From 186529eb9f263e3dc5c19c7bc9778e49208dacf8 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:45:40 +0200 Subject: [PATCH 11/14] nntp_write and nntp_read --- src/nntp_io.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index e33a52c..5665b1f 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -37,14 +37,12 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: with nntplib.NNTP("localhost", readermode=True) as nntp_server: resp, count, first, last, name = nntp_server.group(newsgroup) assert last, f"{newsgroup = } has no articles." - # stat = nntp_server.stat() - # print(f"{stat = } vs. {article_id = }") article = nntp_server.article(article_id) - body_lines = article[1].lines[11:] # Skip the header lines. - print("\n".join(line.decode("utf-8") for line in body_lines)) - # print(f"{article = }") - # print(f"{article.decode("utf-8") = }") - return {} # json.loads(article[1].lines[0].decode("utf-8")) + body_lines = article[1].lines[10:] # Skip the header lines. + assert body_lines, f"{article_id = }: {article = } has no body." + body = "\n".join(line.decode("utf-8") for line in body_lines) + # print(f"{body = }") + return json.loads(body) if __name__ == "__main__": From 0005ccfd0fafc19af4f32f9f9533c2c5809b3e72 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:47:43 +0200 Subject: [PATCH 12/14] nntp_write and nntp_read --- src/nntp_io.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index 5665b1f..e5dc415 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -40,8 +40,8 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: article = nntp_server.article(article_id) body_lines = article[1].lines[10:] # Skip the header lines. assert body_lines, f"{article_id = }: {article = } has no body." - body = "\n".join(line.decode("utf-8") for line in body_lines) - # print(f"{body = }") + body = "\n".join(line.decode("utf-8") for line in body_lines).strip() + print(f"{body = }") return json.loads(body) From 37c140a2cfa942a1f41ebc4a181f5c2a6c316043 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:49:18 +0200 Subject: [PATCH 13/14] nntp_write and nntp_read --- src/nntp_io.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index e5dc415..02b6ce9 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -38,9 +38,9 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: resp, count, first, last, name = nntp_server.group(newsgroup) assert last, f"{newsgroup = } has no articles." article = nntp_server.article(article_id) - body_lines = article[1].lines[10:] # Skip the header lines. + body_lines = article[1].lines[11:] # Skip the header lines. assert body_lines, f"{article_id = }: {article = } has no body." - body = "\n".join(line.decode("utf-8") for line in body_lines).strip() + body = "\n".join(line.decode("utf-8") for line in body_lines) print(f"{body = }") return json.loads(body) From cdf57fc03a0f5c5876a96572c3f639b3a745af22 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 18 Sep 2024 17:51:45 +0200 Subject: [PATCH 14/14] nntp_write and nntp_read --- src/nntp_io.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nntp_io.py b/src/nntp_io.py index 02b6ce9..c68d3a8 100755 --- a/src/nntp_io.py +++ b/src/nntp_io.py @@ -41,7 +41,7 @@ def nntp_read(article_id: str, newsgroup: str = "local.test") -> dict: body_lines = article[1].lines[11:] # Skip the header lines. assert body_lines, f"{article_id = }: {article = } has no body." body = "\n".join(line.decode("utf-8") for line in body_lines) - print(f"{body = }") + # print(f"{body = }") return json.loads(body)