From 4ce3d30f5576a84c379ce4413a08421d3359f361 Mon Sep 17 00:00:00 2001 From: Joongi Kim Date: Wed, 26 Jun 2024 00:48:41 +0900 Subject: [PATCH] Annotate more test codes --- aiodocker/utils.py | 8 ++- tests/test_containers.py | 39 ++++++++------ tests/test_events.py | 10 ++-- tests/test_integration.py | 110 ++++++++++++++++++++++---------------- tests/test_networks.py | 18 ++++--- tests/test_system.py | 4 +- tests/test_utils.py | 37 ++++++------- tests/test_volumes.py | 11 ++-- 8 files changed, 136 insertions(+), 101 deletions(-) diff --git a/aiodocker/utils.py b/aiodocker/utils.py index 8b2d140b..cf5ce783 100644 --- a/aiodocker/utils.py +++ b/aiodocker/utils.py @@ -9,9 +9,11 @@ from typing import ( IO, Any, + Dict, Iterable, Mapping, Optional, + Sequence, Tuple, Union, cast, @@ -189,13 +191,15 @@ def format_env(key, value: Union[None, bytes, str]) -> str: return f"{key}={value}" -def clean_networks(networks: Optional[Iterable[str]] = None) -> Optional[Iterable[str]]: +def clean_networks( + networks: Optional[Iterable[str]] = None, +) -> Optional[Sequence[Dict[str, Any]]]: """ Cleans the values inside `networks` Returns a new list """ if not networks: - return networks + return [] if not isinstance(networks, list): raise TypeError("networks parameter must be a list.") diff --git a/tests/test_containers.py b/tests/test_containers.py index 8cfd7725..551c36ea 100644 --- a/tests/test_containers.py +++ b/tests/test_containers.py @@ -1,20 +1,21 @@ import asyncio -import os import sys import pytest +from aiodocker.containers import DockerContainer +from aiodocker.docker import Docker from aiodocker.exceptions import DockerContainerError, DockerError -async def _validate_hello(container): +async def _validate_hello(container: DockerContainer) -> None: try: await container.start() response = await container.wait() assert response["StatusCode"] == 0 await asyncio.sleep(5) # wait for output in case of slow test container logs = await container.log(stdout=True) - assert "hello" + os.linesep in logs + assert "hello\n" in logs with pytest.raises(TypeError): await container.log() @@ -23,7 +24,7 @@ async def _validate_hello(container): @pytest.mark.asyncio -async def test_run_existing_container(docker, image_name): +async def test_run_existing_container(docker: Docker, image_name: str) -> None: await docker.pull(image_name) container = await docker.containers.run( config={ @@ -37,7 +38,9 @@ async def test_run_existing_container(docker, image_name): @pytest.mark.asyncio -async def test_run_container_with_missing_image(docker, image_name): +async def test_run_container_with_missing_image( + docker: Docker, image_name: str +) -> None: try: await docker.images.delete(image_name) except DockerError as e: @@ -61,7 +64,7 @@ async def test_run_container_with_missing_image(docker, image_name): @pytest.mark.asyncio -async def test_run_failing_start_container(docker, image_name): +async def test_run_failing_start_container(docker: Docker, image_name: str) -> None: try: await docker.images.delete(image_name) except DockerError as e: @@ -91,7 +94,7 @@ async def test_run_failing_start_container(docker, image_name): @pytest.mark.asyncio -async def test_restart(docker, image_name): +async def test_restart(docker: Docker, image_name: str) -> None: # sleep for 10 min to emulate hanging container container = await docker.containers.run( config={ @@ -117,7 +120,7 @@ async def test_restart(docker, image_name): @pytest.mark.asyncio -async def test_container_stats_list(docker, image_name): +async def test_container_stats_list(docker: Docker, image_name: str) -> None: container = await docker.containers.run( config={ "Cmd": ["-c", "print('hello')"], @@ -137,7 +140,7 @@ async def test_container_stats_list(docker, image_name): @pytest.mark.asyncio -async def test_container_stats_stream(docker, image_name): +async def test_container_stats_stream(docker: Docker, image_name: str) -> None: container = await docker.containers.run( config={ "Cmd": ["-c", "print('hello')"], @@ -161,7 +164,7 @@ async def test_container_stats_stream(docker, image_name): @pytest.mark.asyncio -async def test_resize(shell_container): +async def test_resize(shell_container: DockerContainer) -> None: await shell_container.resize(w=120, h=10) @@ -169,7 +172,9 @@ async def test_resize(shell_container): sys.platform == "win32", reason="Commit unpaused containers doesn't work on Windows" ) @pytest.mark.asyncio -async def test_commit(docker, image_name, shell_container): +async def test_commit( + docker: Docker, image_name: str, shell_container: DockerContainer +) -> None: """ "Container" key was removed in v1.45. "ContainerConfig" is not present, although this information is now present in "Config" @@ -192,7 +197,9 @@ async def test_commit(docker, image_name, shell_container): sys.platform == "win32", reason="Commit unpaused containers doesn't work on Windows" ) @pytest.mark.asyncio -async def test_commit_with_changes(docker, image_name, shell_container): +async def test_commit_with_changes( + docker: Docker, image_name: str, shell_container: DockerContainer +) -> None: ret = await shell_container.commit(changes=["EXPOSE 8000", 'CMD ["py"]']) img_id = ret["Id"] img = await docker.images.inspect(img_id) @@ -203,7 +210,7 @@ async def test_commit_with_changes(docker, image_name, shell_container): @pytest.mark.skipif(sys.platform == "win32", reason="Pause doesn't work on Windows") @pytest.mark.asyncio -async def test_pause_unpause(shell_container): +async def test_pause_unpause(shell_container: DockerContainer) -> None: await shell_container.pause() container_info = await shell_container.show() assert "State" in container_info @@ -228,7 +235,7 @@ async def test_pause_unpause(shell_container): @pytest.mark.asyncio -async def test_capture_log_oneshot(docker, image_name) -> None: +async def test_capture_log_oneshot(docker: Docker, image_name: str) -> None: container = await docker.containers.run( config={ "Cmd": [ @@ -252,7 +259,7 @@ async def test_capture_log_oneshot(docker, image_name) -> None: @pytest.mark.asyncio -async def test_capture_log_stream(docker, image_name) -> None: +async def test_capture_log_stream(docker: Docker, image_name: str) -> None: container = await docker.containers.run( config={ "Cmd": [ @@ -278,7 +285,7 @@ async def test_capture_log_stream(docker, image_name) -> None: @pytest.mark.asyncio -async def test_cancel_log(docker) -> None: +async def test_cancel_log(docker: Docker) -> None: container = docker.containers.container("invalid_container_id") with pytest.raises(DockerError): diff --git a/tests/test_events.py b/tests/test_events.py index c84f60d6..310f1a7f 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -1,10 +1,14 @@ +from __future__ import annotations + import asyncio import pytest +from aiodocker.docker import Docker + @pytest.mark.asyncio -async def test_events_default_task(docker): +async def test_events_default_task(docker: Docker) -> None: docker.events.subscribe() assert docker.events.task is not None await docker.close() @@ -13,7 +17,7 @@ async def test_events_default_task(docker): @pytest.mark.asyncio -async def test_events_provided_task(docker): +async def test_events_provided_task(docker: Docker) -> None: task = asyncio.ensure_future(docker.events.run()) docker.events.subscribe(create_task=False) assert docker.events.task is None @@ -25,7 +29,7 @@ async def test_events_provided_task(docker): @pytest.mark.asyncio -async def test_events_no_task(docker): +async def test_events_no_task(docker: Docker) -> None: assert docker.events.task is None await docker.close() assert docker.events.json_stream is None diff --git a/tests/test_integration.py b/tests/test_integration.py index 80a82963..25b57df6 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -7,13 +7,14 @@ import sys import tarfile import time -from typing import List +from typing import Any, Dict, List import aiohttp import pytest from async_timeout import timeout import aiodocker +from aiodocker.containers import DockerContainer from aiodocker.docker import Docker from aiodocker.execs import Stream @@ -38,14 +39,14 @@ async def expect_prompt(stream: Stream) -> bytes: raise AssertionError(f"[Timeout] {ret} {inp}") -def skip_windows(): +def skip_windows() -> None: if sys.platform == "win32": # replaced xfail with skip for sake of tests speed pytest.skip("image operation fails on Windows") @pytest.mark.asyncio -async def test_autodetect_host(monkeypatch): +async def test_autodetect_host(monkeypatch) -> None: docker = Docker() if "DOCKER_HOST" in os.environ: if ( @@ -63,18 +64,19 @@ async def test_autodetect_host(monkeypatch): @pytest.mark.asyncio -async def test_ssl_context(monkeypatch): +async def test_ssl_context(monkeypatch) -> None: cert_dir = pathlib.Path(__file__).parent / "certs" monkeypatch.setenv("DOCKER_HOST", "tcp://127.0.0.1:3456") monkeypatch.setenv("DOCKER_TLS_VERIFY", "1") monkeypatch.setenv("DOCKER_CERT_PATH", str(cert_dir)) docker = Docker() + assert not isinstance(docker.connector, aiohttp.BaseConnector) assert docker.connector._ssl await docker.close() with pytest.raises(TypeError): - docker = Docker(ssl_context="bad ssl context") + docker = Docker(ssl_context="bad ssl context") # type: ignore ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH) - ssl_ctx.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) + ssl_ctx.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS) # type: ignore[attr-defined] ssl_ctx.load_verify_locations(cafile=str(cert_dir / "ca.pem")) ssl_ctx.load_cert_chain( certfile=str(cert_dir / "cert.pem"), keyfile=str(cert_dir / "key.pem") @@ -88,9 +90,9 @@ async def test_ssl_context(monkeypatch): sys.platform == "win32", reason="Unix sockets are not supported on Windows" ) @pytest.mark.asyncio -async def test_connect_invalid_unix_socket(): +async def test_connect_invalid_unix_socket() -> None: docker = Docker("unix:///var/run/does-not-exist-docker.sock") - assert isinstance(docker.connector, aiohttp.connector.UnixConnector) + assert isinstance(docker.connector, aiohttp.UnixConnector) with pytest.raises(aiodocker.DockerError): await docker.containers.list() await docker.close() @@ -100,10 +102,10 @@ async def test_connect_invalid_unix_socket(): sys.platform == "win32", reason="Unix sockets are not supported on Windows" ) @pytest.mark.asyncio -async def test_connect_envvar(monkeypatch): +async def test_connect_envvar(monkeypatch) -> None: monkeypatch.setenv("DOCKER_HOST", "unix:///var/run/does-not-exist-docker.sock") docker = Docker() - assert isinstance(docker.connector, aiohttp.connector.UnixConnector) + assert isinstance(docker.connector, aiohttp.UnixConnector) assert docker.docker_host == "unix://localhost" with pytest.raises(aiodocker.DockerError): await docker.containers.list() @@ -119,7 +121,7 @@ async def test_connect_envvar(monkeypatch): @pytest.mark.asyncio -async def test_connect_with_connector(): +async def test_connect_with_connector() -> None: connector = aiohttp.BaseConnector() docker = Docker(connector=connector) assert docker.connector == connector @@ -127,11 +129,11 @@ async def test_connect_with_connector(): @pytest.mark.asyncio -async def test_container_lifecycles(docker, image_name): +async def test_container_lifecycles(docker: Docker, image_name: str) -> None: containers = await docker.containers.list(all=True) orig_count = len(containers) - config = { + config: Dict[str, Any] = { "Cmd": ["python"], "Image": image_name, "AttachStdin": False, @@ -166,31 +168,34 @@ async def test_container_lifecycles(docker, image_name): sys.platform in ["darwin", "win32"], reason="Docker for Mac and Windows has a bug with websocket", ) -async def test_stdio_stdin(docker, testing_images, shell_container): +async def test_stdio_stdin( + docker: Docker, testing_images: List[str], shell_container: DockerContainer +) -> None: # echo of the input. ws = await shell_container.websocket(stdin=True, stdout=True, stream=True) await ws.send_str("print('hello world\\n')\n") - output = b"" + output_bytes = b"" found = False try: # collect the websocket outputs for at most 2 secs until we see the # output. async with timeout(2): while True: - output += await ws.receive_bytes() - if b"print('hello world\\n')" in output: + output_bytes += await ws.receive_bytes() + if b"print('hello world\\n')" in output_bytes: found = True break except asyncio.TimeoutError: pass await ws.close() if not found: - found = b"print('hello world\\n')" in output - assert found, output + found = b"print('hello world\\n')" in output_bytes + assert found, output_bytes # cross-check with container logs. - log = [] + log: List[str] = [] found = False + output_str = "" try: # collect the logs for at most 2 secs until we see the output. @@ -203,15 +208,17 @@ async def test_stdio_stdin(docker, testing_images, shell_container): except asyncio.TimeoutError: pass if not found: - output = "".join(log) - output.strip() - found = "hello world" in output.split("\r\n") - assert found, output + output_str = "".join(log) + output_str.strip() + found = "hello world" in output_str.split("\r\n") + assert found, output_str @pytest.mark.asyncio @pytest.mark.parametrize("stderr", [True, False], ids=lambda x: f"stderr={x}") -async def test_attach_nontty(docker, image_name, make_container, stderr): +async def test_attach_nontty( + docker: Docker, image_name: str, make_container, stderr: bool +) -> None: if stderr: cmd = [ "python", @@ -221,7 +228,7 @@ async def test_attach_nontty(docker, image_name, make_container, stderr): else: cmd = ["python", "-c", "import time; time.sleep(3); print('Hello')"] - config = { + config: Dict[str, Any] = { "Cmd": cmd, "Image": image_name, "AttachStdin": False, @@ -232,19 +239,25 @@ async def test_attach_nontty(docker, image_name, make_container, stderr): "StdinOnce": False, } - container = await make_container(config, name="aiodocker-testing-attach-nontty") + container: DockerContainer = await make_container( + config, name="aiodocker-testing-attach-nontty" + ) async with container.attach(stdin=False, stdout=True, stderr=True) as stream: - fileno, data = await stream.read_out() + msg = await stream.read_out() + assert msg is not None + fileno, data = msg assert fileno == 2 if stderr else 1 assert data.strip() == b"Hello" @pytest.mark.asyncio -async def test_attach_nontty_wait_for_exit(docker, image_name, make_container): +async def test_attach_nontty_wait_for_exit( + docker: Docker, image_name: str, make_container +) -> None: cmd = ["python", "-c", "import time; time.sleep(3); print('Hello')"] - config = { + config: Dict[str, Any] = { "Cmd": cmd, "Image": image_name, "AttachStdin": False, @@ -255,7 +268,7 @@ async def test_attach_nontty_wait_for_exit(docker, image_name, make_container): "StdinOnce": False, } - container = await make_container( + container: DockerContainer = await make_container( config, name="aiodocker-testing-attach-nontty-wait-for-exit", ) @@ -265,9 +278,9 @@ async def test_attach_nontty_wait_for_exit(docker, image_name, make_container): @pytest.mark.asyncio -async def test_attach_tty(docker, image_name, make_container): +async def test_attach_tty(docker: Docker, image_name: str, make_container) -> None: skip_windows() - config = { + config: Dict[str, Any] = { "Cmd": ["python", "-q"], "Image": image_name, "AttachStdin": True, @@ -278,7 +291,9 @@ async def test_attach_tty(docker, image_name, make_container): "StdinOnce": False, } - container = await make_container(config, name="aiodocker-testing-attach-tty") + container: DockerContainer = await make_container( + config, name="aiodocker-testing-attach-tty" + ) async with container.attach(stdin=True, stdout=True, stderr=True) as stream: await container.resize(w=80, h=25) @@ -301,7 +316,9 @@ async def test_attach_tty(docker, image_name, make_container): @pytest.mark.asyncio -async def test_wait_timeout(docker, testing_images, shell_container): +async def test_wait_timeout( + docker: Docker, testing_images: List[str], shell_container: DockerContainer +) -> None: t1 = datetime.datetime.now() with pytest.raises(asyncio.TimeoutError): await shell_container.wait(timeout=0.5) @@ -311,10 +328,10 @@ async def test_wait_timeout(docker, testing_images, shell_container): @pytest.mark.asyncio -async def test_put_archive(docker, image_name): +async def test_put_archive(docker: Docker, image_name: str) -> None: skip_windows() - config = { + config: Dict[str, Any] = { "Cmd": ["python", "-c", "print(open('tmp/bar/foo.txt').read())"], "Image": image_name, "AttachStdin": False, @@ -331,7 +348,7 @@ async def test_put_archive(docker, image_name): info = tarfile.TarInfo(name="bar") info.type = tarfile.DIRTYPE info.mode = 0o755 - info.mtime = time.time() + info.mtime = int(time.time()) tar.addfile(tarinfo=info) tarinfo = tarfile.TarInfo(name="bar/foo.txt") @@ -353,10 +370,10 @@ async def test_put_archive(docker, image_name): @pytest.mark.asyncio -async def test_get_archive(image_name, make_container): +async def test_get_archive(image_name: str, make_container) -> None: skip_windows() - config = { + config: Dict[str, Any] = { "Cmd": [ "python", "-c", @@ -370,7 +387,7 @@ async def test_get_archive(image_name, make_container): "OpenStdin": False, } - container = await make_container( + container: DockerContainer = await make_container( config=config, name="aiodocker-testing-get-archive" ) await container.start() @@ -378,8 +395,9 @@ async def test_get_archive(image_name, make_container): tar_archive = await container.get_archive("tmp/foo.txt") assert tar_archive is not None - assert len(tar_archive.members) == 1 + assert len(tar_archive.getmembers()) == 1 foo_file = tar_archive.extractfile("foo.txt") + assert foo_file is not None assert foo_file.read() == b"test\n" @@ -387,8 +405,8 @@ async def test_get_archive(image_name, make_container): @pytest.mark.skipif( sys.platform == "win32", reason="Port is not exposed on Windows by some reason" ) -async def test_port(docker, image_name): - config = { +async def test_port(docker: Docker, image_name: str) -> None: + config: Dict[str, Any] = { "Cmd": [ "python", "-c", @@ -415,7 +433,7 @@ async def test_port(docker, image_name): @pytest.mark.asyncio -async def test_events(docker, image_name): +async def test_events(docker: Docker, image_name: str) -> None: # Сheck the stop procedure docker.events.subscribe() await docker.events.stop() @@ -423,7 +441,7 @@ async def test_events(docker, image_name): subscriber = docker.events.subscribe() # Do some stuffs to generate events. - config = {"Cmd": ["python"], "Image": image_name} + config: Dict[str, Any] = {"Cmd": ["python"], "Image": image_name} container = await docker.containers.create_or_replace( config=config, name="aiodocker-testing-temp" ) diff --git a/tests/test_networks.py b/tests/test_networks.py index 8a9c6905..0d9cd6dc 100644 --- a/tests/test_networks.py +++ b/tests/test_networks.py @@ -1,10 +1,14 @@ +from __future__ import annotations + import pytest -import aiodocker +from aiodocker.docker import Docker +from aiodocker.exceptions import DockerError +from aiodocker.networks import DockerNetwork @pytest.mark.asyncio -async def test_list_networks(docker): +async def test_list_networks(docker: Docker) -> None: data = await docker.networks.list() networks = {net["Name"]: net for net in data} assert "none" in networks @@ -12,7 +16,7 @@ async def test_list_networks(docker): @pytest.mark.asyncio -async def test_list_networks_with_filter(docker): +async def test_list_networks_with_filter(docker: Docker) -> None: network = await docker.networks.create({ "Name": "test-net-filter", "Labels": {"some": "label"}, @@ -27,11 +31,11 @@ async def test_list_networks_with_filter(docker): @pytest.mark.asyncio -async def test_networks(docker): +async def test_networks(docker: Docker) -> None: network = await docker.networks.create({"Name": "test-net"}) net_find = await docker.networks.get("test-net") assert (await net_find.show())["Name"] == "test-net" - assert isinstance(network, aiodocker.networks.DockerNetwork) + assert isinstance(network, DockerNetwork) data = await network.show() assert data["Name"] == "test-net" container = None @@ -47,8 +51,8 @@ async def test_networks(docker): @pytest.mark.asyncio -async def test_network_delete_error(docker): +async def test_network_delete_error(docker: Docker) -> None: network = await docker.networks.create({"Name": "test-delete-net"}) assert await network.delete() is True - with pytest.raises(aiodocker.exceptions.DockerError): + with pytest.raises(DockerError): await network.delete() diff --git a/tests/test_system.py b/tests/test_system.py index 9408ed94..43835f0d 100644 --- a/tests/test_system.py +++ b/tests/test_system.py @@ -1,8 +1,10 @@ import pytest +from aiodocker.docker import Docker + @pytest.mark.asyncio -async def test_system_info(docker): +async def test_system_info(docker: Docker) -> None: docker_info = await docker.system.info() assert "ID" in docker_info assert "ServerVersion" in docker_info diff --git a/tests/test_utils.py b/tests/test_utils.py index 886b0a49..343a5bf0 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,18 +1,21 @@ +from __future__ import annotations + import json +from typing import Any, Dict, Sequence import pytest from aiodocker import utils -def test_clean_mapping(): - dirty_dict = {"a": None, "b": {}, "c": [], "d": 1} - clean_dict = {"b": {}, "c": [], "d": 1} +def test_clean_mapping() -> None: + dirty_dict: Dict[Any, Any] = {"a": None, "b": {}, "c": [], "d": 1} + clean_dict: Dict[Any, Any] = {"b": {}, "c": [], "d": 1} result = utils.clean_map(dirty_dict) assert result == clean_dict -def test_parse_content_type(): +def test_parse_content_type() -> None: ct = "text/plain" mt, st, opts = utils.parse_content_type(ct) assert mt == "text" @@ -36,22 +39,14 @@ def test_parse_content_type(): mt, st, opts = utils.parse_content_type(ct) -def test_format_env(): - key = "name" - value = "hello" - assert utils.format_env(key, value) == "name=hello" - - key = "name" - value = None - assert utils.format_env(key, value) == "name" +def test_format_env() -> None: + assert utils.format_env("name", "hello") == "name=hello" + assert utils.format_env("name", None) == "name" + assert utils.format_env("name", b"hello") == "name=hello" - key = "name" - value = b"hello" - assert utils.format_env(key, value) == "name=hello" - -def test_clean_networks(): - networks = [] +def test_clean_networks() -> None: + networks: Sequence[str] = [] assert utils.clean_networks(networks) == [] networks = ("test-network-1", "test-network-2") @@ -64,11 +59,11 @@ def test_clean_networks(): assert utils.clean_networks(networks) == result -def test_clean_filters(): +def test_clean_filters() -> None: filters = {"a": ["1", "2", "3", "4"], "b": "string"} result = {"a": ["1", "2", "3", "4"], "b": ["string"]} assert utils.clean_filters(filters=filters) == json.dumps(result) - filters = () + filters = {} result = {"a": ["1", "2", "3", "4"], "b": ["string"]} - utils.clean_filters(filters=filters) == json.dumps(result) + assert utils.clean_filters(filters=filters) == json.dumps(result) diff --git a/tests/test_volumes.py b/tests/test_volumes.py index 72e447d5..d1ca5419 100644 --- a/tests/test_volumes.py +++ b/tests/test_volumes.py @@ -1,10 +1,11 @@ import pytest -import aiodocker +from aiodocker.docker import Docker +from aiodocker.exceptions import DockerError @pytest.mark.asyncio -async def test_create_search_get_delete(docker): +async def test_create_search_get_delete(docker: Docker) -> None: name = "aiodocker-test-volume-two" await docker.volumes.create({ "Name": name, @@ -17,13 +18,13 @@ async def test_create_search_get_delete(docker): volume_data = volumes[0] volume = await docker.volumes.get(volume_data["Name"]) await volume.delete() - with pytest.raises(aiodocker.exceptions.DockerError): + with pytest.raises(DockerError): await docker.volumes.get(name) @pytest.mark.asyncio @pytest.mark.parametrize("force_delete", [True, False]) -async def test_create_show_delete_volume(docker, force_delete): +async def test_create_show_delete_volume(docker: Docker, force_delete: bool) -> None: name = "aiodocker-test-volume" volume = await docker.volumes.create({ "Name": name, @@ -34,5 +35,5 @@ async def test_create_show_delete_volume(docker, force_delete): data = await volume.show() assert data await volume.delete(force_delete) - with pytest.raises(aiodocker.exceptions.DockerError): + with pytest.raises(DockerError): await docker.volumes.get(name)