-
-
Notifications
You must be signed in to change notification settings - Fork 87
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
[52] Allow string values for foriegn_key
from other modules
#120
[52] Allow string values for foriegn_key
from other modules
#120
Conversation
- This also refactors the `foreign_key` and `RecipeForeignKey` logic slightly to reduce duplicate code for loading `Recipe` objects from other modules.
- Fix lint issues, clean up imports
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR is great @timjklein36! Thanks again for contributing to the project.
I left a comment about an existing helper function to handle string imports. I'd like to know if you have time to take a lookt at it and to check if it's possible to refactor your PR to use it instead of adding new import strategies.
def get_calling_module(levels_back: int) -> Optional[ModuleType]: | ||
"""Get the module some number of stack frames back from the current one. | ||
|
||
Make sure to account for the number of frames between the "calling" code | ||
and the one that calls this function. | ||
|
||
Args: | ||
levels_back (int): Number of stack frames back from the current | ||
|
||
Returns: | ||
(ModuleType): the module from which the code was called | ||
""" | ||
frame = inspect.stack()[levels_back + 1][0] | ||
return inspect.getmodule(frame) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a function in utils.py
named import_from_str
. It's used by baker.make
or baker.prepare
to work with string paths instead of model classes.
This PR looks great and it definitely makes bakery more stable in terms of its external API. But I wonder if we could re-use the previous import function instead of defining new strategies to import models based on strings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this functionality was already present in the import logic of RecipeForeignKey
and of related
. I simply extracted it out into a re-usable function.
I personally think the logic here (using stack frames to get the module from which the code was called) is a bit fragile, but it was already the way it was implemented so I left it alone (aside from pulling it into its own function to avoid duplication).
I am definitely open to alternatives, if you think there is a better way to access the "calling module" and its attributes. Just let me know what you think, and I will update the code. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For context, I did re-use the baker._recipe
import function (which calls import_from_str
) for the new logic that I added, however, I left the "import from calling module" logic as a fallback (to maintain existing use of the foreign_key
function).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@berinhard Please let me know if there is a way to facilitate loading a recipe from the module that called foreign_key
that can re-use any existing function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timjklein36 sorry I didn't have the time to properly review this last week. But I'll do so today and will update the PR with comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timjklein36 thanks for your PR! I reviewed it with more time and calm now and it looks great!
I'd also like to apologize myself for the loose review I gave to this PR in the past and my comments because they were not valid and were created due my lack of concentration when reviewing this. I honestly hope to keep reviewing new PRs from you =)
@berinhard No problem! I enjoy contributing. Thanks for the review! |
What
This change set allows a caller of
foreign_key
to supply a recipe via astr
value that refers to a recipe from another module. Up to now, if astr
value was passed in toforeign_key
it would attempt to load that recipe in the module from whichforeign_key
was called. That functionality is still present. It is used as a fallback if thestr
value provided does not refer to a recipe from another module.Fixes #52.
Why
This offers more flexibility to the use of
foreign_key
and does not require the caller to import the recipe that they want to use.How
The code for
foreign_key
,RecipeForeignKey
, andrelated
was refactored slightly to reduce code duplication for the logic of loading a recipe from the "calling module". In addition to that, since it is assumed that most users ofmodel_bakery
callforeign_key
and do not instantiateRecipeForeignKey
directly, the logic for loading a recipe from a given module path string and the fallback logic for loading from the "calling module" string were placed insideforeign_key
and removed fromRecipeForeignKey
's__init__
method to make it cleaner. The__init__
method now only acceptsRecipe
objects.Docstrings were also added to some existing functions/classes and all new functions.
Example Usage
people.baker_recipes.py
dogs.baker_recipes.py