Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to translate string to list #302

Open
NiceRath opened this issue Sep 27, 2023 · 1 comment
Open

How to translate string to list #302

NiceRath opened this issue Sep 27, 2023 · 1 comment

Comments

@NiceRath
Copy link

NiceRath commented Sep 27, 2023

Greetings!

We have the use-case that some values should be translated to lists if only one value is supplied.

Example:

# nameservers: ['192.168.0.1']
Schema({'nameservers': [AND(str, valid_ip)]})
# WORKS

# nameservers: '192.168.0.1'
Schema({'nameservers': [AND(str, valid_ip)]})
# ERROR: "'192.168.0.1' should be instance of 'list'"

Schema({'nameservers': Use(ensure_list)})
# WORKS, will translate to list - but without value validation..

Schema({'nameservers': And(Use(ensure_list), str, valid_ip)})
# ERROR: "['192.168.0.1'] should be instance of 'str'"

# Referenced functions:
from ipaddress import ip_address, IPv4Address, IPv6Address

def valid_ip6(ip: str) -> bool:
    try:
        return type(ip_address(ip)) is IPv6Address

    except ValueError:
        return False


def valid_ip4(ip: str) -> bool:
    try:
        return type(ip_address(ip)) is IPv4Address

    except ValueError:
        return False

def valid_ip(ip: str) -> bool:
    return valid_ip4(ip) or valid_ip6(ip)

def ensure_list(data: (str, list)) -> list:
    if data is None:
        raise ValueError('Got none-value!')

    if not isinstance(data, list):
        data = [data]

    return data

Is there a clean way to validate the return-values that were translated by calling Use()?

As a workaround we can, of course, create a separate Use function for every different use-case. Per example: Use(list_of_ips)

@mutricyl
Copy link

May I suggest the following ?

sch = Schema({
    'nameservers': Or(
        And(str, valid_ip, Use(lambda x: [x])),  # manage list conversion when string is provided
        And([str], lambda x: all([valid_ip(it) for it in x]))  # check that all ip are valid in the list in case of list. Use Const( lambda ... , error='nice error message') to display a usefull error message
    )})

print(sch.validate({'nameservers': ['192.168.0.1']}))
print(sch.validate({'nameservers': ['192.168.0.1', '192.168.0.2']}))
print(sch.validate({'nameservers': '192.168.0.1'}))

Resulting in:

{'nameservers': ['192.168.0.1']}
{'nameservers': ['192.168.0.1', '192.168.0.2']}
{'nameservers': ['192.168.0.1']}

Would it fit your needs ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants