-
Notifications
You must be signed in to change notification settings - Fork 1
Make validate_params work with the function's parametters instead of a dict #30
Comments
Credit for this idea goes to @JulienPalard |
I'd add: choose another name for this decorator. Both for backward compatibility and to try to stuff more meaning in it? |
@JulienPalard that's a good idea, do you have any recommendations ? :) I was thinking |
I think I might have an idea on how to accomplish this ngl. |
Yes there are ! See the tests folder, they run with Check the readme (I think I detailed it here) or the contributing file and if it's not detailed let me know and I'll add it |
Alright thanks 👍 @validate_params
def example(name: str, age: int, is_student: bool, courses: List[str], grades: Dict[str, int]):
... Would the arguments |
Also I seem to be running into some issues using tox to run the tests, but I can run them fine with pytest. |
No worries if your tests work with pytest they should work with tox. FYI tox is a utility that allows you to run commands with multiple environments, and in this case it allows me to run the tests (pytest) for python 3.8 up to 3.12 for many versions of flask ! |
As for your question about the function, it's a little more complicated than that. Flask can also inject some variables in the function when using slugs (for example https://stackoverflow.com/a/40460690) And then we want to validate the JSON (and maybe one day form data) params that would be inputted along the potentials slugs (Sorry I'm on my phone I can't give you a better example right now) |
@all-contributors please add @JulienPalard for ideas |
I've put up a pull request to add @JulienPalard! 🎉 |
@Mews let me know if you have more questions for this :) |
Oh yeah sorry I still do plan on contributing to this issue I was just busy with something else. |
No worries, take your time :)
Yes there is :) Because of the way flask work, there already are args and kwargs to the function so we need to pass them along :) |
Okay and the name, age etc arguments should also be passed to the function yes? |
Probably yes. Try it and we'll see once you get the PR I'll test it and see if it does what I imagine :) |
Okay, but I'll probably need to change the tests too right? To use the new syntax you proposed |
Yes that's correct ! But don't worry too much about tests and documentation for now, at least not before we validated it does what we want |
Also, taking a look at the tests I found this: # Not a valid type hint
def example(name: (str, int)):
etc... Python does evaluate it but it's not a very good way to do it. You could probably expand the elif origin is tuple:
if not isinstance(value, tuple) or len(value) != len(args):
return False
return all(
_check_type(item, arg, allow_empty, (curr_depth + 1)) for item, arg in zip(value, args)
) Where we check if a tuple was passed, if the tuple has the correct amount of elements, and if the elements of the tuple match the types declared inside |
Also I have a question about a test that's being ran, here: flask-utils/tests/test_validate_params.py Lines 243 to 256 in 3ec12cf
Maybe I'm wrong, but in test_valid_request aren't you passing a string, which would be an invalid type?Feels like it should be like: class TestTupleUnion:
@pytest.fixture(autouse=True)
def setup_routes(self, flask_client):
@flask_client.post("/tuple-union")
@validate_params({"name": (str, int)})
def union():
return "OK", 200
def test_valid_request(self, client):
response = client.post("/tuple-union", json={"name":("this is a string", 123)})
assert response.status_code == 200 Still, as far as I can tell, the |
Sorry for spamming this thread but I've began implementing a few of the changes necessary and I have a question related to pull requests and stuff. I'm making many changes on the same file, on many parts of the code. |
My point of view for this is: each commit should work. Or not break the whole project. Read: tests shall pass. Idea is that I see Another more distant argument is: is someone want to use I also abuse of An approach that is slowly maturing in me is to write the commit message before doing the work, it's a clean way to delimit the task to be done AND to write good commit messages, let's call it "commit message driven development". |
Alright that makes sense I guess. |
Hi @Seluj78 for key in data:
kwargs[key] = data[key]
return fn(*args, **kwargs) However, this causes an obvious issue, which is that if a parameter is optional and is not present in I was thinking you could get around this by doing: for key in parameters:
if _is_optional(parameters[key]) and key not in data:
kwargs[key] = None
else:
kwargs[key] = data[key] So, when an optional parameter isn't passed in the json, it gets passed to the function as |
What about making optional arguments optional in the prototype too? àla : @validate_params
def example(name: str, age : Optional[int] = None):
... |
Yeah that's the same as what my example does, but the user doesn't need to type |
for key in data: kwargs[key] = data[key] I don't have the context, but please take extra care (by adding a test or two) of not having a query string argument clobbered by a value from the request body. I mean (I'm no flask user forgive inconsistencies):
If someone sends:
I except to get |
I mean I'm not a flask expert either, that's why I asked @Seluj78 if the way I was doing it wasn't gonna cause issues. I guess we'll have to wait until he responds. |
(I'm not dead, just was really busy these past few days. I will respond ASAP, probably tomorrow) |
No worries haha |
For the tuple and union question, I do agree with you. We shouldn't allow the usage of # Not a valid type hint
def example(name: (str, int)):
etc... What we can probably do, I don't know how though, is raise a DeprecationWarning when we see this usage. As for the choice between Tuple and Union, I agree with you. For your question about the So the test should test for As for the commit messages question, I agree with Julien. I also do try to keep my commit messages clean and each commit working when I can ! Do let me know if you have more questions. In any case I will test your PR and code once you have it pushed so we can check stuff together. |
I was looking into that test and I think I interpreted what its for incorrectly lol. My proposal for allowing validating tuples still stands though and I'd be happy to introduce it too :) |
Works for me ! |
Instead of having
It would make more sense to have the decorator read the function arguments directly like so :
/!\ One attention point is to see how Flask interacts with the function and where it places it's variables when doing a function with some kind of slug (
@app.route("/users/<user_id>")
)The text was updated successfully, but these errors were encountered: