Skip to content

Commit

Permalink
Fix exec/tty related type annotations and type checks
Browse files Browse the repository at this point in the history
  • Loading branch information
achimnol committed Jun 12, 2024
1 parent 05889ec commit b392be6
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 22 deletions.
34 changes: 22 additions & 12 deletions aiodocker/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from multidict import MultiDict
from yarl import URL

from aiodocker.types import JSONObject

from .exceptions import DockerContainerError, DockerError
from .execs import Exec
from .jsonstream import json_stream_list, json_stream_stream
Expand All @@ -21,13 +23,17 @@ class DockerContainers:
def __init__(self, docker):
self.docker = docker

async def list(self, **kwargs):
async def list(self, **kwargs) -> Sequence[DockerContainer]:
data = await self.docker._query_json(
"containers/json", method="GET", params=kwargs
)
return [DockerContainer(self.docker, **x) for x in data]

async def create_or_replace(self, name, config):
async def create_or_replace(
self,
name: str,
config: JSONObject,
) -> DockerContainer:
container = None

try:
Expand All @@ -46,25 +52,29 @@ async def create_or_replace(self, name, config):

return container

async def create(self, config, *, name=None):
async def create(
self,
config: JSONObject,
*,
name: Optional[str] = None,
) -> DockerContainer:
url = "containers/create"

config = json.dumps(config, sort_keys=True).encode("utf-8")
encoded_config = json.dumps(config, sort_keys=True).encode("utf-8")
kwargs = {}
if name:
kwargs["name"] = name
data = await self.docker._query_json(
url, method="POST", data=config, params=kwargs
url, method="POST", data=encoded_config, params=kwargs
)
return DockerContainer(self.docker, id=data["Id"])

async def run(
self,
config,
config: JSONObject,
*,
auth: Optional[Union[Mapping, str, bytes]] = None,
name: Optional[str] = None,
):
) -> DockerContainer:
"""
Create and start a container.
Expand Down Expand Up @@ -93,22 +103,22 @@ async def run(

return container

async def get(self, container, **kwargs):
async def get(self, container_id: str, **kwargs) -> DockerContainer:
data = await self.docker._query_json(
f"containers/{container}/json",
f"containers/{container_id}/json",
method="GET",
params=kwargs,
)
return DockerContainer(self.docker, **data)

def container(self, container_id, **kwargs):
def container(self, container_id: str, **kwargs) -> DockerContainer:
data = {"id": container_id}
data.update(kwargs)
return DockerContainer(self.docker, **data)

def exec(self, exec_id: str) -> Exec:
"""Return Exec instance for already created exec object."""
return Exec(self.docker, exec_id, None)
return Exec(self.docker, exec_id)


class DockerContainer:
Expand Down
8 changes: 5 additions & 3 deletions aiodocker/execs.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@


class Exec:
def __init__(self, docker: "Docker", id: str, tty: Optional[bool]) -> None:
def __init__(self, docker: "Docker", id: str, tty: Optional[bool] = None) -> None:
self.docker = docker
self._id = id
self._tty = tty
Expand Down Expand Up @@ -96,8 +96,10 @@ def start(self, *, timeout=None, detach=False):
from stdout or 2 if from stderr.
"""
if detach:
assert self._tty is not None
return self._start_detached(timeout, self._tty)
return self._start_detached(
timeout,
self._tty if self._tty is not None else False,
)
else:

async def setup() -> Tuple[URL, bytes, bool]:
Expand Down
29 changes: 24 additions & 5 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
import sys
import traceback
import uuid
from collections.abc import AsyncIterator, Awaitable, Callable
from typing import Any, Dict

import pytest
from packaging.version import parse as parse_version
from typing_extensions import TypeAlias

from aiodocker.containers import DockerContainer
from aiodocker.docker import Docker
from aiodocker.exceptions import DockerError

Expand Down Expand Up @@ -128,24 +131,40 @@ async def swarm(docker):
assert await docker.swarm.leave(force=True)


@pytest.fixture
async def make_container(docker):
container = None
AsyncContainerFactory: TypeAlias = Callable[
[Dict[str, Any], str], Awaitable[DockerContainer]
]


async def _spawn(config: Dict[str, Any], name=None):
@pytest.fixture
async def make_container(
docker: Docker,
) -> AsyncIterator[AsyncContainerFactory]:
container: DockerContainer | None = None

async def _spawn(
config: Dict[str, Any],
name: str,
) -> DockerContainer:
nonlocal container
container = await docker.containers.create_or_replace(config=config, name=name)
assert container is not None
await container.start()
return container

yield _spawn

if container is not None:
assert isinstance(container, DockerContainer)
await container.delete(force=True)


@pytest.fixture
async def shell_container(docker, make_container, image_name):
async def shell_container(
docker: Docker,
make_container,
image_name: str,
) -> AsyncContainerFactory:
config = {
"Cmd": ["python"],
"Image": image_name,
Expand Down
5 changes: 3 additions & 2 deletions tests/test_execs.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,10 @@ async def test_exec_restore_tty_attached(docker, shell_container):
)

exec2 = docker.containers.exec(exec1.id)
async with exec2.start() as stream:
stream = exec2.start()
assert isinstance(stream, Stream)
async with stream:
assert exec2._tty
stream


@pytest.mark.asyncio
Expand Down

0 comments on commit b392be6

Please sign in to comment.