(Forge and/or Gradio) Error Afflicting Many Extensions
Gradio 4 directly caused many extensions to have issues, due to code changes, deprecations, etc.
Not this error. This error is from Forge, and it affects many extensions.
The error, which I'll refer to later as "Inherited Component bug":
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\components\base.py", line 118, in get_component_class_id
module_path = sys.modules[module_name].__file__
KeyError: 'extension-script-name.py'
Traceback Sample
*** Error calling: C:\stable-diffusion-webui-forge\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py/ui
Traceback (most recent call last):
File "C:\stable-diffusion-webui-forge\modules\scripts.py", line 545, in wrap_call
return func(*args, **kwargs)
File "C:\stable-diffusion-webui-forge\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py", line 261, in ui
ar_btns = [
File "C:\stable-diffusion-webui-forge\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py", line 262, in <listcomp>
ARButton(ar=ar, value=label)
File "C:\stable-diffusion-webui-forge\extensions\--sd-webui-ar-plus\scripts\sd-webui-ar.py", line 35, in __init__
super().__init__(**kwargs)
File "C:\stable-diffusion-webui-forge\modules\ui_components.py", line 23, in __init__
super().__init__(*args, elem_classes=["tool", *elem_classes], value=value, **kwargs)
File "C:\stable-diffusion-webui-forge\modules\gradio_extensions.py", line 126, in __repaired_init__
original(self, *args, **fixed_kwargs)
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\component_meta.py", line 163, in wrapper
return fn(self, **kwargs)
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\components\button.py", line 61, in __init__
super().__init__(
File "C:\stable-diffusion-webui-forge\modules\gradio_extensions.py", line 35, in IOComponent_init
res = original_IOComponent_init(self, *args, **kwargs)
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\component_meta.py", line 163, in wrapper
return fn(self, **kwargs)
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\components\base.py", line 224, in __init__
self.component_class_id = self.__class__.get_component_class_id()
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\components\base.py", line 118, in get_component_class_id
module_path = sys.modules[module_name].__file__
KeyError: 'sd-webui-ar.py'
What I believe Forge needs to Fix this Forge error:
- I may be wrong, the error may lie elsewhere.
- I believe IOComponent_init needs to be updated, or another function working with it.
Reproduction:
Inherit from ToolButton() (or, presumably, any component imported from modules.ui_components).
from modules.ui_components import ToolButton
class CustomToolButton(ToolButton):
def __init__(self, value='button', **kwargs):
super().__init__(value, **kwargs)
self.value = value
def some_method(self):
pass
button = CustomToolButton(value='test')
How extension developers can resolve the issue:
Note: developers are typically subclassing UI components so they can define class methods.
Therefore, this solution can be extremely painful/confusing depending on the application.
Solution: Do not subclass any UI components.
from modules.ui_components import ToolButton
button = ToolButton(value='test')
What's happening:
Refer to the Traceback Sample in the accordion above.
Strange Initialization for subclassed components:
File "C:\stable-diffusion-webui-forge\modules\ui_components.py", line 23, in __init__
super().__init__(*args, elem_classes=["tool", *elem_classes], value=value, **kwargs)
Important: At this step, all WebUIs (A1111, Forge, Reforge, etc) experience "Inherited Component bug"
- "Among other things", subclassed component's have
.__module__attribute value: "extension-script-name" - Components which are not subclassed have
.__module__attribute value: "modules.ui_components"
WebUI Repairs Strange Initialization:
File "C:\stable-diffusion-webui-forge\modules\gradio_extensions.py", line 126, in __repaired_init__
original(self, *args, **fixed_kwargs)
At this step, all other WebUIs except Forge successfully repair the Strange Initialization that occurs.
- "Among other things",
.__module__attribute value: "extension-script-name" will be updated to "modules.ui_components"
Hack that fixes the error, but not "Among other things":
"Among other things" (not resolved by this) includes the following:
- Button may initialize as
disabledfor no apparent reason - "value" can be bugged resulting in a blank button
- These buttons seem to completely ignore any custom
.jscode defined by the script - There could be much more strange behavior for different components defined like this
This will make the script load in Forge:
CustomToolButton.__module__ = "modules.ui_components"
Example:
from modules.ui_components import ToolButton
class CustomToolButton(ToolButton):
def __init__(self, value='button', **kwargs):
super().__init__(value, **kwargs)
self.value = value
def some_method(self):
pass
CustomToolButton.__module__ = "modules.ui_components"
button = CustomToolButton(value='test')
What is the specific problem?!?!?!
It has something to do with the patching steps when it tries "__repaired_init__"
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\component_meta.py", line 163, in wrapper
return fn(self, **kwargs)
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\components\button.py", line 61, in __init__
super().__init__(
File "C:\stable-diffusion-webui-forge\modules\gradio_extensions.py", line 35, in IOComponent_init
res = original_IOComponent_init(self, *args, **kwargs)
File "C:\stable-diffusion-webui-forge\venv\lib\site-packages\gradio\component_meta.py", line 163, in wrapper
return fn(self, **kwargs)
This in particular looks very suspicious to me:
I appreciate the discussion you had here, helped to fix some other extensions.
For this issue, have you tried debug stepping through the repair loop in gradio_extensions? Or looked at the @wraps decorators in the extended subclasses? I wonder if the Button and FormComponent have differetn inits in Gradio.
The above is probably not good advice; the root cause seems to be that subclassed gradio components from extensions that are not modules, and thus they aren't in sys's module dict. They will then fail in gradio.components.base.get_component_class_id:
@classmethod
def get_component_class_id(cls) -> str:
module_name = cls.__module__
module_path = sys.modules[module_name].__file__
module_hash = hashlib.md5(f"{cls.__name__}_{module_path}".encode()).hexdigest()
return module_hash
Is it possible that the extension loading is different in Forge compared to other webui's?
I want to add a quick thing I meant to preface my OP with:
When I see people on Reddit / discord saying the reasons they do not use Forge, the main reason is "My extensions don't work".
Here is one major bug that will not be easily resolved by all extension developers, if I am correct that this is indeed on Forge.
I've suffered traumatically in attempting / assisting with debugging this particular issue, and it's brought me some relief to just spill out everything that I learned in the process, in hopes someone who really knows what they are doing can solve this.
I'm really not willing to dive back in, test prints, etc.
I had put debug prints all over the place, tested over and over again for hours... in my script, in the modules, etc.
- Before the repair stage, Forge / A1111 print statements are the same
- In
base.pywhen Forge errors, A1111 has it resolved - it successfully fixes that component.
Thanks for transferring some of your trauma on to me π
You were correct that something was wrong, though it is also a problem in auto1111, they just won't start encountering it until they update to Gradio 4 (or some other code explicitly checks sys.modules). See PR above and let me know if it fixes the issue you were seeing.
Thanks for transferring some of your trauma on to me π
You were correct that something was wrong, though it is also a problem in auto1111, they just won't start encountering it until they update to Gradio 4 (or some other code explicitly checks sys.modules). See PR above and let me know if it fixes the issue you were seeing.
You're very good! I applied your PR, then used git checkout to roll back my extension.
Your PR resolved the __module__ error, but it does not resolve the other Strange Initialization stuff.
- Is ignoring the
.jscode targetting it - Some labels not setting. If I change the way of setting them, those buttons will initialize as
disabled. I could not figure out why this is. LEv145 had the same issue when trying to adjust their subclassed ToolButton() components.
But your PR is already a huge step in the right direction, as the extension loaded up without error!
Comparing the gradio code, base.py between Forge (Gradio 4) and A1111 (Gradio 3), I see there is a drastically different way for initializing component bases.
While we think about the PR, can you describe some tests I can try in this extension? The buttons seemed to load up fine for me:
It seems like I might be on a different branch?
While we think about the PR, can you describe some tests I can try in this extension? The buttons seemed to load up fine for me:
It seems like I might be on a different branch?
The bug affects any extension that subclasses a UI component. My extension was updated to simply not subclass the ToolButtons. I used git checkout to roll back to a version before I made that change, and the PR did fix the error.
Lev145 really solved the problem for us here and itβs actually a complicated solution for our application. Instead of making custom button classes, it tuples functions with each button instance
EDIT Okay I see you were actually looking at their repo. They fixed it as I described
EDIT2 this is the commit before I resolved the issue
you can also check out Segment Anything main branch, they also have the bug - I sent them a PR that replaces the subclassed button with a direct instance
