Repository: gradio-app/gradio
Pull request: Use Literal Type Hint Where Possible
## Description

Closes: #4599

![image](https://github.com/gradio-app/gradio/assets/41651716/39a696a6-edce-48f7-ac7b-1af64bd55195)


## 🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is [an existing issue](https://github.com/gradio-app/gradio/issues) for this change. If not, please create an issue before you create this PR, unless the fix is very small. 

Not adhering to this guideline will result in the PR being closed. 

## Tests & Changelog

1. PRs will only be merged if tests pass on CI. To run the tests locally, please set up [your Gradio environment locally](https://github.com/gradio-app/gradio/blob/main/CONTRIBUTING.md) and run the tests: `bash scripts/run_all_tests.sh`

1. You may need to run the linters: `bash scripts/format_backend.sh` and `bash scripts/format_frontend.sh`
  
1. Unless the pull request is labeled with the "no-changelog-update" label by a maintainer of the repo, all pull requests must update the changelog located in `CHANGELOG.md`:

Please add a brief summary of the change to the Upcoming Release section of the `CHANGELOG.md` file and include
a link to the PR (formatted in markdown) and a link to your github profile (if you like). For example, "* Added a cool new feature by `[@myusername](link-to-your-github-profile)` in `[PR 11111](https://github.com/gradio-app/gradio/pull/11111)`".


Problem statement:
Use literal type hint in component parameters
- [ ] I have searched to see if a similar issue already exists.


**Is your feature request related to a problem? Please describe.**  
There are some places in the code where a string value is expected from a finite list of possibilities. Like `source` in `Video`. These arguments are typed as `str` but `Literal` would provide better autocomplete and editor support.

**Describe the solution you'd like**  
Add `Literal` to the codebase where appropriate.

**Additional context**  
Add any other context or screenshots about the feature request here.

Hints from issue discussion:

Commit message: CHANGELOG

Patch to review:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a8dce218c5..d07c0a1cb0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@
 ## Other Changes:
 
 - Update frontend dependencies in [PR 4601](https://github.com/gradio-app/gradio/pull/4601)
+- Use `typing.Literal` where possible in gradio library and client by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4608](https://github.com/gradio-app/gradio/pull/4608)
 
 ## Breaking Changes:
 
diff --git a/client/python/gradio_client/client.py b/client/python/gradio_client/client.py
index b49c61b6ef..e2e3a4614c 100644
--- a/client/python/gradio_client/client.py
+++ b/client/python/gradio_client/client.py
@@ -145,7 +145,16 @@ def duplicate(
         to_id: str | None = None,
         hf_token: str | None = None,
         private: bool = True,
-        hardware: str | None = None,
+        hardware: Literal[
+            "cpu-basic",
+            "cpu-upgrade",
+            "t4-small",
+            "t4-medium",
+            "a10g-small",
+            "a10g-large",
+            "a100-large",
+        ]
+        | None = None,
         secrets: dict[str, str] | None = None,
         sleep_timeout: int = 5,
         max_workers: int = 40,
@@ -937,7 +946,7 @@ def __next__(self) -> tuple | Any:
                 if self.communicator.job.latest_status.code == Status.FINISHED:
                     raise StopIteration()
 
-    def result(self, timeout=None) -> Any:
+    def result(self, timeout: float | None = None) -> Any:
         """
         Return the result of the call that the future represents. Raises CancelledError: If the future was cancelled, TimeoutError: If the future didn't finish executing before the given timeout, and Exception: If the call raised then that exception will be raised.
 
diff --git a/gradio/components/audio.py b/gradio/components/audio.py
index d21238f457..dd4a20195d 100644
--- a/gradio/components/audio.py
+++ b/gradio/components/audio.py
@@ -52,8 +52,8 @@ def __init__(
         self,
         value: str | tuple[int, np.ndarray] | Callable | None = None,
         *,
-        source: str = "upload",
-        type: str = "numpy",
+        source: Literal["upload", "microphone"] = "upload",
+        type: Literal["numpy", "filepath"] = "numpy",
         label: str | None = None,
         every: float | None = None,
         show_label: bool = True,
@@ -141,7 +141,7 @@ def example_inputs(self) -> dict[str, Any]:
     @staticmethod
     def update(
         value: Any | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
-        source: str | None = None,
+        source: Literal["upload", "microphone"] | None = None,
         label: str | None = None,
         show_label: bool | None = None,
         container: bool | None = None,
diff --git a/gradio/components/bar_plot.py b/gradio/components/bar_plot.py
index 6c0cc99439..988a43f943 100644
--- a/gradio/components/bar_plot.py
+++ b/gradio/components/bar_plot.py
@@ -40,7 +40,18 @@ def __init__(
         y_title: str | None = None,
         color_legend_title: str | None = None,
         group_title: str | None = None,
-        color_legend_position: str | None = None,
+        color_legend_position: Literal[
+            "left",
+            "right",
+            "top",
+            "bottom",
+            "top-left",
+            "top-right",
+            "bottom-left",
+            "bottom-right",
+            "none",
+        ]
+        | None = None,
         height: int | None = None,
         width: int | None = None,
         y_lim: list[int] | None = None,
@@ -136,7 +147,18 @@ def update(
         y_title: str | None = None,
         color_legend_title: str | None = None,
         group_title: str | None = None,
-        color_legend_position: str | None = None,
+        color_legend_position: Literal[
+            "left",
+            "right",
+            "top",
+            "bottom",
+            "top-left",
+            "top-right",
+            "bottom-left",
+            "bottom-right",
+            "none",
+        ]
+        | None = None,
         height: int | None = None,
         width: int | None = None,
         y_lim: list[int] | None = None,
@@ -237,7 +259,19 @@ def create_plot(
         y_title: str | None = None,
         color_legend_title: str | None = None,
         group_title: str | None = None,
-        color_legend_position: str | None = None,
+        color_legend_position: Literal[
+            "left",
+            "right",
+            "top",
+            "bottom",
+            "top-left",
+            "top-right",
+            "bottom-left",
+            "bottom-right",
+            "none",
+        ]
+        | None
+        | None = None,
         height: int | None = None,
         width: int | None = None,
         y_lim: list[int] | None = None,
diff --git a/gradio/components/button.py b/gradio/components/button.py
index 49b6e9d523..39d2c6e93c 100644
--- a/gradio/components/button.py
+++ b/gradio/components/button.py
@@ -29,7 +29,7 @@ def __init__(
         value: str | Callable = "Run",
         *,
         variant: Literal["primary", "secondary", "stop"] = "secondary",
-        size: Literal["sm"] | Literal["lg"] | None = None,
+        size: Literal["sm", "lg"] | None = None,
         visible: bool = True,
         interactive: bool = True,
         elem_id: str | None = None,
@@ -82,7 +82,7 @@ def get_config(self):
     def update(
         value: str | Literal[_Keywords.NO_VALUE] | None = _Keywords.NO_VALUE,
         variant: Literal["primary", "secondary", "stop"] | None = None,
-        size: Literal["sm"] | Literal["lg"] | None = None,
+        size: Literal["sm", "lg"] | None = None,
         visible: bool | None = None,
         interactive: bool | None = None,
         scale: int | None = None,
diff --git a/gradio/components/checkboxgroup.py b/gradio/components/checkboxgroup.py
index b90b402045..04a224c5fb 100644
--- a/gradio/components/checkboxgroup.py
+++ b/gradio/components/checkboxgroup.py
@@ -38,7 +38,7 @@ def __init__(
         choices: list[str] | None = None,
         *,
         value: list[str] | str | Callable | None = None,
-        type: str = "value",
+        type: Literal["value", "index"] = "value",
         label: str | None = None,
         info: str | None = None,
         every: float | None = None,
diff --git a/gradio/components/code.py b/gradio/components/code.py
index dc1e4f3fee..878533ba0d 100644
--- a/gradio/components/code.py
+++ b/gradio/components/code.py
@@ -39,7 +39,20 @@ class Code(Changeable, Inputable, IOComponent, StringSerializable):
     def __init__(
         self,
         value: str | tuple[str] | None = None,
-        language: str | None = None,
+        language: Literal[
+            "python",
+            "markdown",
+            "json",
+            "html",
+            "css",
+            "javascript",
+            "typescript",
+            "yaml",
+            "dockerfile",
+            "shell",
+            "r",
+            None,
+        ] = None,
         *,
         lines: int = 5,
         label: str | None = None,
@@ -114,7 +127,21 @@ def update(
         scale: int | None = None,
         min_width: int | None = None,
         visible: bool | None = None,
-        language: str | None = None,
+        language: Literal[
+            "python",
+            "markdown",
+            "json",
+            "html",
+            "css",
+            "javascript",
+            "typescript",
+            "yaml",
+            "dockerfile",
+            "shell",
+            "r",
+            None,
+        ]
+        | None = None,
         interactive: bool | None = None,
     ):
         return {
diff --git a/gradio/components/dataframe.py b/gradio/components/dataframe.py
index 750b6e1464..f0ed13adaf 100644
--- a/gradio/components/dataframe.py
+++ b/gradio/components/dataframe.py
@@ -49,10 +49,10 @@ def __init__(
         row_count: int | tuple[int, str] = (1, "dynamic"),
         col_count: int | tuple[int, str] | None = None,
         datatype: str | list[str] = "str",
-        type: str = "pandas",
+        type: Literal["pandas", "numpy", "array"] = "pandas",
         max_rows: int | None = 20,
         max_cols: int | None = None,
-        overflow_row_behaviour: str = "paginate",
+        overflow_row_behaviour: Literal["paginate", "show_ends"] = "paginate",
         label: str | None = None,
         every: float | None = None,
         show_label: bool = True,
diff --git a/gradio/components/dataset.py b/gradio/components/dataset.py
index 9491368587..af7a7c8bb7 100644
--- a/gradio/components/dataset.py
+++ b/gradio/components/dataset.py
@@ -34,7 +34,7 @@ def __init__(
         components: list[IOComponent] | list[str],
         samples: list[list[Any]] | None = None,
         headers: list[str] | None = None,
-        type: str = "values",
+        type: Literal["values", "index"] = "values",
         samples_per_page: int = 10,
         visible: bool = True,
         elem_id: str | None = None,
diff --git a/gradio/components/dropdown.py b/gradio/components/dropdown.py
index 0a30634cf5..6d7a56cda7 100644
--- a/gradio/components/dropdown.py
+++ b/gradio/components/dropdown.py
@@ -43,7 +43,7 @@ def __init__(
         choices: list[str] | None = None,
         *,
         value: str | list[str] | Callable | None = None,
-        type: str = "value",
+        type: Literal["value", "index"] = "value",
         multiselect: bool | None = None,
         max_choices: int | None = None,
         label: str | None = None,
diff --git a/gradio/components/file.py b/gradio/components/file.py
index 71a3f02014..c1cca56950 100644
--- a/gradio/components/file.py
+++ b/gradio/components/file.py
@@ -45,9 +45,9 @@ def __init__(
         self,
         value: str | list[str] | Callable | None = None,
         *,
-        file_count: str = "single",
+        file_count: Literal["single", "multiple", "directory"] = "single",
         file_types: list[str] | None = None,
-        type: str = "file",
+        type: Literal["file", "binary"] = "file",
         label: str | None = None,
         every: float | None = None,
         show_label: bool = True,
diff --git a/gradio/components/gallery.py b/gradio/components/gallery.py
index 559cb0ef3f..84468149ff 100644
--- a/gradio/components/gallery.py
+++ b/gradio/components/gallery.py
@@ -47,7 +47,8 @@ def __init__(
         rows: int | tuple | None = None,
         height: str | None = None,
         preview: bool | None = None,
-        object_fit: str | None = None,
+        object_fit: Literal["contain", "cover", "fill", "none", "scale-down"]
+        | None = None,
         allow_preview: bool = True,
         **kwargs,
     ):
@@ -110,7 +111,8 @@ def update(
         rows: int | tuple | None = None,
         height: str | None = None,
         preview: bool | None = None,
-        object_fit: str | None = None,
+        object_fit: Literal["contain", "cover", "fill", "none", "scale-down"]
+        | None = None,
         allow_preview: bool | None = None,
     ):
         updated_config = {
diff --git a/gradio/components/image.py b/gradio/components/image.py
index e7b9cb461a..2618cbe828 100644
--- a/gradio/components/image.py
+++ b/gradio/components/image.py
@@ -59,11 +59,11 @@ def __init__(
         shape: tuple[int, int] | None = None,
         height: int | None = None,
         width: int | None = None,
-        image_mode: str = "RGB",
+        image_mode: Literal["RGB", "L"] = "RGB",
         invert_colors: bool = False,
-        source: str = "upload",
-        tool: str | None = None,
-        type: str = "numpy",
+        source: Literal["upload", "webcam", "canvas"] = "upload",
+        tool: Literal["editor", "select", "sketch", "color-sketch"] | None = None,
+        type: Literal["numpy", "pil", "filepath"] = "numpy",
         label: str | None = None,
         every: float | None = None,
         show_label: bool = True,
diff --git a/gradio/components/textbox.py b/gradio/components/textbox.py
index 83424ff6ef..f73ee37ab3 100644
--- a/gradio/components/textbox.py
+++ b/gradio/components/textbox.py
@@ -67,7 +67,7 @@ def __init__(
         visible: bool = True,
         elem_id: str | None = None,
         elem_classes: list[str] | str | None = None,
-        type: str = "text",
+        type: Literal["text", "password", "email"] = "text",
         show_copy_button: bool = False,
         **kwargs,
     ):
@@ -151,7 +151,7 @@ def update(
         min_width: int | None = None,
         visible: bool | None = None,
         interactive: bool | None = None,
-        type: str | None = None,
+        type: Literal["text", "password", "email"] | None = None,
         show_copy_button: bool | None = None,
     ):
         return {
diff --git a/gradio/components/upload_button.py b/gradio/components/upload_button.py
index d3f64ba446..68205ed618 100644
--- a/gradio/components/upload_button.py
+++ b/gradio/components/upload_button.py
@@ -34,14 +34,14 @@ def __init__(
         *,
         variant: Literal["primary", "secondary", "stop"] = "secondary",
         visible: bool = True,
-        size: Literal["sm"] | Literal["lg"] | None = None,
+        size: Literal["sm", "lg"] | None = None,
         scale: int | None = None,
         min_width: int | None = None,
         interactive: bool = True,
         elem_id: str | None = None,
         elem_classes: list[str] | str | None = None,
-        type: str = "file",
-        file_count: str = "single",
+        type: Literal["file", "bytes"] = "file",
+        file_count: Literal["single", "multiple", "directory"] = "single",
         file_types: list[str] | None = None,
         **kwargs,
     ):
@@ -108,7 +108,7 @@ def update(
         | list[str]
         | Literal[_Keywords.NO_VALUE]
         | None = _Keywords.NO_VALUE,
-        size: Literal["sm"] | Literal["lg"] | None = None,
+        size: Literal["sm", "lg"] | None = None,
         variant: Literal["primary", "secondary", "stop"] | None = None,
         interactive: bool | None = None,
         visible: bool | None = None,
diff --git a/gradio/components/video.py b/gradio/components/video.py
index 382fbde638..14752987bb 100644
--- a/gradio/components/video.py
+++ b/gradio/components/video.py
@@ -47,7 +47,7 @@ def __init__(
         value: str | tuple[str, str | None] | Callable | None = None,
         *,
         format: str | None = None,
-        source: str = "upload",
+        source: Literal["upload", "webcam"] = "upload",
         height: int | None = None,
         width: int | None = None,
         label: str | None = None,
@@ -133,7 +133,7 @@ def update(
         | tuple[str, str | None]
         | Literal[_Keywords.NO_VALUE]
         | None = _Keywords.NO_VALUE,
-        source: str | None = None,
+        source: Literal["upload", "webcam"] | None = None,
         height: int | None = None,
         width: int | None = None,
         label: str | None = None,
diff --git a/gradio/events.py b/gradio/events.py
index 9662ad9822..14237d8ceb 100644
--- a/gradio/events.py
+++ b/gradio/events.py
@@ -76,9 +76,7 @@ def __init__(
         self,
         trigger: Block,
         event_name: str,
-        show_progress: Literal["full"]
-        | Literal["minimal"]
-        | Literal["hidden"] = "full",
+        show_progress: Literal["full", "minimal", "hidden"] = "full",
         callback: Callable | None = None,
         trigger_after: int | None = None,
         trigger_only_on_success: bool = False,
@@ -98,9 +96,7 @@ def __call__(
         api_name: str | None = None,
         status_tracker: None = None,
         scroll_to_output: bool = False,
-        show_progress: Literal["full"]
-        | Literal["minimal"]
-        | Literal["hidden"] = "full",
+        show_progress: Literal["full", "minimal", "hidden"] = "full",
         queue: bool | None = None,
         batch: bool = False,
         max_batch_size: int = 4,
diff --git a/gradio/layouts.py b/gradio/layouts.py
index 80e1588b85..b5d06969a6 100644
--- a/gradio/layouts.py
+++ b/gradio/layouts.py
@@ -1,7 +1,7 @@
 from __future__ import annotations
 
 import warnings
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Literal
 
 from gradio_client.documentation import document, set_documentation_group
 
@@ -30,7 +30,7 @@ class Row(BlockContext):
     def __init__(
         self,
         *,
-        variant: str = "default",
+        variant: Literal["default", "panel", "compact"] = "default",
         visible: bool = True,
         elem_id: str | None = None,
         equal_height: bool = True,
@@ -107,7 +107,7 @@ def __init__(
         *,
         scale: int = 1,
         min_width: int = 320,
-        variant: str = "default",
+        variant: Literal["default", "panel", "compact"] = "default",
         visible: bool = True,
         elem_id: str | None = None,
         **kwargs,
diff --git a/gradio/templates.py b/gradio/templates.py
index 5e970be1a8..63e509806e 100644
--- a/gradio/templates.py
+++ b/gradio/templates.py
@@ -1,6 +1,6 @@
 from __future__ import annotations
 
-from typing import Any, Callable
+from typing import Any, Callable, Literal
 
 import numpy as np
 from PIL.Image import Image
@@ -55,11 +55,11 @@ def __init__(
         value: str | Image | np.ndarray | None = None,
         *,
         shape: tuple[int, int] | None = None,
-        image_mode: str = "RGB",
+        image_mode: Literal["RGB", "L"] = "RGB",
         invert_colors: bool = False,
-        source: str = "webcam",
-        tool: str | None = None,
-        type: str = "numpy",
+        source: Literal["webcam"] = "webcam",
+        tool: Literal["editor", "select", "sketch", "color-sketch"] | None = None,
+        type: Literal["numpy", "pil", "filepath"] = "numpy",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = True,
@@ -102,11 +102,11 @@ def __init__(
         value: str | Image | np.ndarray | None = None,
         *,
         shape: tuple[int, int] = (28, 28),
-        image_mode: str = "L",
+        image_mode: Literal["L"] = "L",
         invert_colors: bool = True,
-        source: str = "canvas",
-        tool: str | None = None,
-        type: str = "numpy",
+        source: Literal["canvas"] = "canvas",
+        tool: Literal["editor", "select", "sketch", "color-sketch"] | None = None,
+        type: Literal["numpy", "pil", "filepath"] = "numpy",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = True,
@@ -149,11 +149,11 @@ def __init__(
         value: str | Image | np.ndarray | None = None,
         *,
         shape: tuple[int, int] | None = None,
-        image_mode: str = "RGB",
+        image_mode: Literal["RGB"] = "RGB",
         invert_colors: bool = False,
-        source: str = "canvas",
-        tool: str = "color-sketch",
-        type: str = "numpy",
+        source: Literal["canvas"] = "canvas",
+        tool: Literal["color-sketch"] = "color-sketch",
+        type: Literal["numpy", "pil", "filepath"] = "numpy",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = True,
@@ -196,11 +196,11 @@ def __init__(
         value: str | Image | np.ndarray | None = None,
         *,
         shape: tuple[int, int] | None = None,
-        image_mode: str = "RGB",
+        image_mode: Literal["RGB", "L"] = "RGB",
         invert_colors: bool = False,
-        source: str = "upload",
-        tool: str = "sketch",
-        type: str = "numpy",
+        source: Literal["upload"] = "upload",
+        tool: Literal["sketch"] = "sketch",
+        type: Literal["numpy", "pil", "filepath"] = "numpy",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = True,
@@ -243,11 +243,11 @@ def __init__(
         value: str | Image | np.ndarray | None = None,
         *,
         shape: tuple[int, int] | None = None,
-        image_mode: str = "RGB",
+        image_mode: Literal["RGB", "L"] = "RGB",
         invert_colors: bool = False,
-        source: str = "upload",
-        tool: str = "color-sketch",
-        type: str = "numpy",
+        source: Literal["upload"] = "upload",
+        tool: Literal["color-sketch"] = "color-sketch",
+        type: Literal["numpy", "pil", "filepath"] = "numpy",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = True,
@@ -290,11 +290,11 @@ def __init__(
         value: str | Image | np.ndarray | None = None,
         *,
         shape: tuple[int, int] | None = None,
-        image_mode: str = "RGB",
+        image_mode: Literal["RGB", "L"] = "RGB",
         invert_colors: bool = False,
-        source: str = "upload",
-        tool: str | None = None,
-        type: str = "pil",
+        source: Literal["upload", "webcam", "canvas"] = "upload",
+        tool: Literal["editor", "select", "sketch", "color-sketch"] | None = None,
+        type: Literal["pil"] = "pil",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = None,
@@ -336,8 +336,8 @@ def __init__(
         self,
         value: str | Callable | None = None,
         *,
-        format: str | None = "mp4",
-        source: str = "upload",
+        format: Literal["mp4"] | None = "mp4",
+        source: Literal["upload", "webcam"] = "upload",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = None,
@@ -373,8 +373,8 @@ def __init__(
         self,
         value: str | tuple[int, np.ndarray] | Callable | None = None,
         *,
-        source: str = "microphone",
-        type: str = "numpy",
+        source: Literal["microphone"] = "microphone",
+        type: Literal["numpy", "filepath"] = "numpy",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = None,
@@ -408,8 +408,8 @@ def __init__(
         self,
         value: str | list[str] | Callable | None = None,
         *,
-        file_count: str = "multiple",
-        type: str = "file",
+        file_count: Literal["multiple"] = "multiple",
+        type: Literal["file", "binary"] = "file",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = None,
@@ -445,10 +445,10 @@ def __init__(
         row_count: int | tuple[int, str] = (1, "dynamic"),
         col_count: int | tuple[int, str] | None = None,
         datatype: str | list[str] = "str",
-        type: str = "numpy",
+        type: Literal["numpy"] = "numpy",
         max_rows: int | None = 20,
         max_cols: int | None = None,
-        overflow_row_behaviour: str = "paginate",
+        overflow_row_behaviour: Literal["paginate", "show_ends"] = "paginate",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = None,
@@ -492,10 +492,10 @@ def __init__(
         row_count: int | tuple[int, str] = (1, "dynamic"),
         col_count: int | tuple[int, str] | None = None,
         datatype: str | list[str] = "str",
-        type: str = "array",
+        type: Literal["array"] = "array",
         max_rows: int | None = 20,
         max_cols: int | None = None,
-        overflow_row_behaviour: str = "paginate",
+        overflow_row_behaviour: Literal["paginate", "show_ends"] = "paginate",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = None,
@@ -537,12 +537,12 @@ def __init__(
         *,
         headers: list[str] | None = None,
         row_count: int | tuple[int, str] = (1, "dynamic"),
-        col_count: int | tuple[int, str] = 1,
+        col_count: Literal[1] = 1,
         datatype: str | list[str] = "str",
-        type: str = "array",
+        type: Literal["array"] = "array",
         max_rows: int | None = 20,
         max_cols: int | None = None,
-        overflow_row_behaviour: str = "paginate",
+        overflow_row_behaviour: Literal["paginate", "show_ends"] = "paginate",
         label: str | None = None,
         show_label: bool = True,
         interactive: bool | None = None,


Code review comments:
diff_hunk: @@ -59,11 +59,11 @@ def __init__(
         shape: tuple[int, int] | None = None,
         height: int | None = None,
         width: int | None = None,
-        image_mode: str = "RGB",
+        image_mode: Literal["RGB", "L"] = "RGB",
path: gradio/components/image.py
text: @user1:
Actually I think PIL supports quite a few more image modes: https://pillow.readthedocs.io/en/stable/handbook/concepts.html

diff_hunk: @@ -39,7 +39,20 @@ class Code(Changeable, Inputable, IOComponent, StringSerializable):
     def __init__(
         self,
         value: str | tuple[str] | None = None,
-        language: str | None = None,
+        language: Literal[
+            "python",
+            "markdown",
+            "json",
+            "html",
+            "css",
+            "javascript",
+            "typescript",
+            "yaml",
+            "dockerfile",
+            "shell",
+            "r",
+            None,
+        ] = None,
path: gradio/components/code.py
text: @user1:
```suggestion
        ] | None = None,
```