gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
33.39k stars 2.52k forks source link

Custom component doc generation can fail if a non-component python class is exported #8612

Open freddyaboulton opened 3 months ago

freddyaboulton commented 3 months ago

Describe the bug

In your custom component project, if you export a python class that's not a gradio component, then the docs and build commands will fail.

We should only document classes that are component classes. Any other classes can be manually documented.

Have you searched existing issues? 🔎

Reproduction

gradio cc create TemplateComponent --no-configure-metadata

Add a python class to the __init__.py

from gradio.components.base import Component

class Helper:
    pass

class TemplateComponent(Component):
    def preprocess(self, payload):

from .templatecomponent import TemplateComponent, Helper

__all__ = ['TemplateComponent', 'Helper']

Then run gradio cc build

/Users/freddy/miniconda3/envs/test/lib/python3.9/site-packages/gradio/ │
│ cli/commands/components/_docs_utils.py:711 in render_class_docs        │
│                                                                        │
│   708 │                                                                │
│   709 │   gr.ParamViewer(value=_docs["{class_name}"]["members"]["__ini │
│   710                                                                  │
│ ❱ 711 {render_class_events(docs[class_name].get("events", None), class │
│   712                                                                  │
│   713 {make_user_fn(                                                   │
│   714 │   class_name,                                                  │
│                                                                        │
│ ╭────────────────────────────── locals ──────────────────────────────╮ │
│ │                 class_name = 'Helper'                              │ │
│ │                       docs = {                                     │ │
│ │                              │   'Helper': {                       │ │
│ │                              │   │   'description': '',            │ │
│ │                              │   │   'members': {}                 │ │
│ │                              │   },                                │ │
│ │                              │   '__meta__': {                     │ │
│ │                              │   │   'additional_interfaces': {}   │ │
│ │                              │   },                                │ │
│ │                              │   'TemplateComponent': {            │ │
│ │                              │   │   'description': 'A base class  │ │
│ │                              for defining methods that all         │ │
│ │                              input/output components should        │ │
│ │                              have.',                               │ │
│ │                              │   │   'members': {                  │ │
│ │                              │   │   │   '__init__': {             │ │
│ │                              │   │   │   │   'value': {            │ │
│ │                              │   │   │   │   │   'type': 'Any',    │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'label': {            │ │
│ │                              │   │   │   │   │   'type': 'str |    │ │
│ │                              None',                                │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'info': {             │ │
│ │                              │   │   │   │   │   'type': 'str |    │ │
│ │                              None',                                │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'show_label': {       │ │
│ │                              │   │   │   │   │   'type': 'bool |   │ │
│ │                              None',                                │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'container': {        │ │
│ │                              │   │   │   │   │   'type': 'bool',   │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'True',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'scale': {            │ │
│ │                              │   │   │   │   │   'type': 'int |    │ │
│ │                              None',                                │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'min_width': {        │ │
│ │                              │   │   │   │   │   'type': 'int |    │ │
│ │                              None',                                │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'interactive': {      │ │
│ │                              │   │   │   │   │   'type': 'bool |   │ │
│ │                              None',                                │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'visible': {          │ │
│ │                              │   │   │   │   │   'type': 'bool',   │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'True',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   'elem_id': {          │ │
│ │                              │   │   │   │   │   'type': 'str |    │ │
│ │                              None',                                │ │
│ │                              │   │   │   │   │   'default':        │ │
│ │                              'None',                               │ │
│ │                              │   │   │   │   │   'description':    │ │
│ │                              None                                  │ │
│ │                              │   │   │   │   },                    │ │
│ │                              │   │   │   │   ... +5                │ │
│ │                              │   │   │   },                        │ │
│ │                              │   │   │   'postprocess': {},        │ │
│ │                              │   │   │   'preprocess': {}          │ │
│ │                              │   │   },                            │ │
│ │                              │   │   'events': {}                  │ │
│ │                              │   }                                 │ │
│ │                              }                                     │ │
│ │               docs_classes = ''                                    │ │
│ │                    exports = ['Helper', 'TemplateComponent']       │ │
│ │                    linkify = {}                                    │ │
│ │  user_fn_input_description = None                                  │ │
│ │         user_fn_input_type = None                                  │ │
│ │ user_fn_output_description = None                                  │ │
│ │        user_fn_output_type = None                                  │ │
│ ╰────────────────────────────────────────────────────────────────────╯ │
│                                                                        │
│ /Users/freddy/miniconda3/envs/test/lib/python3.9/site-packages/gradio/ │
│ cli/commands/components/_docs_utils.py:540 in render_class_events      │
│                                                                        │
│   537                                                                  │
│   538 def render_class_events(events: dict, name):                     │
│   539 │   """Renders the events for a class."""                        │
│ ❱ 540 │   if len(events) == 0:                                         │
│   541 │   │   return ""                                                │
│   542 │                                                                │
│   543 │   else:                                                        │
│                                                                        │
│ ╭───── locals ──────╮                                                  │
│ │ events = None     │                                                  │
│ │   name = 'Helper' │                                                  │
│ ╰───────────────────╯                                                  │
╰────────────────────────────────────────────────────────────────────────╯
TypeError: object of type 'NoneType' has no len()

Screenshot

No response

Logs

No response

System Info

Gradio Environment Information:
------------------------------
Operating System: Darwin
gradio version: 4.36.1
gradio_client version: 1.0.1

------------------------------------------------
gradio dependencies in your environment:

aiofiles: 23.2.1
altair: 5.3.0
fastapi: 0.110.2
ffmpy: 0.3.2
gradio-client==1.0.1 is not installed.
httpx: 0.27.0
huggingface-hub: 0.22.2
importlib-resources: 6.4.0
jinja2: 3.1.3
markupsafe: 2.1.5
matplotlib: 3.8.4
numpy: 1.26.4
orjson: 3.10.1
packaging: 24.0
pandas: 2.2.2
pillow: 10.3.0
pydantic: 2.7.1
pydub: 0.25.1
python-multipart: 0.0.9
pyyaml: 6.0.1
ruff: 0.4.2
semantic-version: 2.10.0
tomlkit==0.12.0 is not installed.
typer: 0.12.3
typing-extensions: 4.11.0
urllib3: 2.2.1
uvicorn: 0.29.0
authlib; extra == 'oauth' is not installed.
itsdangerous; extra == 'oauth' is not installed.

gradio_client dependencies in your environment:

fsspec: 2024.3.1
httpx: 0.27.0
huggingface-hub: 0.22.2
packaging: 24.0
typing-extensions: 4.11.0
websockets: 11.0.3

Severity

I can work around it

pngwn commented 3 months ago

I though we handled this case. Must be faulty.