From 1172fa8180c584ba50c315ce712f708fcba9f954 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Wed, 16 Oct 2019 18:46:38 +0000 Subject: [PATCH] [breaking] make config loaders async --- README.md | 4 ++-- tcadmin/tests/test_util_config.py | 36 +++++++++++++++++++------------ tcadmin/util/config.py | 18 ++++++++-------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index a6143379..4c31d435 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ It has a `load` method that will load data, optionally parsing it as YAML: ```python data = loader.load("data.bin") -aliases = loader.load("aliases.yml", parse="yaml") +aliases = await loader.load("aliases.yml", parse="yaml") ``` You can also define your own loader class. @@ -191,7 +191,7 @@ class Workers(ConfigList): bigness = attr.ib(type=int, default=1) ``` -Then simply call `Workers.load(loader)` to load a `workers.yml` that looks something like +Then simply call `await Workers.load(loader)` to load a `workers.yml` that looks something like ```yaml - workerId: small diff --git a/tcadmin/tests/test_util_config.py b/tcadmin/tests/test_util_config.py index bc3984ab..b54e02c0 100644 --- a/tcadmin/tests/test_util_config.py +++ b/tcadmin/tests/test_util_config.py @@ -7,36 +7,42 @@ import os import yaml import attr +import pytest from tcadmin.util.config import ConfigList, ConfigDict, LocalLoader, StaticLoader -def test_local_loader(): +@pytest.mark.asyncio +async def test_local_loader(): dir = os.path.dirname(__file__) loader = LocalLoader(dir) - assert yaml.load(loader.load_raw("testfile.yml")) == {"data": [1, 2]} + assert yaml.load(await loader.load_raw("testfile.yml")) == {"data": [1, 2]} -def test_local_loader_parse(): +@pytest.mark.asyncio +async def test_local_loader_parse(): dir = os.path.dirname(__file__) loader = LocalLoader(dir) - assert loader.load("testfile.yml", parse="yaml") == {"data": [1, 2]} + assert await loader.load("testfile.yml", parse="yaml") == {"data": [1, 2]} -def test_local_loader_no_parse(): +@pytest.mark.asyncio +async def test_local_loader_no_parse(): dir = os.path.dirname(__file__) loader = LocalLoader(dir) - assert yaml.load(loader.load("testfile.yml")) == {"data": [1, 2]} + assert yaml.load(await loader.load("testfile.yml")) == {"data": [1, 2]} -def test_static_loader_yaml(): +@pytest.mark.asyncio +async def test_static_loader_yaml(): loader = StaticLoader({"data.yml": {"foo": "bar"}}) - assert yaml.load(loader.load_raw("data.yml")) == {"foo": "bar"} + assert yaml.load(await loader.load_raw("data.yml")) == {"foo": "bar"} -def test_static_loader_raw(): +@pytest.mark.asyncio +async def test_static_loader_raw(): loader = StaticLoader({"data.bin": b"abcd"}) - assert loader.load_raw("data.bin") == b"abcd" + assert await loader.load_raw("data.bin") == b"abcd" loader = StaticLoader( @@ -68,8 +74,9 @@ def sum_values(self): return sum(i.v for i in self) -def test_config_array(): - kvs = KVs.load(loader) +@pytest.mark.asyncio +async def test_config_array(): + kvs = await KVs.load(loader) assert kvs[0].k == "a" assert kvs[0].v == 1 assert kvs[1].k == "b" @@ -95,6 +102,7 @@ class Item: historical = attr.ib(type=bool, default=False) -def test_config_dict(): - nicks = Nicknames.load(loader) +@pytest.mark.asyncio +async def test_config_dict(): + nicks = await Nicknames.load(loader) assert nicks["Gertie"].fullname == "Gertrude" diff --git a/tcadmin/util/config.py b/tcadmin/util/config.py index 04a9912b..96de1018 100644 --- a/tcadmin/util/config.py +++ b/tcadmin/util/config.py @@ -10,10 +10,10 @@ class Loader(ABC): - def load(self, filename, parse=None): + async def load(self, filename, parse=None): """Load the given file. If parse is `"yaml"` then the content is parsed as YAML; otherwise it is returned as a bytestring.""" - raw = self.load_raw(filename) + raw = await self.load_raw(filename) if parse == "yaml": return yaml.load(raw) elif parse: @@ -21,7 +21,7 @@ def load(self, filename, parse=None): return raw @abstractmethod - def load_raw(self, filename): + async def load_raw(self, filename): pass @@ -29,7 +29,7 @@ class StaticLoader(Loader): def __init__(self, data): self.data = data - def load_raw(self, filename): + async def load_raw(self, filename): raw = self.data[filename] if not isinstance(raw, bytes): return yaml.dump(raw) @@ -40,15 +40,15 @@ class LocalLoader(Loader): def __init__(self, directory="."): self.directory = directory - def load_raw(self, filename): + async def load_raw(self, filename): with open(os.path.join(self.directory, filename), "rb") as f: return f.read() class ConfigList(list): @classmethod - def load(cls, loader): - data = loader.load(cls.filename, parse="yaml") + async def load(cls, loader): + data = await loader.load(cls.filename, parse="yaml") assert isinstance(data, list), "{} is not a YAML array".format(cls.filename) return cls(cls.Item(**cls.transform_item(item)) for item in data) @@ -59,8 +59,8 @@ def transform_item(cls, item): class ConfigDict(dict): @classmethod - def load(cls, loader): - data = loader.load(cls.filename, parse="yaml") + async def load(cls, loader): + data = await loader.load(cls.filename, parse="yaml") assert isinstance(data, dict), "{} is not a YAML object".format(cls.filename) return cls((k, cls.Item(k, **cls.transform_item(v))) for k, v in data.items())