Skip to content

Commit

Permalink
type annotate twisted.test.test_error
Browse files Browse the repository at this point in the history
  • Loading branch information
graingert committed Sep 26, 2023
1 parent 28d3b00 commit 972a4c3
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 43 deletions.
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,6 @@ module = [
'twisted.test.test_cooperator',
'twisted.test.test_defgen',
'twisted.test.test_dirdbm',
'twisted.test.test_error',
'twisted.test.test_factories',
'twisted.test.test_fdesc',
'twisted.test.test_ftp',
Expand Down
127 changes: 85 additions & 42 deletions src/twisted/test/test_error.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,62 @@
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.

from __future__ import annotations

import errno
import socket
import sys
from typing import Sequence

from twisted.internet import error
from twisted.python.runtime import platformType
from twisted.trial import unittest


class StringificationTests(unittest.SynchronousTestCase):
"""Test that the exceptions have useful stringifications."""

listOfTests = [
listOfTests: list[
tuple[
str,
type[Exception],
Sequence[str | int | Exception | None],
dict[str, str | int],
]
] = [
# (output, exception[, args[, kwargs]]),
("An error occurred binding to an interface.", error.BindError),
("An error occurred binding to an interface: foo.", error.BindError, ["foo"]),
("An error occurred binding to an interface.", error.BindError, [], {}),
(
"An error occurred binding to an interface: foo.",
error.BindError,
["foo"],
{},
),
(
"An error occurred binding to an interface: foo bar.",
error.BindError,
["foo", "bar"],
{},
),
(
"Couldn't listen on eth0:4242: Foo.",
error.CannotListenError,
("eth0", 4242, socket.error("Foo")),
{},
),
("Message is too long to send.", error.MessageLengthError),
("Message is too long to send.", error.MessageLengthError, [], {}),
(
"Message is too long to send: foo bar.",
error.MessageLengthError,
["foo", "bar"],
{},
),
("DNS lookup failed.", error.DNSLookupError),
("DNS lookup failed: foo bar.", error.DNSLookupError, ["foo", "bar"]),
("An error occurred while connecting.", error.ConnectError),
("DNS lookup failed.", error.DNSLookupError, [], {}),
("DNS lookup failed: foo bar.", error.DNSLookupError, ["foo", "bar"], {}),
("An error occurred while connecting.", error.ConnectError, [], {}),
(
"An error occurred while connecting: someOsError.",
error.ConnectError,
["someOsError"],
{},
),
(
"An error occurred while connecting: foo.",
Expand All @@ -51,62 +68,80 @@ class StringificationTests(unittest.SynchronousTestCase):
"An error occurred while connecting: someOsError: foo.",
error.ConnectError,
["someOsError", "foo"],
{},
),
("Couldn't bind.", error.ConnectBindError),
("Couldn't bind: someOsError.", error.ConnectBindError, ["someOsError"]),
("Couldn't bind.", error.ConnectBindError, [], {}),
("Couldn't bind: someOsError.", error.ConnectBindError, ["someOsError"], {}),
(
"Couldn't bind: someOsError: foo.",
error.ConnectBindError,
["someOsError", "foo"],
{},
),
("Hostname couldn't be looked up.", error.UnknownHostError, [], {}),
("No route to host.", error.NoRouteError, [], {}),
("Connection was refused by other side.", error.ConnectionRefusedError, [], {}),
("TCP connection timed out.", error.TCPTimedOutError, [], {}),
("File used for UNIX socket is no good.", error.BadFileError, [], {}),
(
"Service name given as port is unknown.",
error.ServiceNameUnknownError,
[],
{},
),
("Hostname couldn't be looked up.", error.UnknownHostError),
("No route to host.", error.NoRouteError),
("Connection was refused by other side.", error.ConnectionRefusedError),
("TCP connection timed out.", error.TCPTimedOutError),
("File used for UNIX socket is no good.", error.BadFileError),
("Service name given as port is unknown.", error.ServiceNameUnknownError),
("User aborted connection.", error.UserError),
("User timeout caused connection failure.", error.TimeoutError),
("An SSL error occurred.", error.SSLError),
("User aborted connection.", error.UserError, [], {}),
("User timeout caused connection failure.", error.TimeoutError, [], {}),
("An SSL error occurred.", error.SSLError, [], {}),
(
"Connection to the other side was lost in a non-clean fashion.",
error.ConnectionLost,
[],
{},
),
(
"Connection to the other side was lost in a non-clean fashion: foo bar.",
error.ConnectionLost,
["foo", "bar"],
{},
),
("Connection was closed cleanly.", error.ConnectionDone),
("Connection was closed cleanly.", error.ConnectionDone, [], {}),
(
"Connection was closed cleanly: foo bar.",
error.ConnectionDone,
["foo", "bar"],
{},
),
(
"Uh.", # TODO nice docstring, you've got there.
error.ConnectionFdescWentAway,
[],
{},
),
("Tried to cancel an already-called event.", error.AlreadyCalled),
("Tried to cancel an already-called event.", error.AlreadyCalled, [], {}),
(
"Tried to cancel an already-called event: foo bar.",
error.AlreadyCalled,
["foo", "bar"],
{},
),
("Tried to cancel an already-cancelled event.", error.AlreadyCancelled),
("Tried to cancel an already-cancelled event.", error.AlreadyCancelled, [], {}),
(
"Tried to cancel an already-cancelled event: x 2.",
error.AlreadyCancelled,
["x", "2"],
{},
),
(
"A process has ended without apparent errors: process finished with exit code 0.",
error.ProcessDone,
[None],
{},
),
(
"A process has ended with a probable error condition: process ended.",
error.ProcessTerminated,
[],
{},
),
(
"A process has ended with a probable error condition: process ended with exit code 42.",
Expand All @@ -123,39 +158,39 @@ class StringificationTests(unittest.SynchronousTestCase):
(
"The Connector was not connecting when it was asked to stop connecting.",
error.NotConnectingError,
[],
{},
),
(
"The Connector was not connecting when it was asked to stop connecting: x 13.",
error.NotConnectingError,
["x", "13"],
{},
),
(
"The Port was not listening when it was asked to stop listening.",
error.NotListeningError,
[],
{},
),
(
"The Port was not listening when it was asked to stop listening: a 12.",
error.NotListeningError,
["a", "12"],
{},
),
]

def testThemAll(self):
def testThemAll(self) -> None:
for entry in self.listOfTests:
output = entry[0]
exception = entry[1]
try:
args = entry[2]
except IndexError:
args = ()
try:
kwargs = entry[3]
except IndexError:
kwargs = {}
args = entry[2]
kwargs = entry[3]

self.assertEqual(str(exception(*args, **kwargs)), output)

def test_connectingCancelledError(self):
def test_connectingCancelledError(self) -> None:
"""
L{error.ConnectingCancelledError} has an C{address} attribute.
"""
Expand All @@ -169,19 +204,19 @@ class SubclassingTests(unittest.SynchronousTestCase):
Some exceptions are subclasses of other exceptions.
"""

def test_connectionLostSubclassOfConnectionClosed(self):
def test_connectionLostSubclassOfConnectionClosed(self) -> None:
"""
L{error.ConnectionClosed} is a superclass of L{error.ConnectionLost}.
"""
self.assertTrue(issubclass(error.ConnectionLost, error.ConnectionClosed))

def test_connectionDoneSubclassOfConnectionClosed(self):
def test_connectionDoneSubclassOfConnectionClosed(self) -> None:
"""
L{error.ConnectionClosed} is a superclass of L{error.ConnectionDone}.
"""
self.assertTrue(issubclass(error.ConnectionDone, error.ConnectionClosed))

def test_invalidAddressErrorSubclassOfValueError(self):
def test_invalidAddressErrorSubclassOfValueError(self) -> None:
"""
L{ValueError} is a superclass of L{error.InvalidAddressError}.
"""
Expand All @@ -195,7 +230,9 @@ class GetConnectErrorTests(unittest.SynchronousTestCase):
exception instance.
"""

def assertErrnoException(self, errno, expectedClass):
def assertErrnoException(
self, errno: int, expectedClass: type[error.ConnectError]
) -> None:
"""
When called with a tuple with the given errno,
L{error.getConnectError} returns an exception which is an instance of
Expand All @@ -205,7 +242,13 @@ def assertErrnoException(self, errno, expectedClass):
result = error.getConnectError(e)
self.assertCorrectException(errno, "lalala", result, expectedClass)

def assertCorrectException(self, errno, message, result, expectedClass):
def assertCorrectException(
self,
errno: int | None,
message: object,
result: error.ConnectError,
expectedClass: type[error.ConnectError],
) -> None:
"""
The given result of L{error.getConnectError} has the given attributes
(C{osError} and C{args}), and is an instance of the given class.
Expand All @@ -216,28 +259,28 @@ def assertCorrectException(self, errno, message, result, expectedClass):
self.assertEqual(result.osError, errno)
self.assertEqual(result.args, (message,))

def test_errno(self):
def test_errno(self) -> None:
"""
L{error.getConnectError} converts based on errno for C{socket.error}.
"""
self.assertErrnoException(errno.ENETUNREACH, error.NoRouteError)
self.assertErrnoException(errno.ECONNREFUSED, error.ConnectionRefusedError)
self.assertErrnoException(errno.ETIMEDOUT, error.TCPTimedOutError)
if platformType == "win32":
if sys.platform == "win32":
self.assertErrnoException(
errno.WSAECONNREFUSED, error.ConnectionRefusedError
)
self.assertErrnoException(errno.WSAENETUNREACH, error.NoRouteError)

def test_gaierror(self):
def test_gaierror(self) -> None:
"""
L{error.getConnectError} converts to a L{error.UnknownHostError} given
a C{socket.gaierror} instance.
"""
result = error.getConnectError(socket.gaierror(12, "hello"))
self.assertCorrectException(12, "hello", result, error.UnknownHostError)

def test_nonTuple(self):
def test_nonTuple(self) -> None:
"""
L{error.getConnectError} converts to a L{error.ConnectError} given
an argument that cannot be unpacked.
Expand Down

0 comments on commit 972a4c3

Please sign in to comment.