Skip to content

Commit

Permalink
Add wipac_dev_tools.strtobool() [minor] (#40)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <github-actions@github.com>
  • Loading branch information
ric-evans and github-actions committed Aug 26, 2022
1 parent 2e2b186 commit 4fcde91
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 5 deletions.
18 changes: 17 additions & 1 deletion README.md
Expand Up @@ -132,7 +132,7 @@ def from_environment_as_dataclass(
(positional arguments), optional fields with defaults, default
factories, post-init processing, etc.
If a field's type is a bool, `strtobool` is used for typecasting.
If a field's type is a bool, `wipac_dev_tools.strtobool` is applied.
If a field's type is a `list`, `dict`, `set`, `frozenset`, or
an analogous type alias from the 'typing' module, then a conversion
Expand Down Expand Up @@ -205,4 +205,20 @@ def from_environment_as_dataclass(
ValueError - If an indicated value is not a legal value
TypeError - If an argument or indicated value is not a legal type
"""
```

#### `wipac_dev_tools.strtobool()`
```
def strtobool(string: str) -> bool:
"""Smart-cast a string to a bool using common-sense interpretations.
Unlike the since deprecated `distutils.util.strtobool`, this
returns an actual bool.
True: 'y', 'yes', 't', 'true', 'on', '1'
False: 'n', 'no', 'f', 'false', 'off', '0'
Raises:
ValueError: if the string does not match any of the about
"""
```
4 changes: 2 additions & 2 deletions requirements.txt
Expand Up @@ -6,13 +6,13 @@
#
certifi==2022.6.15
# via requests
charset-normalizer==2.1.0
charset-normalizer==2.1.1
# via requests
idna==3.3
# via requests
requests==2.28.1
# via wipac-dev-tools (setup.py)
typing-extensions==4.3.0
# via wipac-dev-tools (setup.py)
urllib3==1.26.10
urllib3==1.26.12
# via requests
47 changes: 47 additions & 0 deletions tests/strtobool_test.py
@@ -0,0 +1,47 @@
"""Test strtobool.py."""


from random import choice

import pytest
from wipac_dev_tools import strtobool


def random_case(string: str) -> str:
"""Randomly capitalize string."""
return "".join(choice((str.upper, str.lower))(c) for c in string)


def test_true() -> None:
"""Test True cases"""
strings = ["y", "yes", "t", "true", "on", "1"]
strings.extend([s.upper() for s in strings])
strings.extend([random_case(s) for s in strings]) # yes, this doubles everything

for string in strings:
val = strtobool(string)
assert isinstance(val, bool)
assert val


def test_false() -> None:
"""Test False cases."""
strings = ["n", "no", "f", "false", "off", "0"]
strings.extend([s.upper() for s in strings])
strings.extend([random_case(s) for s in strings]) # yes, this doubles everything

for string in strings:
val = strtobool(string)
assert isinstance(val, bool)
assert not val


def test_value_error() -> None:
"""Test error cases"""
strings = ["nah", "yup", "", "hmm", "maybe", "offf", "123"]
strings.extend([s.upper() for s in strings])
strings.extend([random_case(s) for s in strings]) # yes, this doubles everything

for string in strings:
with pytest.raises(ValueError, match=rf"Invalid truth value: {string}"):
strtobool(string)
2 changes: 2 additions & 0 deletions wipac_dev_tools/__init__.py
Expand Up @@ -3,12 +3,14 @@
from . import logging_tools
from .enviro_tools import from_environment, from_environment_as_dataclass # noqa
from .setup_tools import SetupShop # noqa
from .strtobool import strtobool

__all__ = [
"from_environment",
"from_environment_as_dataclass",
"SetupShop",
"logging_tools",
"strtobool",
]

# version is a human-readable version number.
Expand Down
5 changes: 3 additions & 2 deletions wipac_dev_tools/enviro_tools.py
Expand Up @@ -4,7 +4,6 @@
import os
import re
import sys
from distutils.util import strtobool
from typing import (
Any,
Dict,
Expand All @@ -18,6 +17,8 @@
cast,
)

from .strtobool import strtobool

try:
from typing import Final
except ImportError:
Expand Down Expand Up @@ -191,7 +192,7 @@ def from_environment_as_dataclass(
(positional arguments), optional fields with defaults, default
factories, post-init processing, etc.
If a field's type is a bool, `strtobool` is used for typecasting.
If a field's type is a bool, `wipac_dev_tools.strtobool` is applied.
If a field's type is a `list`, `dict`, `set`, `frozenset`, or
an analogous type alias from the 'typing' module, then a conversion
Expand Down
21 changes: 21 additions & 0 deletions wipac_dev_tools/strtobool.py
@@ -0,0 +1,21 @@
"""The useful `strtobool()`, originally from the deprecated `distutils.util`."""


def strtobool(string: str) -> bool:
"""Smart-cast a string to a bool using common-sense interpretations.
Unlike the since deprecated `distutils.util.strtobool`, this
returns an actual bool.
True: 'y', 'yes', 't', 'true', 'on', '1'
False: 'n', 'no', 'f', 'false', 'off', '0'
Raises:
ValueError: if the string does not match any of the about
"""
if string.lower() in ("y", "yes", "t", "true", "on", "1"):
return True
elif string.lower() in ("n", "no", "f", "false", "off", "0"):
return False
else:
raise ValueError(f"Invalid truth value: {string}")

0 comments on commit 4fcde91

Please sign in to comment.