-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Language Agnostic Typing in /info
route
#4039
Changes from 17 commits
46f8b7e
61e1f1f
7a021e0
47b3913
c658d54
cdf53d3
41dcd56
2581fb5
b3a1649
37c188b
67724b5
7b9bbf8
b603caf
95e176b
205a3e4
30cef95
7dce123
5f029be
c041345
e8d3102
fdfe9f3
f9e8d19
114bab7
09421eb
1c6dca0
9a22631
faa003c
fceafef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,12 @@ | |
from gradio_client import serializing, utils | ||
from gradio_client.documentation import document, set_documentation_group | ||
from gradio_client.serializing import Serializable | ||
from gradio_client.utils import Communicator, JobStatus, Status, StatusUpdate | ||
from gradio_client.utils import ( | ||
Communicator, | ||
JobStatus, | ||
Status, | ||
StatusUpdate, | ||
) | ||
|
||
set_documentation_group("py-client") | ||
|
||
|
@@ -402,14 +407,15 @@ def view_api( | |
# Versions of Gradio older than 3.26 returned format of the API info | ||
# from the /info endpoint | ||
if ( | ||
version.parse(self.config.get("version", "2.0")) >= version.Version("3.26") | ||
version.parse(self.config.get("version", "2.0")) > version.Version("3.28.1") | ||
and r.ok | ||
): | ||
info = r.json() | ||
else: | ||
fetch = requests.post( | ||
utils.SPACE_FETCHER_URL, | ||
json={"serialize": self.serialize, "config": json.dumps(self.config)}, | ||
# Serialize has no effect | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ignore this comment - will delete |
||
json={"config": json.dumps(self.config), "serialize": self.serialize}, | ||
) | ||
if fetch.ok: | ||
info = fetch.json()["api"] | ||
|
@@ -449,7 +455,7 @@ def reset_session(self) -> None: | |
def _render_endpoints_info( | ||
self, | ||
name_or_index: str | int, | ||
endpoints_info: Dict[str, List[Dict[str, str]]], | ||
endpoints_info: Dict[str, List[Dict[str, Any]]], | ||
) -> str: | ||
parameter_names = [p["label"] for p in endpoints_info["parameters"]] | ||
parameter_names = [utils.sanitize_parameter_names(p) for p in parameter_names] | ||
|
@@ -473,13 +479,25 @@ def _render_endpoints_info( | |
human_info += " Parameters:\n" | ||
if endpoints_info["parameters"]: | ||
for info in endpoints_info["parameters"]: | ||
human_info += f" - [{info['component']}] {utils.sanitize_parameter_names(info['label'])}: {info['type_python']} ({info['type_description']})\n" | ||
desc = ( | ||
f" ({info['python_type']['description']})" | ||
if info["python_type"].get("description") | ||
else "" | ||
abidlabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
type_ = info["python_type"]["type"] | ||
human_info += f" - [{info['component']}] {utils.sanitize_parameter_names(info['label'])}: {type_}{desc} \n" | ||
else: | ||
human_info += " - None\n" | ||
human_info += " Returns:\n" | ||
if endpoints_info["returns"]: | ||
for info in endpoints_info["returns"]: | ||
human_info += f" - [{info['component']}] {utils.sanitize_parameter_names(info['label'])}: {info['type_python']} ({info['type_description']})\n" | ||
desc = ( | ||
f" ({info['python_type']['description']})" | ||
if info["python_type"].get("description") | ||
else "" | ||
abidlabs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
type_ = info["python_type"]["type"] | ||
human_info += f" - [{info['component']}] {utils.sanitize_parameter_names(info['label'])}: {type_}{desc} \n" | ||
else: | ||
human_info += " - None\n" | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,8 +9,17 @@ | |
from gradio_client import media_data, utils | ||
from gradio_client.data_classes import FileData | ||
|
||
serializer_types = json.load(open(Path(__file__).parent / "types.json")) | ||
|
||
|
||
class Serializable: | ||
def serialized_info(self): | ||
""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This docstring is out of date |
||
The typing information for this component as a dictionary whose values are a list of 2 strings: [Python type, language-agnostic description]. | ||
Keys of the dictionary are: raw_input, raw_output, serialized_input, serialized_output | ||
""" | ||
return self.api_info() | ||
|
||
def api_info(self) -> Dict[str, List[str]]: | ||
""" | ||
The typing information for this component as a dictionary whose values are a list of 2 strings: [Python type, language-agnostic description]. | ||
|
@@ -57,12 +66,10 @@ def deserialize( | |
class SimpleSerializable(Serializable): | ||
"""General class that does not perform any serialization or deserialization.""" | ||
|
||
def api_info(self) -> Dict[str, str | List[str]]: | ||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return { | ||
"raw_input": ["Any", ""], | ||
"raw_output": ["Any", ""], | ||
"serialized_input": ["Any", ""], | ||
"serialized_output": ["Any", ""], | ||
"info": serializer_types["SimpleSerializable"], | ||
"serialized_info": False, | ||
} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
|
@@ -75,12 +82,10 @@ def example_inputs(self) -> Dict[str, Any]: | |
class StringSerializable(Serializable): | ||
"""Expects a string as input/output but performs no serialization.""" | ||
|
||
def api_info(self) -> Dict[str, List[str]]: | ||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return { | ||
"raw_input": ["str", "string value"], | ||
"raw_output": ["str", "string value"], | ||
"serialized_input": ["str", "string value"], | ||
"serialized_output": ["str", "string value"], | ||
"info": serializer_types["StringSerializable"], | ||
"serialized_info": False, | ||
} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
|
@@ -93,12 +98,10 @@ def example_inputs(self) -> Dict[str, Any]: | |
class ListStringSerializable(Serializable): | ||
"""Expects a list of strings as input/output but performs no serialization.""" | ||
|
||
def api_info(self) -> Dict[str, List[str]]: | ||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return { | ||
"raw_input": ["List[str]", "list of string values"], | ||
"raw_output": ["List[str]", "list of string values"], | ||
"serialized_input": ["List[str]", "list of string values"], | ||
"serialized_output": ["List[str]", "list of string values"], | ||
"info": serializer_types["ListStringSerializable"], | ||
"serialized_info": False, | ||
} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
|
@@ -111,15 +114,13 @@ def example_inputs(self) -> Dict[str, Any]: | |
class BooleanSerializable(Serializable): | ||
"""Expects a boolean as input/output but performs no serialization.""" | ||
|
||
def api_info(self) -> Dict[str, List[str]]: | ||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return { | ||
"raw_input": ["bool", "boolean value"], | ||
"raw_output": ["bool", "boolean value"], | ||
"serialized_input": ["bool", "boolean value"], | ||
"serialized_output": ["bool", "boolean value"], | ||
"info": serializer_types["BooleanSerializable"], | ||
"serialized_info": False, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can get rid of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool I was wondering about that as well. Why some components have it and why others don't |
||
} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
def example_inputs(self) -> Dict[str, Dict | bool]: | ||
return { | ||
"raw": True, | ||
"serialized": True, | ||
|
@@ -129,12 +130,10 @@ def example_inputs(self) -> Dict[str, Any]: | |
class NumberSerializable(Serializable): | ||
"""Expects a number (int/float) as input/output but performs no serialization.""" | ||
|
||
def api_info(self) -> Dict[str, List[str]]: | ||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return { | ||
"raw_input": ["int | float", "numeric value"], | ||
"raw_output": ["int | float", "numeric value"], | ||
"serialized_input": ["int | float", "numeric value"], | ||
"serialized_output": ["int | float", "numeric value"], | ||
"info": serializer_types["NumberSerializable"], | ||
"serialized_info": False, | ||
} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
|
@@ -147,13 +146,11 @@ def example_inputs(self) -> Dict[str, Any]: | |
class ImgSerializable(Serializable): | ||
"""Expects a base64 string as input/output which is serialized to a filepath.""" | ||
|
||
def api_info(self) -> Dict[str, List[str]]: | ||
return { | ||
"raw_input": ["str", "base64 representation of image"], | ||
"raw_output": ["str", "base64 representation of image"], | ||
"serialized_input": ["str", "filepath or URL to image"], | ||
"serialized_output": ["str", "filepath or URL to image"], | ||
} | ||
def serialized_info(self): | ||
return {"type": "string", "description": "filepath or URL to image"} | ||
|
||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return {"info": serializer_types["ImgSerializable"], "serialized_info": True} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
return { | ||
|
@@ -204,19 +201,11 @@ def deserialize( | |
class FileSerializable(Serializable): | ||
"""Expects a dict with base64 representation of object as input/output which is serialized to a filepath.""" | ||
|
||
def api_info(self) -> Dict[str, List[str]]: | ||
return { | ||
"raw_input": [ | ||
"str | Dict", | ||
"base64 string representation of file; or a dictionary-like object, the keys should be either: is_file (False), data (base64 representation of file) or is_file (True), name (str filename)", | ||
], | ||
"raw_output": [ | ||
"Dict", | ||
"dictionary-like object with keys: name (str filename), data (base64 representation of file), is_file (bool, set to False)", | ||
], | ||
"serialized_input": ["str", "filepath or URL to file"], | ||
"serialized_output": ["str", "filepath or URL to file"], | ||
} | ||
def serialized_info(self): | ||
return {"type": "string", "description": "filepath or URL to file"} | ||
|
||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return {"info": serializer_types["FileSerializable"], "serialized_info": True} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
return { | ||
|
@@ -331,19 +320,11 @@ def deserialize( | |
|
||
|
||
class VideoSerializable(FileSerializable): | ||
def api_info(self) -> Dict[str, List[str]]: | ||
return { | ||
"raw_input": [ | ||
"str | Dict", | ||
"base64 string representation of file; or a dictionary-like object, the keys should be either: is_file (False), data (base64 representation of file) or is_file (True), name (str filename)", | ||
], | ||
"raw_output": [ | ||
"Tuple[Dict, Dict]", | ||
"a tuple of 2 dictionary-like object with keys: name (str filename), data (base64 representation of file), is_file (bool, set to False). First dictionary is for the video, second dictionary is for the subtitles.", | ||
], | ||
"serialized_input": ["str", "filepath or URL to file"], | ||
"serialized_output": ["str", "filepath or URL to file"], | ||
} | ||
def serialized_info(self): | ||
return {"type": "string", "description": "filepath or URL to video file"} | ||
|
||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return {"info": serializer_types["FileSerializable"], "serialized_info": True} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
return { | ||
|
@@ -378,13 +359,11 @@ def deserialize( | |
|
||
|
||
class JSONSerializable(Serializable): | ||
def api_info(self) -> Dict[str, List[str]]: | ||
return { | ||
"raw_input": ["str | Dict | List", "JSON-serializable object or a string"], | ||
"raw_output": ["Dict | List", "dictionary- or list-like object"], | ||
"serialized_input": ["str", "filepath to JSON file"], | ||
"serialized_output": ["str", "filepath to JSON file"], | ||
} | ||
def serialized_info(self): | ||
return {"type": "string", "description": "filepath to JSON file"} | ||
|
||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return {"info": serializer_types["JSONSerializable"], "serialized_info": True} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
return { | ||
|
@@ -430,24 +409,16 @@ def deserialize( | |
|
||
|
||
class GallerySerializable(Serializable): | ||
def api_info(self) -> Dict[str, List[str]]: | ||
def serialized_info(self): | ||
return { | ||
"type": "string", | ||
"description": "path to directory with images and a file associating images with captions called captions.json", | ||
} | ||
|
||
def api_info(self) -> Dict[str, Dict | bool]: | ||
return { | ||
"raw_input": [ | ||
"List[List[str | None]]", | ||
"List of lists. The inner lists should contain two elements: a base64 file representation and an optional caption, the outer list should contain one such list for each image in the gallery.", | ||
], | ||
"raw_output": [ | ||
"List[List[str | None]]", | ||
"List of lists. The inner lists should contain two elements: a base64 file representation and an optional caption, the outer list should contain one such list for each image in the gallery.", | ||
], | ||
"serialized_input": [ | ||
"str", | ||
"path to directory with images and a file associating images with captions called captions.json", | ||
], | ||
"serialized_output": [ | ||
"str", | ||
"path to directory with images and a file associating images with captions called captions.json", | ||
], | ||
"info": serializer_types["GallerySerializable"], | ||
"serialized_info": True, | ||
} | ||
|
||
def example_inputs(self) -> Dict[str, Any]: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now