-
-
Notifications
You must be signed in to change notification settings - Fork 94
feat(fields): implement Param and CallableParam for handling unmapped parameters that can be referenced during build #650
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
base: main
Are you sure you want to change the base?
Conversation
… parameters that can be referenced during build
…ew Param and CallableParam field types
@adhtruong, I have an update ready to update this pull request, but after merging with main, I am encountering issues realted to some typing related to SQLAlchemy factories. Please let me know how you want me to proceed (wait for patch, submit anyways, or something else). Here's what I'm seeing:
|
…ith older versions of python
…s versions of python
@adhtruong Interestingly, when I ran pre-commit separately, it raised the mypy errors, but when it ran as part of the git hook, it passed. Not sure what is happening there. Anyways, here is the updated feature we have been discussing. Thank you for your patience as I reworked it. From our conversation, I did a little thinking, and I decided to alter the API just slightly from what we discussed. Instead of including a I needed a way to understand if the user's intention is to call the passed value (for example passing a lambda that they might not want to be called) but also override that value at build time and still have the same action (call it or not). I didn't want the user to have to pass a temporary placeholder value for the param at factory definition time (just to minimize the amount of code needed to use the feature) so we could understand their intention related to calling or not calling the passed value. So I figured asking with the boolean option would be a simpler interface for the user. Thanks again for your review and feedback! |
What is the use case of requiring the kwargs from the factory field itself passed to a callable declared at build time? This feels like quite a specific use case that inclined to push to user itself rather as feels niche in the current form. Is this with the intention to have params passed to other params or could the use case describing be supported like that so if more similar to existing code base This is compared |
@adhtruong I'm sorry if I didn't explain myself accurately, but the kwargs that get passed to the callable can only be passed during the declaration of the factory, not at build time. I thought there was too much potential for collision between kwarg names and factory field names to attempt to handle passing kwargs at build time. Essentially, there are two routes:
I thought it made sense, from the viewpoint of API consistency, that if we allow overriding Also, like I mentioned previously, the reason for using an |
@adhtruong @guacs let me know if I can clarify or respond on this any further or how you want to proceed. Thanks! |
Hey @leverage-analytics , sorry the late reply on this! I think the callable use case may be a little confusing as doesn't link the params of kwargs closely to the calllable passed in a build time. I think just having the whole value overriding is fine and keeps overall design simpler. This matches the existing interface of other fields closer e.g. if If there is a strong use case for this kind of overriding, then have the original form of separate field types for callable and not makes this difference more clear so usage if consistent at field level. |
@adhtruong thanks for the feedback! As I see it, our options are:
Like I said, I'd prefer the first, but I'm open to supporting the project how the maintainers see best. Thanks! |
Just to clarify 1. Would this would looks like class Param:
def __init__(self, default: T, default_factory: Callable[[], T)-> None: ...
class Factory(DataclassFactory[MyType]):
a = Param(default_factory=lambda: 1)
assert Factory.build(a=2).a == 2. # would this error?
assert Factory.build(a=lambda: 2) == lambda: 2 # would this get evaluated? For 3 use case, would this be covered via |
@adhtruong answered based on my proposal class Factory(DataclassFactory[MyType]):
a = Param(default_factory=lambda: 1)
# This example results in an attribute error because no parameter values get mapped
# into the objects produced by the factory (assuming MyType doesn't have attribute 'a').
assert Factory.build(a=2).a == 2.
# In the following case, the expression lambda: 2 would be evaluated during build
# because the user specific a default_factory for the`Param`.
assert Factory.build(a=lambda: 2) |
Documentation preview will be available shortly at https://litestar-org.github.io/polyfactory-docs-preview/650 |
Thanks again for clarifying. Appreciate the patience on back and forth and explaining to help me understand! I think 3 makes is my preference as most in line with existing fields and result can be achieved by user with
I think can make a minor tweak (commented in line) to make this work for coverage form too |
This completes the development and testing related to #604.
process_kwargs
andprocess_kwargs_coverage
. A new helper method was used to determine which fields in a factory are Unmapped types (Params or CallableParam)