pytest shells

This commit is contained in:
Jörn-Michael Miehe 2021-10-15 19:39:14 +02:00
parent 8a28730954
commit 243fee3f23
2 changed files with 150 additions and 28 deletions

View file

@ -48,7 +48,7 @@ class _Project(BaseModel):
@root_validator(pre=True) @root_validator(pre=True)
@classmethod @classmethod
def unify_project(cls, values): def unify_project(cls, values) -> Dict[str, Any]:
"""parse different project notations""" """parse different project notations"""
if "name" in values: if "name" in values:
@ -91,7 +91,7 @@ class Config(BaseModel):
version: constr(regex=RE_SEMVER) = "0.2.0" version: constr(regex=RE_SEMVER) = "0.2.0"
shells: Optional[List[Path]] = [ shells: List[Path] = [
Path("/bin/bash"), Path("/bin/bash"),
] ]
@ -152,9 +152,32 @@ class Config(BaseModel):
return yml_string return yml_string
@validator("shells", pre=True)
@classmethod
def unify_shells(cls, value) -> List[str]:
"""parse different shells notations"""
if value is None:
return []
elif isinstance(value, list):
return value
elif isinstance(value, dict):
return list(value)
else:
# any other format (try to coerce to str first)
try:
return [str(value)]
except Exception as e:
# undefined format
raise ValueError("Invalid Shells Format")
@validator("projects", pre=True) @validator("projects", pre=True)
@classmethod @classmethod
def unify_projects(cls, value): def unify_projects(cls, value) -> List[Dict[str, str]]:
"""parse different projects notations""" """parse different projects notations"""
if value is None: if value is None:
@ -173,8 +196,13 @@ class Config(BaseModel):
result.append(entry) result.append(entry)
else: else:
# handle single project name try:
result.append({"name": str(entry)}) # handle single project name
result.append({"name": str(entry)})
except Exception as e:
# undefined format
raise ValueError("Invalid Projects Format")
return result return result
@ -183,8 +211,14 @@ class Config(BaseModel):
return [value] return [value]
else: else:
# handle single project name # any other format (try to coerce to str first)
return [{"name": str(value)}] try:
# handle as a single project name
return [{"name": str(value)}]
except Exception as e:
# undefined format
raise ValueError("Invalid Projects Format")
@validator("environment", pre=True) @validator("environment", pre=True)
@classmethod @classmethod
@ -215,20 +249,20 @@ class Config(BaseModel):
result: Dict[str, Optional[str]] = {} result: Dict[str, Optional[str]] = {}
for item in value: for item in value:
key, value = parse_str(str(item)) try:
result[key] = value key, value = parse_str(str(item))
result[key] = value
except Exception as e:
# undefined format
raise ValueError("Invalid Environment Format")
return result return result
elif isinstance(value, str):
# string format (single variable):
# "<var>=<value>"
key, value = parse_str(value)
return {key: value}
else: else:
# any other format (try to coerce to str first) # any other format (try to coerce to str first)
# string format (single variable):
# "<var>=<value>"
try: try:
key, value = parse_str(str(value)) key, value = parse_str(str(value))
return {key: value} return {key: value}

View file

@ -8,6 +8,12 @@ from pydantic import ValidationError
from kiwi_scp.config import Config from kiwi_scp.config import Config
class UnCoercible:
"""A class that doesn't have a string representation"""
def __str__(self):
raise ValueError
def test_default(): def test_default():
c = Config() c = Config()
version = toml.load("./pyproject.toml")["tool"]["poetry"]["version"] version = toml.load("./pyproject.toml")["tool"]["poetry"]["version"]
@ -22,6 +28,70 @@ def test_default():
assert c.network.cidr == IPv4Network("10.22.46.0/24") assert c.network.cidr == IPv4Network("10.22.46.0/24")
########
# SHELLS
########
def test_shells_empty():
c = Config(shells=None)
assert c == Config(shells=[])
assert c.shells == []
def test_shells_list():
c = Config(shells=["/bin/sh", "sh"])
assert len(c.shells) == 2
assert c.shells[0] == Path("/bin/sh")
assert c.shells[1] == Path("sh")
c = Config(shells=["/bin/bash"])
assert len(c.shells) == 1
assert c.shells[0] == Path("/bin/bash")
def test_shells_dict():
c = Config(shells={"/bin/bash": None})
assert len(c.shells) == 1
assert c.shells[0] == Path("/bin/bash")
def test_shells_coercible():
c = Config(shells="/bin/bash")
assert c == Config(shells=Path("/bin/bash"))
assert len(c.shells) == 1
assert c.shells[0] == Path("/bin/bash")
c = Config(shells=123)
assert len(c.shells) == 1
assert c.shells[0] == Path("123")
def test_shells_uncoercible():
with pytest.raises(ValidationError) as exc_info:
Config(shells=UnCoercible())
assert len(exc_info.value.errors()) == 1
error = exc_info.value.errors()[0]
assert error["msg"] == "Invalid Shells Format"
assert error["type"] == "value_error"
with pytest.raises(ValidationError) as exc_info:
Config(shells=["/bin/bash", UnCoercible()])
assert len(exc_info.value.errors()) == 1
error = exc_info.value.errors()[0]
assert error["msg"] == "value is not a valid path"
assert error["type"] == "type_error.path"
########## ##########
# PROJECTS # PROJECTS
########## ##########
@ -29,9 +99,7 @@ def test_default():
def test_proj_empty(): def test_proj_empty():
c = Config(projects=None) c = Config(projects=None)
assert c.projects == [] assert c == Config(projects=[])
c = Config(projects=[])
assert c.projects == [] assert c.projects == []
@ -75,7 +143,7 @@ def test_proj_dict():
assert p.override_storage is None assert p.override_storage is None
def test_proj_name(): def test_proj_coercible():
c = Config(projects="project") c = Config(projects="project")
assert c == Config(projects=["project"]) assert c == Config(projects=["project"])
@ -87,6 +155,24 @@ def test_proj_name():
assert p.override_storage is None assert p.override_storage is None
def test_proj_uncoercible():
with pytest.raises(ValidationError) as exc_info:
Config(projects=["valid", UnCoercible()])
assert len(exc_info.value.errors()) == 1
error = exc_info.value.errors()[0]
assert error["msg"] == "Invalid Projects Format"
assert error["type"] == "value_error"
with pytest.raises(ValidationError) as exc_info:
Config(projects=UnCoercible())
assert len(exc_info.value.errors()) == 1
error = exc_info.value.errors()[0]
assert error["msg"] == "Invalid Projects Format"
assert error["type"] == "value_error"
############# #############
# ENVIRONMENT # ENVIRONMENT
############# #############
@ -139,7 +225,7 @@ def test_env_list():
assert c.environment["123"] is None assert c.environment["123"] is None
def test_env_str(): def test_env_coercible():
c = Config(environment="variable=value") c = Config(environment="variable=value")
assert len(c.environment) == 1 assert len(c.environment) == 1
@ -152,8 +238,6 @@ def test_env_str():
assert "variable" in c.environment assert "variable" in c.environment
assert c.environment["variable"] is None assert c.environment["variable"] is None
def test_env_coercible():
c = Config(environment=123) c = Config(environment=123)
assert len(c.environment) == 1 assert len(c.environment) == 1
@ -167,11 +251,7 @@ def test_env_coercible():
assert c.environment["123.4"] is None assert c.environment["123.4"] is None
def test_env_undef(): def test_env_uncoercible():
class UnCoercible:
def __str__(self):
raise ValueError
with pytest.raises(ValidationError) as exc_info: with pytest.raises(ValidationError) as exc_info:
Config(environment=UnCoercible()) Config(environment=UnCoercible())
@ -179,3 +259,11 @@ def test_env_undef():
error = exc_info.value.errors()[0] error = exc_info.value.errors()[0]
assert error["msg"] == "Invalid Environment Format" assert error["msg"] == "Invalid Environment Format"
assert error["type"] == "value_error" assert error["type"] == "value_error"
with pytest.raises(ValidationError) as exc_info:
Config(environment=["valid", UnCoercible()])
assert len(exc_info.value.errors()) == 1
error = exc_info.value.errors()[0]
assert error["msg"] == "Invalid Environment Format"
assert error["type"] == "value_error"