Created
May 26, 2023 09:12
-
-
Save spookylukey/d8dfdab4ffd606a4404e24f1b699aa06 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
The make_OnboardingRenameTeamForm class was a hack to try to get around some problems: | |
We want to do this at module level: | |
OnboardingRenameTeamForm = global_preference_form_builder(preferences=[("organization_name", "branding")]) | |
However, this is a problem because `global_preference_form_builder` does database queries, | |
which is in general a bad idea to do when modules are loading, and it breaks our test suite badly. | |
First idea - change `OnboardingRenameTeamForm` to a function that will return the form - the wizard shouldn't | |
know the difference: | |
def OnboardingRenameTeamForm(*args, **kwargs): | |
actual_form_class = global_preference_form_builder(preferences=[("organization_name", "branding")]) | |
return actual_form_class(*args, **kwargs) | |
Problem: the wizard *does* know the difference, because it does an `isinstance` check to detect | |
form classes. This is an even bigger problem, because `isinstance` on a function doesn't just | |
return False, it throws an error. So, we need to supply something like a class, but when the class | |
is called, it should return a different type of thing. That's what the `__new__` thing is supposed | |
to do, a bit like this: https://stackoverflow.com/questions/20221858/python-new-method-returning-something-other-than-class-instance | |
Except I didn't test it and messed it up. Here is my debugging using a simplified case: | |
I couldn't see how `data` could get passed multiple times, but from experience I'm guessing this | |
is something to do with `data` being the first positional arg, so the code is trying to pass both | |
the first positional arg and the `data` kwarg. | |
Debugging in IPython: | |
In [1]: class Form: | |
...: def __init__(self, data=None, other=None): | |
...: pass | |
...: | |
In [2]: class FormMaker: | |
...: def __new__(*args, **kwargs): | |
...: return Form(*args, **kwargs) | |
...: | |
In [3]: FormMaker() | |
Out[3]: <__main__.Form at 0x7ff3de21a8c0> | |
In [4]: Form(data="test") | |
Out[4]: <__main__.Form at 0x7ff3de21a320> | |
In [4]: FormMaker(data="test") | |
--------------------------------------------------------------------------- | |
TypeError Traceback (most recent call last) | |
Cell In[4], line 1 | |
----> 1 FormMaker(data="test") | |
Cell In[2], line 3, in FormMaker.__new__(*args, **kwargs) | |
2 def __new__(*args, **kwargs): | |
----> 3 return Form(*args, **kwargs) | |
OK, good I've got the same error. Print debugging on what those args are: | |
In [5]: class FormMaker: | |
...: def __new__(*args, **kwargs): | |
...: print(args) | |
...: print(kwargs) | |
...: return Form(*args, **kwargs) | |
...: | |
In [6]: FormMaker(data="test") | |
(<class '__main__.FormMaker'>,) | |
{'data': 'test'} | |
Confirmed - it's passing a positional arg, which is a class object. I messed up the signature to | |
`__new__`, which should start with `cls`. Fix: | |
In [8]: class FormMaker: | |
...: def __new__(cls, *args, **kwargs): | |
...: print(args) | |
...: print(kwargs) | |
...: return Form(*args, **kwargs) | |
...: | |
In [9]: FormMaker(data="test") | |
() | |
{'data': 'test'} | |
Out[9]: <__main__.Form at 0x7ff3dc8ef1c0> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment