+def blank(value: T.AnyStr) -> None:
+ """Check that value is an empty or blank string."""
+ if not isinstance(value, str) or value.strip():
+ raise ValueError(f'expected "{value!r}" to be a blank string')
+
+
+def port(value: int) -> None:
+ """Check that value resembles a port."""
+ if not isinstance(value, int) or value < 1 or value > 65535:
+ raise ValueError(f'expected "{value}" to be be a port')
+
+
def equals(expected: Val, actual: Val) -> None:
"""Check that the two values are equal."""
if expected != actual:
def equals(expected: Val, actual: Val) -> None:
"""Check that the two values are equal."""
if expected != actual:
def in_range(value: Num, gte: Num, lte: Num) -> None:
"""Check that value lies in the range [min, max]."""
if not gte >= value >= lte:
raise ValueError(f"value {value} must be between {gte} and {lte}")
def in_range(value: Num, gte: Num, lte: Num) -> None:
"""Check that value lies in the range [min, max]."""
if not gte >= value >= lte:
raise ValueError(f"value {value} must be between {gte} and {lte}")
+def lines(text: T.AnyStr, num: int) -> None:
+ """Check that text splits into `num` lines."""
+ rows = text.splitlines()
+ if len(rows) != num:
+ raise ValueError(f"expected {num} lines, got {len(rows)}: {rows}")
+
+
def is_in(needle: Val, *haystacks: T.Container[Val]) -> None:
"""Check that at least one haystack includes needle."""
for haystack in haystacks:
def is_in(needle: Val, *haystacks: T.Container[Val]) -> None:
"""Check that at least one haystack includes needle."""
for haystack in haystacks:
+
+
+def file_exists(path: T.Union[str, Path]) -> None:
+ """Check that file or directory exists."""
+ if not os.path.exists(path):
+ raise ValueError("expected path '{path}' to exist")