Deepwalker / trafaret

Ultimate transformation library that supports validation, contexts and aiohttp.
http://trafaret.readthedocs.org/en/latest/
BSD 2-Clause "Simplified" License
177 stars 31 forks source link

Using function to validate username #105

Open Dreamsorcerer opened 4 years ago

Dreamsorcerer commented 4 years ago

I couldn't find an example of this in the documentation, so is this the expected way to run a function to validate a value?

    def check_if_user_exists(username):
        if username == "reserved":
            raise t.DataError("Username already exists")
        return username
    signup_form = t.Dict({
        "username": t.String() & check_if_user_exists,
        "password": t.String()
    })

As an extension to that, is it possible to support async functions in some way? So, that code might end up looking like:

    async def check_if_user_exists(username):
        with db.connect() as conn:
            result = await conn.scalar(users.count().where(users.username == username))
        if result is not None:
            raise t.DataError("Username already exists")
        return username
    signup_form = t.Dict({
        "username": t.String() & t.Await(check_if_user_exists),
        "password": t.String()
    })
Dreamsorcerer commented 4 years ago

OK, answer to second question is await signup_form.async_check(), which doesn't appear in the documentation, but found it in the source code.

Dreamsorcerer commented 4 years ago

Worth noting however, that subdict(trafaret=func) does not use async.

Deepwalker commented 4 years ago

subdict is a function. We need to implement async_subdict then

Deepwalker commented 4 years ago

It was not documented possible because no one was really interested in async version.

Dreamsorcerer commented 4 years ago

Well, I found this project as it was being used in some aiohttp demos, so I'm probably not the only one.

Deepwalker commented 4 years ago

Yes, but if you use trafaret for sanitising of input data then you will not need to call anything asynchronously. But of course if you need to make query to database, then you will need async version. That was my thought when I added async to trafaret. So, we probably need to update documentation then. BTW we have context argument, so you can place application object here for some deeply nested trafarets.

Dreamsorcerer commented 4 years ago

Yes, in fact that's exactly what I've done. I pass the request object through as the context.