diff --git a/.github/workflows/test-devel.yml b/.github/workflows/test-devel.yml index fb936ea..f73176b 100644 --- a/.github/workflows/test-devel.yml +++ b/.github/workflows/test-devel.yml @@ -401,7 +401,7 @@ jobs: - name: Install dashboard dependencies run: |- python -m pip install --upgrade pip - pip install defusedxml + pip install defusedxml docutils -r requirements.txt - name: Generate dashboard run: |- shopt -s globstar diff --git a/.github/workflows/test-devel_release.yml b/.github/workflows/test-devel_release.yml index 3e0fc2e..8fa975f 100644 --- a/.github/workflows/test-devel_release.yml +++ b/.github/workflows/test-devel_release.yml @@ -86,7 +86,7 @@ jobs: - name: Install dashboard dependencies run: |- python -m pip install --upgrade pip - pip install defusedxml + pip install defusedxml docutils -r requirements.txt - name: Generate dashboard run: |- shopt -s globstar diff --git a/.github/workflows/test-stable.yml b/.github/workflows/test-stable.yml index 4067f3b..c4a0468 100644 --- a/.github/workflows/test-stable.yml +++ b/.github/workflows/test-stable.yml @@ -444,7 +444,7 @@ jobs: - name: Install dashboard dependencies run: |- python -m pip install --upgrade pip - pip install defusedxml + pip install defusedxml docutils -r requirements.txt - name: Generate dashboard run: |- shopt -s globstar diff --git a/irctest/client_tests/cap.py b/irctest/client_tests/cap.py index 5361945..03aa1a1 100644 --- a/irctest/client_tests/cap.py +++ b/irctest/client_tests/cap.py @@ -1,3 +1,5 @@ +"""Format of ``CAP LS`` sent by IRCv3 clients.""" + from irctest import cases from irctest.irc_utils.message_parser import Message diff --git a/irctest/client_tests/sasl.py b/irctest/client_tests/sasl.py index 7cc3781..bf766f9 100644 --- a/irctest/client_tests/sasl.py +++ b/irctest/client_tests/sasl.py @@ -1,3 +1,8 @@ +"""SASL authentication from clients, for all known mechanisms. + +For now, only `SASLv3.1 `_ +is tested, not `SASLv3.2 `_.""" + import base64 import pytest diff --git a/irctest/client_tests/tls.py b/irctest/client_tests/tls.py index e24e421..285bd36 100644 --- a/irctest/client_tests/tls.py +++ b/irctest/client_tests/tls.py @@ -1,3 +1,5 @@ +"""Clients should validate certificates; either with a CA or fingerprints.""" + import socket import ssl diff --git a/irctest/dashboard/format.py b/irctest/dashboard/format.py index cd7c6b0..615a243 100644 --- a/irctest/dashboard/format.py +++ b/irctest/dashboard/format.py @@ -2,6 +2,7 @@ import base64 import dataclasses import gzip import hashlib +import importlib from pathlib import Path import re import sys @@ -16,10 +17,10 @@ from typing import ( Tuple, TypeVar, ) -import xml.dom.minidom import xml.etree.ElementTree as ET from defusedxml.ElementTree import parse as parse_xml +import docutils.core NETLIFY_CHAR_BLACKLIST = frozenset('":<>|*?\r\n#') """Characters not allowed in output filenames""" @@ -117,9 +118,24 @@ def iter_job_results(job_file_name: Path, job: ET.ElementTree) -> Iterator[CaseR ) +def rst_to_element(s: str) -> ET.Element: + html = docutils.core.publish_parts(s, writer_name="xhtml")["html_body"] + htmltree = ET.fromstring(html) + return htmltree + + +def append_docstring(element: ET.Element, obj: object) -> None: + if obj.__doc__ is None: + return + + element.append(rst_to_element(obj.__doc__)) + + def build_module_html( jobs: List[str], results: List[CaseResult], module_name: str ) -> ET.Element: + module = importlib.import_module(module_name) + root = ET.Element("html") head = ET.SubElement(root, "head") ET.SubElement(head, "title").text = module_name @@ -129,6 +145,8 @@ def build_module_html( ET.SubElement(body, "h1").text = module_name + append_docstring(body, module) + results_by_class = group_by(results, lambda r: r.class_name) table = ET.SubElement(body, "table") @@ -153,6 +171,7 @@ def build_module_html( id=row_anchor, ) section_header.text = class_name + append_docstring(th, getattr(module, class_name)) # Header row: one column for each implementation table.append(job_row) @@ -213,10 +232,6 @@ def build_module_html( else: cell.text = text or "?" - # Hacky: ET expects the namespace to be present in every tag we create instead; - # but it would be excessively verbose. - root.set("xmlns", "http://www.w3.org/1999/xhtml") - return root @@ -261,13 +276,15 @@ def write_html_index(output_dir: Path, pages: List[Tuple[str, str]]) -> None: ET.SubElement(body, "h1").text = "irctest dashboard" - ul = ET.SubElement(body, "ul") + dl = ET.SubElement(body, "dl") + dl.set("class", "module-index") for (module_name, file_name) in sorted(pages): - link = ET.SubElement(ET.SubElement(ul, "li"), "a", href=f"./{file_name}") - link.text = module_name + module = importlib.import_module(module_name) - root.set("xmlns", "http://www.w3.org/1999/xhtml") + link = ET.SubElement(ET.SubElement(dl, "dt"), "a", href=f"./{file_name}") + link.text = module_name + append_docstring(ET.SubElement(dl, "dd"), module) write_xml_file(output_dir / "index.xhtml", root) @@ -281,14 +298,15 @@ def write_assets(output_dir: Path) -> None: def write_xml_file(filename: Path, root: ET.Element) -> None: + # Hacky: ET expects the namespace to be present in every tag we create instead; + # but it would be excessively verbose. + root.set("xmlns", "http://www.w3.org/1999/xhtml") + # Serialize s = ET.tostring(root) - # Prettify - s = xml.dom.minidom.parseString(s).toprettyxml(indent=" ") - - with filename.open("wt") as fd: - fd.write(s) # type: ignore + with filename.open("wb") as fd: + fd.write(s) def parse_xml_file(filename: Path) -> ET.ElementTree: diff --git a/irctest/dashboard/style.css b/irctest/dashboard/style.css index 1609da2..ed0b737 100644 --- a/irctest/dashboard/style.css +++ b/irctest/dashboard/style.css @@ -8,6 +8,10 @@ } } +dl.module-index { + column-width: 40em; /* Magic constant for 2 columns on average laptop/desktop */ +} + /* Only 1px solid border between cells */ table.test-matrix { border-spacing: 0; diff --git a/irctest/self_tests/cases.py b/irctest/self_tests/cases.py index eda4b5d..63cf659 100644 --- a/irctest/self_tests/cases.py +++ b/irctest/self_tests/cases.py @@ -1,3 +1,5 @@ +"""Internal checks of assertion implementations.""" + from typing import Dict, List, Tuple import pytest diff --git a/irctest/server_tests/register_verify.py b/irctest/server_tests/account_registration.py similarity index 98% rename from irctest/server_tests/register_verify.py rename to irctest/server_tests/account_registration.py index 805d373..ba8a25d 100644 --- a/irctest/server_tests/register_verify.py +++ b/irctest/server_tests/account_registration.py @@ -1,3 +1,8 @@ +""" +`Draft IRCv3 account-registration +`_ +""" + from irctest import cases from irctest.patma import ANYSTR diff --git a/irctest/server_tests/account_tag.py b/irctest/server_tests/account_tag.py index ea909db..f5d2e87 100644 --- a/irctest/server_tests/account_tag.py +++ b/irctest/server_tests/account_tag.py @@ -1,5 +1,5 @@ """ - +`IRCv3 account-tag `_ """ from irctest import cases diff --git a/irctest/server_tests/away.py b/irctest/server_tests/away.py index 7b24a08..a6ea7b4 100644 --- a/irctest/server_tests/away.py +++ b/irctest/server_tests/away.py @@ -1,3 +1,8 @@ +""" +AWAY command (`RFC 2812 `__, +`Modern `__) +""" + from irctest import cases from irctest.numerics import RPL_AWAY, RPL_NOWAWAY, RPL_UNAWAY, RPL_USERHOST from irctest.patma import StrRe @@ -32,7 +37,7 @@ class AwayTestCase(cases.BaseServerTestCase): """ "The server acknowledges the change in away status by returning the `RPL_NOWAWAY` and `RPL_UNAWAY` numerics." - -- https://github.com/ircdocs/modern-irc/pull/100 + -- https://modern.ircdocs.horse/#away-message """ self.connectClient("bar") self.sendLine(1, "AWAY :I'm not here right now") @@ -48,7 +53,7 @@ class AwayTestCase(cases.BaseServerTestCase): """ "Servers SHOULD notify clients when a user they're interacting with is away when relevant" - -- https://github.com/ircdocs/modern-irc/pull/100 + -- https://modern.ircdocs.horse/#away-message " :" -- https://modern.ircdocs.horse/#rplaway-301 @@ -75,7 +80,7 @@ class AwayTestCase(cases.BaseServerTestCase): """ "Servers SHOULD notify clients when a user they're interacting with is away when relevant" - -- https://github.com/ircdocs/modern-irc/pull/100 + -- https://modern.ircdocs.horse/#away-message " :" -- https://modern.ircdocs.horse/#rplaway-301 @@ -113,7 +118,7 @@ class AwayTestCase(cases.BaseServerTestCase): """ "Servers SHOULD notify clients when a user they're interacting with is away when relevant" - -- https://github.com/ircdocs/modern-irc/pull/100 + -- https://modern.ircdocs.horse/#away-message " :" -- https://modern.ircdocs.horse/#rplaway-301 diff --git a/irctest/server_tests/away_notify.py b/irctest/server_tests/away_notify.py index 6d3b8d6..283c007 100644 --- a/irctest/server_tests/away_notify.py +++ b/irctest/server_tests/away_notify.py @@ -1,5 +1,5 @@ """ - +`IRCv3 away-notify `_ """ from irctest import cases diff --git a/irctest/server_tests/bot_mode.py b/irctest/server_tests/bot_mode.py index 161aaf4..224c77e 100644 --- a/irctest/server_tests/bot_mode.py +++ b/irctest/server_tests/bot_mode.py @@ -1,6 +1,5 @@ """ -Draft bot mode specification, as defined in - +`IRCv3 draft bot mode `_ """ from irctest import cases, runner diff --git a/irctest/server_tests/bouncer.py b/irctest/server_tests/bouncer.py index 4daed8d..c1cdc9f 100644 --- a/irctest/server_tests/bouncer.py +++ b/irctest/server_tests/bouncer.py @@ -1,3 +1,9 @@ +""" +`Ergo `_-specific tests of +`multiclient features +`_ +""" + from irctest import cases from irctest.irc_utils.sasl import sasl_plain_blob from irctest.numerics import ERR_NICKNAMEINUSE, RPL_WELCOME diff --git a/irctest/server_tests/buffering.py b/irctest/server_tests/buffering.py index 321e04b..4adf01d 100644 --- a/irctest/server_tests/buffering.py +++ b/irctest/server_tests/buffering.py @@ -1,5 +1,7 @@ -"""Sends packets with various length to check the server reassembles them -correctly. Also checks truncation""" +""" +Sends packets with various length to check the server reassembles them +correctly. Also checks truncation. +""" import socket import time diff --git a/irctest/server_tests/cap.py b/irctest/server_tests/cap.py index b4fd31d..fac6e68 100644 --- a/irctest/server_tests/cap.py +++ b/irctest/server_tests/cap.py @@ -1,3 +1,8 @@ +""" +`IRCv3 Capability negotiation +`_ +""" + from irctest import cases from irctest.patma import ANYSTR from irctest.runner import CapabilityNotSupported, ImplementationChoice @@ -172,3 +177,60 @@ class CapTestCase(cases.BaseServerTestCase, cases.OptionalityHelper): enabled_caps.discard("cap-notify") # implicitly added by some impls self.assertEqual(enabled_caps, {cap1}) self.assertNotIn("time", cap_list.tags) + + @cases.mark_specifications("IRCv3") + def testIrc301CapLs(self): + """ + Current version: + + "The LS subcommand is used to list the capabilities supported by the server. + The client should send an LS subcommand with no other arguments to solicit + a list of all capabilities." + + "If a client has not indicated support for CAP LS 302 features, + the server MUST NOT send these new features to the client." + -- + + Before the v3.1 / v3.2 merge: + + IRCv3.1: “The LS subcommand is used to list the capabilities + supported by the server. The client should send an LS subcommand with + no other arguments to solicit a list of all capabilities.” + -- + + IRCv3.2: “Servers MUST NOT send messages described by this document if + the client only supports version 3.1.” + -- + """ # noqa + self.addClient() + self.sendLine(1, "CAP LS") + m = self.getRegistrationMessage(1) + self.assertNotEqual( + m.params[2], + "*", + m, + fail_msg="Server replied with multi-line CAP LS to a " + "“CAP LS” (ie. IRCv3.1) request: {msg}", + ) + self.assertFalse( + any("=" in cap for cap in m.params[2].split()), + "Server replied with a name-value capability in " + "CAP LS reply as a response to “CAP LS” (ie. IRCv3.1) " + "request: {}".format(m), + ) + + @cases.mark_specifications("IRCv3") + def testEmptyCapList(self): + """“If no capabilities are active, an empty parameter must be sent.” + -- + """ # noqa + self.addClient() + self.sendLine(1, "CAP LIST") + m = self.getRegistrationMessage(1) + self.assertMessageMatch( + m, + command="CAP", + params=["*", "LIST", ""], + fail_msg="Sending “CAP LIST” as first message got a reply " + "that is not “CAP * LIST :”: {msg}", + ) diff --git a/irctest/server_tests/channel.py b/irctest/server_tests/channel.py index 5fead80..61472f7 100644 --- a/irctest/server_tests/channel.py +++ b/irctest/server_tests/channel.py @@ -1,3 +1,7 @@ +""" +Channel casemapping +""" + import pytest from irctest import cases, client_mock, runner diff --git a/irctest/server_tests/channel_forward.py b/irctest/server_tests/channel_forward.py index 9ce7312..11b284d 100644 --- a/irctest/server_tests/channel_forward.py +++ b/irctest/server_tests/channel_forward.py @@ -1,3 +1,9 @@ +""" +`Ergo `_-specific tests of channel forwarding + +TODO: Should be extended to other servers, once a specification is written. +""" + from irctest import cases from irctest.numerics import ERR_CHANOPRIVSNEEDED, ERR_INVALIDMODEPARAM, ERR_LINKCHANNEL diff --git a/irctest/server_tests/channel_rename.py b/irctest/server_tests/channel_rename.py index d22d950..5bcdbfe 100644 --- a/irctest/server_tests/channel_rename.py +++ b/irctest/server_tests/channel_rename.py @@ -1,24 +1,22 @@ +""" +`Draft IRCv3 channel-rename `_ +""" + from irctest import cases from irctest.numerics import ERR_CHANOPRIVSNEEDED -MODERN_CAPS = [ - "server-time", - "message-tags", - "batch", - "labeled-response", - "echo-message", - "account-tag", -] RENAME_CAP = "draft/channel-rename" +@cases.mark_specifications("IRCv3") class ChannelRenameTestCase(cases.BaseServerTestCase): """Basic tests for channel-rename.""" - @cases.mark_specifications("Ergo") def testChannelRename(self): - self.connectClient("bar", name="bar", capabilities=MODERN_CAPS + [RENAME_CAP]) - self.connectClient("baz", name="baz", capabilities=MODERN_CAPS) + self.connectClient( + "bar", name="bar", capabilities=[RENAME_CAP], skip_if_cap_nak=True + ) + self.connectClient("baz", name="baz") self.joinChannel("bar", "#bar") self.joinChannel("baz", "#bar") self.getMessages("bar") diff --git a/irctest/server_tests/chathistory.py b/irctest/server_tests/chathistory.py index a387e6f..a264ae5 100644 --- a/irctest/server_tests/chathistory.py +++ b/irctest/server_tests/chathistory.py @@ -1,3 +1,7 @@ +""" +`IRCv3 draft chathistory `_ +""" + import secrets import time diff --git a/irctest/server_tests/chmodes/auditorium.py b/irctest/server_tests/chmodes/auditorium.py index 8cd74a3..bd328cb 100644 --- a/irctest/server_tests/chmodes/auditorium.py +++ b/irctest/server_tests/chmodes/auditorium.py @@ -1,3 +1,9 @@ +""" +`Ergo `_-specific tests of auditorium mode + +TODO: Should be extended to other servers, once a specification is written. +""" + import math import time diff --git a/irctest/server_tests/chmodes/ban.py b/irctest/server_tests/chmodes/ban.py index 22cdebc..471e40a 100644 --- a/irctest/server_tests/chmodes/ban.py +++ b/irctest/server_tests/chmodes/ban.py @@ -1,3 +1,10 @@ +""" +Channel ban (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + from irctest import cases from irctest.numerics import ERR_BANNEDFROMCHAN, RPL_BANLIST, RPL_ENDOFBANLIST from irctest.patma import ANYSTR, StrRe @@ -26,7 +33,7 @@ class BanModeTestCase(cases.BaseServerTestCase): @cases.mark_specifications("Modern") def testBanList(self): - """https://github.com/ircdocs/modern-irc/pull/125""" + """`RPL_BANLIST `""" self.connectClient("chanop") self.joinChannel(1, "#chan") self.getMessages(1) diff --git a/irctest/server_tests/chmodes/ergo.py b/irctest/server_tests/chmodes/ergo.py index eef9d11..ae4d26d 100644 --- a/irctest/server_tests/chmodes/ergo.py +++ b/irctest/server_tests/chmodes/ergo.py @@ -1,3 +1,7 @@ +""" +Various Ergo-specific channel modes +""" + from irctest import cases from irctest.numerics import ERR_CANNOTSENDTOCHAN, ERR_CHANOPRIVSNEEDED diff --git a/irctest/server_tests/chmodes/key.py b/irctest/server_tests/chmodes/key.py index eae1ab3..6878c90 100644 --- a/irctest/server_tests/chmodes/key.py +++ b/irctest/server_tests/chmodes/key.py @@ -1,3 +1,10 @@ +""" +Channel key (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + import pytest from irctest import cases diff --git a/irctest/server_tests/chmodes/moderated.py b/irctest/server_tests/chmodes/moderated.py index e403dfe..d5b7b26 100644 --- a/irctest/server_tests/chmodes/moderated.py +++ b/irctest/server_tests/chmodes/moderated.py @@ -1,3 +1,9 @@ +""" +Channel moderation mode (`RFC 2812 +`__, +`Modern `__) +""" + from irctest import cases from irctest.numerics import ERR_CANNOTSENDTOCHAN diff --git a/irctest/server_tests/chmodes/mute_extban.py b/irctest/server_tests/chmodes/mute_extban.py index a17b0b4..5c3c6d4 100644 --- a/irctest/server_tests/chmodes/mute_extban.py +++ b/irctest/server_tests/chmodes/mute_extban.py @@ -1,3 +1,7 @@ +""" +Mute extban, currently no specifications or ways to discover it. +""" + from irctest import cases, runner from irctest.numerics import ERR_CANNOTSENDTOCHAN, ERR_CHANOPRIVSNEEDED from irctest.patma import ANYLIST, StrRe diff --git a/irctest/server_tests/chmodes/secret.py b/irctest/server_tests/chmodes/secret.py index 15efaff..30f7759 100644 --- a/irctest/server_tests/chmodes/secret.py +++ b/irctest/server_tests/chmodes/secret.py @@ -1,3 +1,10 @@ +""" +Channel secrecy mode (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + from irctest import cases from irctest.numerics import RPL_LIST diff --git a/irctest/server_tests/confusables.py b/irctest/server_tests/confusables.py index 223d84b..480ece2 100644 --- a/irctest/server_tests/confusables.py +++ b/irctest/server_tests/confusables.py @@ -1,3 +1,8 @@ +""" +`Ergo `_-specific tests for nick collisions based on Unicode +confusable characters +""" + from irctest import cases from irctest.numerics import ERR_NICKNAMEINUSE, RPL_WELCOME diff --git a/irctest/server_tests/connection_registration.py b/irctest/server_tests/connection_registration.py index 6a1df18..e4a1c0b 100644 --- a/irctest/server_tests/connection_registration.py +++ b/irctest/server_tests/connection_registration.py @@ -1,6 +1,8 @@ """ Tests section 4.1 of RFC 1459. + +TODO: cross-reference Modern and RFC 2812 too """ from irctest import cases @@ -183,60 +185,3 @@ class ConnectionRegistrationTestCase(cases.BaseServerTestCase): command=ERR_NEEDMOREPARAMS, params=[StrRe(r"(\*|foo)"), "USER", ANYSTR], ) - - @cases.mark_specifications("IRCv3") - def testIrc301CapLs(self): - """ - Current version: - - "The LS subcommand is used to list the capabilities supported by the server. - The client should send an LS subcommand with no other arguments to solicit - a list of all capabilities." - - "If a client has not indicated support for CAP LS 302 features, - the server MUST NOT send these new features to the client." - -- - - Before the v3.1 / v3.2 merge: - - IRCv3.1: “The LS subcommand is used to list the capabilities - supported by the server. The client should send an LS subcommand with - no other arguments to solicit a list of all capabilities.” - -- - - IRCv3.2: “Servers MUST NOT send messages described by this document if - the client only supports version 3.1.” - -- - """ # noqa - self.addClient() - self.sendLine(1, "CAP LS") - m = self.getRegistrationMessage(1) - self.assertNotEqual( - m.params[2], - "*", - m, - fail_msg="Server replied with multi-line CAP LS to a " - "“CAP LS” (ie. IRCv3.1) request: {msg}", - ) - self.assertFalse( - any("=" in cap for cap in m.params[2].split()), - "Server replied with a name-value capability in " - "CAP LS reply as a response to “CAP LS” (ie. IRCv3.1) " - "request: {}".format(m), - ) - - @cases.mark_specifications("IRCv3") - def testEmptyCapList(self): - """“If no capabilities are active, an empty parameter must be sent.” - -- - """ # noqa - self.addClient() - self.sendLine(1, "CAP LIST") - m = self.getRegistrationMessage(1) - self.assertMessageMatch( - m, - command="CAP", - params=["*", "LIST", ""], - fail_msg="Sending “CAP LIST” as first message got a reply " - "that is not “CAP * LIST :”: {msg}", - ) diff --git a/irctest/server_tests/echo_message.py b/irctest/server_tests/echo_message.py index f183316..1da3412 100644 --- a/irctest/server_tests/echo_message.py +++ b/irctest/server_tests/echo_message.py @@ -1,5 +1,5 @@ """ - +`IRCv3 echo-message `_ """ import pytest diff --git a/irctest/server_tests/ergo/services.py b/irctest/server_tests/ergo/services.py index eb00ab2..ef877bd 100644 --- a/irctest/server_tests/ergo/services.py +++ b/irctest/server_tests/ergo/services.py @@ -1,3 +1,7 @@ +""" +`Ergo `-specific tests of NickServ. +""" + from irctest import cases from irctest.numerics import RPL_YOUREOPER diff --git a/irctest/server_tests/extended_join.py b/irctest/server_tests/extended_join.py index 7adf811..13dc975 100644 --- a/irctest/server_tests/extended_join.py +++ b/irctest/server_tests/extended_join.py @@ -1,5 +1,5 @@ """ - +`IRCv3 extended-join `_ """ from irctest import cases diff --git a/irctest/server_tests/help.py b/irctest/server_tests/help.py index c5acc65..9058ea3 100644 --- a/irctest/server_tests/help.py +++ b/irctest/server_tests/help.py @@ -1,5 +1,5 @@ """ -The HELP and HELPOP command. +The HELP and HELPOP command (`Modern `__) """ import re diff --git a/irctest/server_tests/info.py b/irctest/server_tests/info.py index db0d9db..8e3ed61 100644 --- a/irctest/server_tests/info.py +++ b/irctest/server_tests/info.py @@ -1,5 +1,8 @@ """ -The INFO command. +The INFO command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) """ import pytest diff --git a/irctest/server_tests/invite.py b/irctest/server_tests/invite.py index 8c07371..f441849 100644 --- a/irctest/server_tests/invite.py +++ b/irctest/server_tests/invite.py @@ -1,3 +1,10 @@ +""" +The INVITE command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + import pytest from irctest import cases diff --git a/irctest/server_tests/isupport.py b/irctest/server_tests/isupport.py index 40f087d..2c3cbaa 100644 --- a/irctest/server_tests/isupport.py +++ b/irctest/server_tests/isupport.py @@ -1,3 +1,8 @@ +""" +RPL_ISUPPORT: `format `__ +and various `tokens `__ +""" + import re from irctest import cases, runner diff --git a/irctest/server_tests/join.py b/irctest/server_tests/join.py index 673d403..e3433e6 100644 --- a/irctest/server_tests/join.py +++ b/irctest/server_tests/join.py @@ -1,3 +1,10 @@ +""" +The JOIN command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + from irctest import cases from irctest.irc_utils import ambiguities diff --git a/irctest/server_tests/kick.py b/irctest/server_tests/kick.py index aaafcd5..d2acc72 100644 --- a/irctest/server_tests/kick.py +++ b/irctest/server_tests/kick.py @@ -1,3 +1,10 @@ +""" +The INFO command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + import pytest from irctest import cases, client_mock, runner diff --git a/irctest/server_tests/labeled_responses.py b/irctest/server_tests/labeled_responses.py index f1c2374..03f9dfd 100644 --- a/irctest/server_tests/labeled_responses.py +++ b/irctest/server_tests/labeled_responses.py @@ -1,8 +1,8 @@ """ +`IRCv3 labeled-response `_ + This specification is a little hard to test because all labels are optional; so there may be many false positives. - - """ import re diff --git a/irctest/server_tests/list.py b/irctest/server_tests/list.py index 9529cb9..0c57289 100644 --- a/irctest/server_tests/list.py +++ b/irctest/server_tests/list.py @@ -1,3 +1,12 @@ +""" +The LIST command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) + +TODO: check with Modern +""" + from irctest import cases diff --git a/irctest/server_tests/lusers.py b/irctest/server_tests/lusers.py index 58f3601..7eb59d6 100644 --- a/irctest/server_tests/lusers.py +++ b/irctest/server_tests/lusers.py @@ -1,3 +1,11 @@ +""" +The LUSERS command (`RFC 2812 +`__, +`Modern `__), +which provides statistics on user counts. +""" + + from dataclasses import dataclass import re from typing import Optional diff --git a/irctest/server_tests/message_tags.py b/irctest/server_tests/message_tags.py index 9d7ba14..e19a2d9 100644 --- a/irctest/server_tests/message_tags.py +++ b/irctest/server_tests/message_tags.py @@ -1,5 +1,5 @@ """ -https://ircv3.net/specs/extensions/message-tags.html +`IRCv3 message-tags `_ """ import pytest diff --git a/irctest/server_tests/messages.py b/irctest/server_tests/messages.py index 7f26025..a4e8544 100644 --- a/irctest/server_tests/messages.py +++ b/irctest/server_tests/messages.py @@ -1,6 +1,5 @@ """ -Section 3.2 of RFC 2812 - +The PRIVMSG and NOTICE commands. """ from irctest import cases diff --git a/irctest/server_tests/metadata.py b/irctest/server_tests/metadata.py index 6317c5e..abfde8b 100644 --- a/irctest/server_tests/metadata.py +++ b/irctest/server_tests/metadata.py @@ -1,6 +1,5 @@ """ -Tests METADATA features. - +`Deprecated IRCv3 Metadata `_ """ from irctest import cases diff --git a/irctest/server_tests/monitor.py b/irctest/server_tests/monitor.py index 56e0306..211ee67 100644 --- a/irctest/server_tests/monitor.py +++ b/irctest/server_tests/monitor.py @@ -1,5 +1,5 @@ """ - +`IRCv3 MONITOR `_ """ from irctest import cases diff --git a/irctest/server_tests/multi_prefix.py b/irctest/server_tests/multi_prefix.py index 02e7aa9..1861ac7 100644 --- a/irctest/server_tests/multi_prefix.py +++ b/irctest/server_tests/multi_prefix.py @@ -1,6 +1,5 @@ """ -Tests multi-prefix. - +`IRCv3 multi-prefix `_ """ from irctest import cases diff --git a/irctest/server_tests/multiline.py b/irctest/server_tests/multiline.py index 7e872df..ac4b7d5 100644 --- a/irctest/server_tests/multiline.py +++ b/irctest/server_tests/multiline.py @@ -1,5 +1,5 @@ """ -draft/multiline +`Draft IRCv3 multiline `_ """ from irctest import cases diff --git a/irctest/server_tests/names.py b/irctest/server_tests/names.py index 628b2ac..5a79743 100644 --- a/irctest/server_tests/names.py +++ b/irctest/server_tests/names.py @@ -1,3 +1,10 @@ +""" +The NAMES command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + from irctest import cases from irctest.numerics import RPL_ENDOFNAMES from irctest.patma import ANYSTR diff --git a/irctest/server_tests/part.py b/irctest/server_tests/part.py index acc2f86..59a2045 100644 --- a/irctest/server_tests/part.py +++ b/irctest/server_tests/part.py @@ -1,3 +1,12 @@ +""" +The PART command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) + +TODO: cross-reference Modern +""" + import time from irctest import cases diff --git a/irctest/server_tests/pingpong.py b/irctest/server_tests/pingpong.py index 33dc4aa..0924d6b 100644 --- a/irctest/server_tests/pingpong.py +++ b/irctest/server_tests/pingpong.py @@ -1,3 +1,7 @@ +""" +The PING and PONG commands +""" + from irctest import cases from irctest.numerics import ERR_NEEDMOREPARAMS, ERR_NOORIGIN from irctest.patma import ANYSTR diff --git a/irctest/server_tests/quit.py b/irctest/server_tests/quit.py index 8a7200d..022447f 100644 --- a/irctest/server_tests/quit.py +++ b/irctest/server_tests/quit.py @@ -1,3 +1,12 @@ +""" +The QUITcommand (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) + +TODO: cross-reference RFC 1459 and Modern +""" + import time from irctest import cases diff --git a/irctest/server_tests/readq.py b/irctest/server_tests/readq.py index 4e8182d..05eeeed 100644 --- a/irctest/server_tests/readq.py +++ b/irctest/server_tests/readq.py @@ -1,9 +1,12 @@ +""" +`Ergo `_-specific tests of responses to DoS attacks +using long lines. +""" + from irctest import cases class ReadqTestCase(cases.BaseServerTestCase): - """Test responses to DoS attacks using long lines.""" - @cases.mark_specifications("Ergo") @cases.mark_capabilities("message-tags") def testReadqTags(self): diff --git a/irctest/server_tests/regressions.py b/irctest/server_tests/regressions.py index 0361b3c..15ff21e 100644 --- a/irctest/server_tests/regressions.py +++ b/irctest/server_tests/regressions.py @@ -1,5 +1,5 @@ """ -Regression tests for bugs in oragono. +Regression tests for bugs in `Ergo `_. """ import time diff --git a/irctest/server_tests/relaymsg.py b/irctest/server_tests/relaymsg.py index 07df252..18af038 100644 --- a/irctest/server_tests/relaymsg.py +++ b/irctest/server_tests/relaymsg.py @@ -1,3 +1,7 @@ +""" +RELAYMSG command of `Ergo `_ +""" + from irctest import cases from irctest.irc_utils.junkdrawer import random_name from irctest.patma import ANYSTR diff --git a/irctest/server_tests/roleplay.py b/irctest/server_tests/roleplay.py index 6ccfd68..2387ced 100644 --- a/irctest/server_tests/roleplay.py +++ b/irctest/server_tests/roleplay.py @@ -1,3 +1,7 @@ +""" +Roleplay features of `Ergo `_ +""" + from irctest import cases from irctest.irc_utils.junkdrawer import random_name from irctest.numerics import ERR_CANNOTSENDRP diff --git a/irctest/server_tests/statusmsg.py b/irctest/server_tests/statusmsg.py index 7a07a2b..fb063f8 100644 --- a/irctest/server_tests/statusmsg.py +++ b/irctest/server_tests/statusmsg.py @@ -1,3 +1,10 @@ +""" +STATUSMSG ISUPPORT token and related PRIVMSG (`Modern +`__) + +TODO: cross-reference Modern +""" + from irctest import cases, runner from irctest.numerics import RPL_NAMREPLY diff --git a/irctest/server_tests/topic.py b/irctest/server_tests/topic.py index 4d83604..9489571 100644 --- a/irctest/server_tests/topic.py +++ b/irctest/server_tests/topic.py @@ -1,3 +1,10 @@ +""" +The TOPIC command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) +""" + from irctest import cases, client_mock, runner from irctest.numerics import ERR_CHANOPRIVSNEEDED, RPL_NOTOPIC, RPL_TOPIC, RPL_TOPICTIME diff --git a/irctest/server_tests/utf8.py b/irctest/server_tests/utf8.py index 46c838b..32ff563 100644 --- a/irctest/server_tests/utf8.py +++ b/irctest/server_tests/utf8.py @@ -1,3 +1,10 @@ +""" +`Ergo `_-specific tests of non-Unicode filtering + +TODO: turn this into a test of `IRCv3 UTF8ONLY +`_ +""" + from irctest import cases from irctest.patma import ANYSTR diff --git a/irctest/server_tests/wallops.py b/irctest/server_tests/wallops.py index 2d5fb69..c1d493b 100644 --- a/irctest/server_tests/wallops.py +++ b/irctest/server_tests/wallops.py @@ -1,3 +1,9 @@ +""" +The WALLOPS command (`RFC 2812 +`__, +`Modern `__) +""" + from irctest import cases, runner from irctest.numerics import ERR_NOPRIVILEGES, ERR_UNKNOWNCOMMAND, RPL_YOUREOPER from irctest.patma import ANYSTR, StrRe diff --git a/irctest/server_tests/who.py b/irctest/server_tests/who.py index c526b0d..e320cb1 100644 --- a/irctest/server_tests/who.py +++ b/irctest/server_tests/who.py @@ -1,3 +1,10 @@ +""" +The WHO command (`Modern `__) +and `IRCv3 WHOX `_ + +TODO: cross-reference RFC 1459 and RFC 2812 +""" + import re import pytest diff --git a/irctest/server_tests/whois.py b/irctest/server_tests/whois.py index 8a0ef3a..a23ee66 100644 --- a/irctest/server_tests/whois.py +++ b/irctest/server_tests/whois.py @@ -1,3 +1,9 @@ +""" +The WHOIS command (`Modern `__) + +TODO: cross-reference RFC 1459 and RFC 2812 +""" + import pytest from irctest import cases diff --git a/irctest/server_tests/whowas.py b/irctest/server_tests/whowas.py index 2550432..dd65b54 100644 --- a/irctest/server_tests/whowas.py +++ b/irctest/server_tests/whowas.py @@ -1,3 +1,13 @@ +""" +The WHOSWAS command (`RFC 1459 +`__, +`RFC 2812 `__, +`Modern `__) + +TODO: cross-reference Modern +""" + + import pytest from irctest import cases, runner diff --git a/irctest/server_tests/znc_playback.py b/irctest/server_tests/znc_playback.py index a5ac61f..ca00efd 100644 --- a/irctest/server_tests/znc_playback.py +++ b/irctest/server_tests/znc_playback.py @@ -1,3 +1,7 @@ +""" +`Ergo `_-specific tests of ZNC-like message playback +""" + import time from irctest import cases diff --git a/make_workflows.py b/make_workflows.py index 657ae85..62ab72b 100644 --- a/make_workflows.py +++ b/make_workflows.py @@ -367,7 +367,7 @@ def generate_workflow(config: dict, version_flavor: VersionFlavor): "name": "Install dashboard dependencies", "run": script( "python -m pip install --upgrade pip", - "pip install defusedxml", + "pip install defusedxml docutils -r requirements.txt", ), }, {