From 2a25491ab5785f00e1723e453e77a5d2f288dd40 Mon Sep 17 00:00:00 2001 From: parnexcodes Date: Sun, 11 Oct 2026 08:45:18 +0530 Subject: [PATCH 1/2] feat: named error codes for ports Fixes #24 Co-Authored-By: Claude Opus 5.5 --- README.md | 8 +++++++- src/usedock/__init__.py | 6 ++++++ src/usedock/errors.py | 15 +++++++++++++++ tests/test_client.py | 6 ++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a70303f..be5c11a 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,13 @@ Some codes raise a subclass of `DockError`, so you can catch them directly: `ConnectorNotConnectedError` (`connector_not_connected`, 409), `ConnectorAdminOnlyError` (`connector_admin_only`, 403), `ConnectorNotFoundError` (`connector_not_found`, 404), `ImageUnknownError` -(`image_unknown`, 400) and `ImageUnavailableError` (`image_unavailable`, 400). +(`image_unknown`, 400), `ImageUnavailableError` (`image_unavailable`, 400), +`PortNotFoundError` (`port_not_found`, 404), `PortLimitReachedError` +(`port_limit_reached`, 409) and `PortsUnavailableError` (`ports_unavailable`, +503). + +Port 2222 is reserved for the dock agent and is rejected with +`validation_error`. A dock can expose at most 10 ports. ## Configuration diff --git a/src/usedock/__init__.py b/src/usedock/__init__.py index 80ed42f..08c4aed 100644 --- a/src/usedock/__init__.py +++ b/src/usedock/__init__.py @@ -6,6 +6,9 @@ DockError, ImageUnavailableError, ImageUnknownError, + PortLimitReachedError, + PortNotFoundError, + PortsUnavailableError, ) from .models import ( Connector, @@ -34,6 +37,9 @@ "Image", "ImageUnavailableError", "ImageUnknownError", + "PortLimitReachedError", + "PortNotFoundError", + "PortsUnavailableError", "Operation", "Port", ] diff --git a/src/usedock/errors.py b/src/usedock/errors.py index f6450f1..39d1126 100644 --- a/src/usedock/errors.py +++ b/src/usedock/errors.py @@ -39,12 +39,27 @@ class ImageUnavailableError(DockError): """``image_unavailable`` (400): the image is in the catalog but no host serves it right now.""" +class PortNotFoundError(DockError): + """``port_not_found`` (404): closing a port that is not exposed.""" + + +class PortLimitReachedError(DockError): + """``port_limit_reached`` (409): a dock already exposes the maximum of 10 ports.""" + + +class PortsUnavailableError(DockError): + """``ports_unavailable`` (503): hosted ports are not configured on this deployment.""" + + _BY_CODE: Dict[str, Type[DockError]] = { "connector_not_connected": ConnectorNotConnectedError, "connector_admin_only": ConnectorAdminOnlyError, "connector_not_found": ConnectorNotFoundError, "image_unknown": ImageUnknownError, "image_unavailable": ImageUnavailableError, + "port_not_found": PortNotFoundError, + "port_limit_reached": PortLimitReachedError, + "ports_unavailable": PortsUnavailableError, } diff --git a/tests/test_client.py b/tests/test_client.py index 545ec16..abc8964 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -23,6 +23,9 @@ DockState, ImageUnavailableError, ImageUnknownError, + PortLimitReachedError, + PortNotFoundError, + PortsUnavailableError, ) from usedock.client import MAX_COMMAND_BYTES, shell_quote @@ -642,6 +645,9 @@ def test_images_list() -> None: ("connector_admin_only", 403, ConnectorAdminOnlyError), ("image_unknown", 400, ImageUnknownError), ("image_unavailable", 400, ImageUnavailableError), + ("port_not_found", 404, PortNotFoundError), + ("port_limit_reached", 409, PortLimitReachedError), + ("ports_unavailable", 503, PortsUnavailableError), ], ) def test_new_error_codes_raise_typed_errors(code: str, status: int, cls: type) -> None: From ac78d34d441ae2253f8121a88f1faf7f5f82e845 Mon Sep 17 00:00:00 2001 From: parnexcodes Date: Sun, 11 Oct 2026 08:48:10 +0530 Subject: [PATCH 2/2] chore: keep __all__ alphabetical Co-Authored-By: Claude Opus 5.5 --- src/usedock/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/usedock/__init__.py b/src/usedock/__init__.py index 08c4aed..c2b59aa 100644 --- a/src/usedock/__init__.py +++ b/src/usedock/__init__.py @@ -37,9 +37,9 @@ "Image", "ImageUnavailableError", "ImageUnknownError", + "Operation", + "Port", "PortLimitReachedError", "PortNotFoundError", "PortsUnavailableError", - "Operation", - "Port", ]