Repository: gradio-app/gradio
Pull request: Allow `gr.Templates` to take in arguments
A fix to `gr.Templates` so that they can take in arguments. Fixes: #2595

Problem statement:
`gr.Sketchpad` does not take arguments
### Describe the bug

When using the `gr.Sketchpad` component with any of the parameters in the docstring, it fails.
`gr.Sketchpad` only works without any parameter.

### Is there an existing issue for this?

- [X] I have searched the existing issues

### Reproduction

To reproduce this, you can run this snippet:
```python
import gradio as gr

def show(img):
    return img

demo = gr.Interface(show, 
                    inputs=gr.Sketchpad(invert_colors=False), 
                    outputs='image')
demo.launch()
```


### Screenshot

On Investigation, it looks like the SketchPad component has a hardcoded set of keyword arguments passed to the super class. Not sure about the reason for it. 

```python
class Sketchpad(components.Image):
    """
    Sets: image_mode="L", source="canvas", shape=(28, 28), invert_colors=True
    """

    is_template = True

    def __init__(self, **kwargs):
        super().__init__(
            image_mode="L",
            source="canvas",
            shape=(28, 28),
            invert_colors=True,
            interactive=True,
            **kwargs
        )
```

This is probably the reason for the error
`TypeError: gradio.components.Image.__init__() got multiple values for keyword argument 'invert_colors'`

### Logs

```shell
In the above example, when passing the keyword arguments like `invert_colors` or `shape` to `gr.Sketchpad()` it throws the error:


      5 
      6 demo = gr.Interface(show, 
----> 7                     inputs=gr.Sketchpad(invert_colors=False),
      8                     outputs='image')
      9 demo.launch()

/usr/local/lib/python3.9/site-packages/gradio/templates.py in __init__(self, **kwargs)
     43 
     44     def __init__(self, **kwargs):
---> 45         super().__init__(
     46             image_mode="L",
     47             source="canvas",

TypeError: gradio.components.Image.__init__() got multiple values for keyword argument 'invert_colors'
```


### System Info

```shell
Gradio version: '3.8.2'
OS: MacOS
Browser: Chrome
```


### Severity

blocking all usage of gradio

Hints from issue discussion:

Commit message: formatting

Patch to review:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d9acf58f3..f0a76934f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,8 @@ No changes to highlight.
 
 ## Full Changelog:
 * Add `api_name` to `Blocks.__call__` by  [@freddyaboulton](https://github.com/freddyaboulton) in [PR 2593](https://github.com/gradio-app/gradio/pull/2593) 
+* Allow `gr.Templates` to accept parameters to override the defaults by [@abidlabs](https://github.com/abidlabs) in [PR 2600](https://github.com/gradio-app/gradio/pull/2600) 
+
 
 ## Contributors Shoutout:
 No changes to highlight.
diff --git a/gradio/__init__.py b/gradio/__init__.py
index 22bdccd0ba..1ca2fd67b7 100644
--- a/gradio/__init__.py
+++ b/gradio/__init__.py
@@ -23,6 +23,7 @@
     Dropdown,
     File,
     Gallery,
+    Highlight,
     Highlightedtext,
     HighlightedText,
     Image,
@@ -60,7 +61,6 @@
 from gradio.routes import mount_gradio_app
 from gradio.templates import (
     Files,
-    Highlight,
     ImageMask,
     ImagePaint,
     List,
diff --git a/gradio/components.py b/gradio/components.py
index 70879fb4f8..bdc040a878 100644
--- a/gradio/components.py
+++ b/gradio/components.py
@@ -3982,6 +3982,7 @@ def get_component_instance(comp: str | dict | Component, render=True) -> Compone
 
 DataFrame = Dataframe
 Highlightedtext = HighlightedText
+Highlight = HighlightedText
 Checkboxgroup = CheckboxGroup
 TimeSeries = Timeseries
 Json = JSON
diff --git a/gradio/templates.py b/gradio/templates.py
index fdbe85ca83..e9b64788b1 100644
--- a/gradio/templates.py
+++ b/gradio/templates.py
@@ -9,7 +9,9 @@ class Text(components.Textbox):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(lines=1, **kwargs)
+        defaults = dict(lines=1)
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class TextArea(components.Textbox):
@@ -20,73 +22,80 @@ class TextArea(components.Textbox):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(lines=7, **kwargs)
+        defaults = dict(lines=7)
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Webcam(components.Image):
     """
-    Sets: source="webcam"
+    Sets: source="webcam", interactive=True
     """
 
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(source="webcam", interactive=True, **kwargs)
+        defaults = dict(source="webcam", interactive=True)
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Sketchpad(components.Image):
     """
-    Sets: image_mode="L", source="canvas", shape=(28, 28), invert_colors=True
+    Sets: image_mode="L", source="canvas", shape=(28, 28), invert_colors=True, interactive=True
     """
 
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(
+        defaults = dict(
             image_mode="L",
             source="canvas",
             shape=(28, 28),
             invert_colors=True,
             interactive=True,
-            **kwargs
         )
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Paint(components.Image):
     """
-    Sets: source="canvas", tool="color-sketch"
+    Sets: source="canvas", tool="color-sketch", interactive=True
     """
 
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(
-            source="canvas", tool="color-sketch", interactive=True, **kwargs
-        )
+        defaults = dict(source="canvas", tool="color-sketch", interactive=True)
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class ImageMask(components.Image):
     """
-    Sets: source="canvas", tool="sketch"
+    Sets: source="upload", tool="sketch", interactive=True
     """
 
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(source="upload", tool="sketch", interactive=True, **kwargs)
+        defaults = dict(source="upload", tool="sketch", interactive=True)
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class ImagePaint(components.Image):
     """
-    Sets: source="upload", tool="color-sketch"
+    Sets: source="upload", tool="color-sketch", interactive=True
     """
 
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(
-            source="upload", tool="color-sketch", interactive=True, **kwargs
-        )
+        defaults = dict(source="upload", tool="color-sketch", interactive=True)
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Pil(components.Image):
@@ -97,7 +106,9 @@ class Pil(components.Image):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(type="pil", **kwargs)
+        defaults = dict(type="pil")
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class PlayableVideo(components.Video):
@@ -108,7 +119,9 @@ class PlayableVideo(components.Video):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(format="mp4", **kwargs)
+        defaults = dict(format="mp4")
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Microphone(components.Audio):
@@ -119,7 +132,9 @@ class Microphone(components.Audio):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(source="microphone", **kwargs)
+        defaults = dict(source="microphone")
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Mic(components.Audio):
@@ -130,7 +145,9 @@ class Mic(components.Audio):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(source="microphone", **kwargs)
+        defaults = dict(source="microphone")
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Files(components.File):
@@ -141,7 +158,9 @@ class Files(components.File):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(file_count="multiple", **kwargs)
+        defaults = dict(file_count="multiple")
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Numpy(components.Dataframe):
@@ -152,7 +171,9 @@ class Numpy(components.Dataframe):
     is_template = True
 
     def __init__(self, **kwargs):
-        super().__init__(type="numpy", **kwargs)
+        defaults = dict(type="numpy")
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class Matrix(components.Dataframe):
@@ -165,9 +186,10 @@ class Matrix(components.Dataframe):
     def __init__(self, **kwargs):
         """
         Custom component
-        @param kwargs:
         """
-        super().__init__(type="array", **kwargs)
+        defaults = dict(type="array")
+        defaults.update(kwargs)
+        super().__init__(**defaults)
 
 
 class List(components.Dataframe):
@@ -180,17 +202,7 @@ class List(components.Dataframe):
     def __init__(self, **kwargs):
         """
         Custom component
-        @param kwargs:
-        """
-        super().__init__(type="array", col_count=1, **kwargs)
-
-
-class Highlight(components.HighlightedText):
-    is_template = True
-
-    def __init__(self, **kwargs):
-        """
-        Custom component
-        @param kwargs:
         """
-        super().__init__(**kwargs)
+        defaults = dict(type="array", col_count=1)
+        defaults.update(kwargs)
+        super().__init__(**defaults)
diff --git a/test/test_components.py b/test/test_components.py
index 1cf68d8f28..545d8e1610 100644
--- a/test/test_components.py
+++ b/test/test_components.py
@@ -165,6 +165,17 @@ def test_static(self):
         component = gr.Textbox("abc")
         self.assertEqual(component.get_config().get("value"), "abc")
 
+    def test_override_template(self):
+        """
+        override template
+        """
+        component = gr.TextArea(value="abc")
+        self.assertEqual(component.get_config().get("value"), "abc")
+        self.assertEqual(component.get_config().get("lines"), 7)
+        component = gr.TextArea(value="abc", lines=4)
+        self.assertEqual(component.get_config().get("value"), "abc")
+        self.assertEqual(component.get_config().get("lines"), 4)
+
 
 class TestNumber(unittest.TestCase):
     def test_component_functions(self):


Code review comments:
diff_hunk: @@ -97,7 +106,9 @@ class Pil(components.Image):
     is_template = True
 
     def __init__(self, **kwargs):
path: gradio/templates.py
text: @user1:
Wouldn't it be better if we specified the kwargs the class supports as opposed to accepting arbitrary kwargs?

Right now you could do `gr.Pil(type="numpy")` which is confusing/defeats the purpose of the template. Also means devs won't get hints from their editors and makes it easy to make a typo and only be aware at runtime.

@author:
Ah yeah you're right. I think it's okay to override the template params but you're right it would be good to specify them explicitly