Skip to content

Commit

Permalink
remove min_size option and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Fredrik Borg committed Aug 24, 2023
1 parent c785ceb commit 70ec862
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 37 deletions.
5 changes: 3 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ repos:
language: python
entry: mypy
types: [python]
additional_dependencies: ["mypy==1.4.0", "pydantic", "pytest", "types-setuptools"]
args: ["--strict", "--install-types", "--non-interactive"]
args: [".", "--strict"]
pass_filenames: false
always_run: true

- repo: local
hooks:
Expand Down
14 changes: 1 addition & 13 deletions caep/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,12 @@ class FieldError(Exception):
class ArrayInfo(BaseModel):
array_type: type
split: str = DEFAULT_SPLIT
min_size: int = 0


class DictInfo(BaseModel):
dict_type: type
split: str = DEFAULT_SPLIT
kv_split: str = DEFAULT_KV_SPLIT
min_size: int = 0


Arrays = Dict[str, ArrayInfo]
Expand Down Expand Up @@ -96,11 +94,6 @@ def split_dict(

d[key.strip()] = dict_info.dict_type(val.strip())

if len(d.keys()) < dict_info.min_size:
raise FieldError(
f"{field} have to few elements {len(d)} < {dict_info.min_size}"
)

return d


Expand All @@ -119,9 +112,6 @@ def split_list(value: str, array: ArrayInfo, field: Optional[str] = None) -> Lis
# Split by configured split value, unless it is escaped
lst = [array.array_type(v.strip()) for v in escape_split(value, array.split)]

if len(lst) < array.min_size:
raise FieldError(f"{field} have to few elements {len(lst)} < {array.min_size}")

return lst


Expand Down Expand Up @@ -268,7 +258,6 @@ def build_parser(
arrays[field] = ArrayInfo(
array_type=array_type,
split=schema.get("split", DEFAULT_SPLIT),
min_size=schema.get("min_size", 0),
)

# For arrays (lists, sets etc), we parse as str in caep and split values by
Expand All @@ -287,7 +276,6 @@ def build_parser(
dict_type=dict_type,
split=schema.get("split", DEFAULT_SPLIT),
kv_split=schema.get("kv_split", DEFAULT_KV_SPLIT),
min_size=schema.get("min_size", 0),
)

else:
Expand Down Expand Up @@ -365,7 +353,7 @@ def load(
# `model_json_schema` in pydantic 2.x.

if PYDANTIC_MAJOR_VERSION == "2":
fields = model.model_json_schema(alias).get("properties") # type: ignore
fields = model.model_json_schema(alias).get("properties")
else:
fields = model.schema(alias).get("properties")

Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from os import path

from setuptools import setup
from setuptools import setup # type: ignore

# read the contents of your README file
this_directory = path.abspath(path.dirname(__file__))
Expand All @@ -11,7 +11,7 @@

setup(
name="caep",
version="1.0.0b1",
version="1.0.0",
author="mnemonic AS",
zip_safe=True,
author_email="[email protected]",
Expand All @@ -31,6 +31,7 @@
"dev": [
"mypy",
"pytest",
"types-setuptools",
]
},
classifiers=[
Expand Down
14 changes: 8 additions & 6 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import shlex
from pathlib import Path
from typing import Any, Dict, List, Optional
from typing import List, Optional

import pytest
from pydantic import BaseModel # noqa: E0611
from pydantic import Field, root_validator
from pydantic import Field, model_validator
from test_schema import parse_args

import caep
Expand All @@ -19,13 +19,15 @@ class ExampleConfig(BaseModel):
password: Optional[str] = Field(description="Password")
parent_id: Optional[str] = Field(description="Parent ID")

@root_validator(skip_on_failure=True)
def check_arguments(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@model_validator(mode="after") # type: ignore
def check_arguments(cls, m: "ExampleConfig") -> "ExampleConfig":
"""If one argument is set, they should all be set"""

caep.raise_if_some_and_not_all(values, ["username", "password", "parent_id"])
caep.raise_if_some_and_not_all(
m.__dict__, ["username", "password", "parent_id"]
)

return values
return m


def test_config_files() -> None:
Expand Down
54 changes: 40 additions & 14 deletions tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,23 @@ class Arguments(BaseModel):
float_arg: float = Field(default=0.5, description="Float with default value")

# List fields will be separated by space as default
intlist: List[int] = Field(description="Space separated list of ints", split=" ")
intlist: List[int] = Field(
description="Space separated list of ints", json_schema_extra={"split": " "}
)

# Can optionally use "split" argument to use another value to split based on
strlist: List[str] = Field(description="Comma separated list of strings")

# Set that will be separated by space (default)
strset: Set[str] = Field(description="Space separated set of strings", split=" ")
strset: Set[str] = Field(
description="Space separated set of strings", json_schema_extra={"split": " "}
)

dict_str: Dict[str, str] = Field(description="Str Dict split by comma and colon")

dict_int: Dict[str, int] = Field(
description="Int Dict split by slash and dash", split="-", kv_split="/"
description="Int Dict split by slash and dash",
json_schema_extra={"split": "-", "kv_split": "/"},
)

ipv4: Optional[ipaddress.IPv4Address] = Field(description="IPv4 Address")
Expand All @@ -56,7 +61,7 @@ class Arguments(BaseModel):


class ArgNs2(BaseModel):
str_arg: str = Field(value="Unset", description="String argument")
str_arg: str = Field("Unset", description="String argument")


class ArgNs1(BaseModel):
Expand All @@ -81,6 +86,16 @@ class MultipleFiles(BaseModel):
second_file: bool = Field(description="Value set in second config file")


class MinLength(BaseModel):
# Can optionally use "split" argument to use another value to split based on
strlist: List[str] = Field(
description="Comma separated list of strings", min_length=1
)
dict_str: Dict[str, str] = Field(
description="Str Dict split by comma and colon", min_length=2
)


class ArgCombined(Arg1, Arg2, Arg3):
pass

Expand Down Expand Up @@ -196,8 +211,6 @@ def test_schema_commandline_dict_int() -> None:
assert dict_int is not None
assert dict_int is not {}

print(dict_int)

assert dict_int["a"] == 1
assert dict_int["b"] == 2

Expand Down Expand Up @@ -329,6 +342,27 @@ def test_schema_joined_schemas() -> None:
assert config.enabled is True


def test_min_length() -> None:
"""Test schema that is created based on three other schemas"""

with pytest.raises(SystemExit):
parse_args(MinLength, shlex.split("--strlist arg1,arg2"))

with pytest.raises(SystemExit):
parse_args(MinLength, shlex.split("--dict-str a:b,c:d"))

config = parse_args(
MinLength,
shlex.split(
"--strlist arg1 --dict-str 'header 1: x option, header 2: y option'"
),
)

assert config.strlist == ["arg1"]
assert config.dict_str["header 1"] == "x option"
assert config.dict_str["header 2"] == "y option"


def test_escape_split() -> None:
assert escape_split("A\\,B\\,C,1\\,2\\,3") == ["A,B,C", "1,2,3"]
assert escape_split("ABC 123", split=" ") == ["ABC", "123"]
Expand All @@ -344,10 +378,6 @@ def test_split_list() -> None:
# Configure split value
assert split_list("a b c", ArrayInfo(array_type=str, split=" "))

# min_size
with pytest.raises(FieldError):
assert split_list("", ArrayInfo(array_type=str, min_size=1))


def test_split_dict() -> None:
# Defaults
Expand All @@ -357,9 +387,5 @@ def test_split_dict() -> None:

assert d["c"] == "value X"

with pytest.raises(FieldError):
v = split_dict("", DictInfo(dict_type=str, min_size=1))
print(v)

with pytest.raises(FieldError):
split_dict("a,b", DictInfo(dict_type=str))

0 comments on commit 70ec862

Please sign in to comment.