diff --git a/CHANGELOG.md b/CHANGELOG.md index f07e21e895..f6882e3d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ - Fixed bug where text for altair plots was not legible in dark mode by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3555](https://github.com/gradio-app/gradio/pull/3555) - Fixes `Chatbot` and `Image` components so that files passed during processing are added to a directory where they can be served from, by [@abidlabs](https://github.com/abidlabs) in [PR 3523](https://github.com/gradio-app/gradio/pull/3523) - Use Gradio API server to send telemetry using `huggingface_hub` [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3488](https://github.com/gradio-app/gradio/pull/3488) -- Fixes an issue where if the Blocks scope was not exited, then State could be shared across sessions, by [@abidlabs](https://github.com/abidlabs) in [PR 3600](https://github.com/gradio-app/gradio/pull/3600) +- Fixes an an issue where if the Blocks scope was not exited, then State could be shared across sessions, by [@abidlabs](https://github.com/abidlabs) in [PR 3600](https://github.com/gradio-app/gradio/pull/3600) +- Ensures that `gr.load()` loads and applies the upstream theme, by [@abidlabs](https://github.com/abidlabs) in [PR 3641](https://github.com/gradio-app/gradio/pull/3641) - Fixed bug where "or" was not being localized in file upload text by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3599](https://github.com/gradio-app/gradio/pull/3599) - Fixed bug where chatbot does not autoscroll inside of a tab, row or column by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3637](https://github.com/gradio-app/gradio/pull/3637) - Fixed bug where textbox shrinks when `lines` set to larger than 20 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3637](https://github.com/gradio-app/gradio/pull/3637) @@ -37,11 +38,12 @@ No changes to highlight. ## Full Changelog: -* Mobile responsive iframes in themes guide by [@aliabd](https://github.com/aliabd) in [PR 3562](https://github.com/gradio-app/gradio/pull/3562) -* Remove extra $demo from theme guide by [@aliabd](https://github.com/aliabd) in [PR 3563](https://github.com/gradio-app/gradio/pull/3563) -* Set the theme name to be the upstream repo name when loading from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3595](https://github.com/gradio-app/gradio/pull/3595) -* Copy everything in website Dockerfile, fix build issues by [@aliabd](https://github.com/aliabd) in [PR 3659](https://github.com/gradio-app/gradio/pull/3659) -* Raise error when an event is queued but the queue is not configured by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3640](https://github.com/gradio-app/gradio/pull/3640) +- Mobile responsive iframes in themes guide by [@aliabd](https://github.com/aliabd) in [PR 3562](https://github.com/gradio-app/gradio/pull/3562) +- Remove extra $demo from theme guide by [@aliabd](https://github.com/aliabd) in [PR 3563](https://github.com/gradio-app/gradio/pull/3563) +- Set the theme name to be the upstream repo name when loading from the hub by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3595](https://github.com/gradio-app/gradio/pull/3595) +- Copy everything in website Dockerfile, fix build issues by [@aliabd](https://github.com/aliabd) in [PR 3659](https://github.com/gradio-app/gradio/pull/3659) +- Raise error when an event is queued but the queue is not configured by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3640](https://github.com/gradio-app/gradio/pull/3640) +- Allows users to apss in a string name for a built-in theme, by [@abidlabs](https://github.com/abidlabs) in [PR 3641](https://github.com/gradio-app/gradio/pull/3641) ## Contributors Shoutout: diff --git a/gradio/blocks.py b/gradio/blocks.py index 9ffdae2573..01dd2b786a 100644 --- a/gradio/blocks.py +++ b/gradio/blocks.py @@ -55,6 +55,17 @@ if TYPE_CHECKING: # Only import for type checking (is False at runtime). from gradio.components import Component +BUILT_IN_THEMES: Dict[str, Theme] = { + t.name: t + for t in [ + themes.Base(), + themes.Default(), + themes.Monochrome(), + themes.Soft(), + themes.Glass(), + ] +} + class Block: def __init__( @@ -495,6 +506,7 @@ class Blocks(BlockContext): ): """ Parameters: + theme: a Theme object or a string representing a theme. If a string, will look for a built-in theme with that name (e.g. "soft" or "default"), or will attempt to load a theme from the HF Hub (e.g. "gradio/monochrome"). If None, will use the Default theme. analytics_enabled: whether to allow basic telemetry. If None, will use GRADIO_ANALYTICS_ENABLED environment variable or default to True. mode: a human-friendly name for the kind of Blocks or Interface being created. title: The tab title to display when this is opened in a browser window. @@ -506,11 +518,14 @@ class Blocks(BlockContext): if theme is None: theme = DefaultTheme() elif isinstance(theme, str): - try: - theme = Theme.from_hub(theme) - except Exception as e: - warnings.warn(f"Cannot load {theme}. Caught Exception: {str(e)}") - theme = DefaultTheme() + if theme.lower() in BUILT_IN_THEMES: + theme = BUILT_IN_THEMES[theme.lower()] + else: + try: + theme = Theme.from_hub(theme) + except Exception as e: + warnings.warn(f"Cannot load {theme}. Caught Exception: {str(e)}") + theme = DefaultTheme() if not isinstance(theme, Theme): warnings.warn("Theme should be a class loaded from gradio.themes") theme = DefaultTheme() @@ -570,16 +585,9 @@ class Blocks(BlockContext): self.file_directories = [] if self.analytics_enabled: - built_in_themes = [ - themes.Base(), - themes.Default(), - themes.Monochrome(), - themes.Soft(), - themes.Glass(), - ] is_custom_theme = not any( self.theme.to_dict() == built_in_theme.to_dict() - for built_in_theme in built_in_themes + for built_in_theme in BUILT_IN_THEMES.values() ) data = { "mode": self.mode, @@ -607,6 +615,7 @@ class Blocks(BlockContext): """ config = copy.deepcopy(config) components_config = config["components"] + theme = config.get("theme", "default") original_mapping: Dict[int, Block] = {} def get_block_instance(id: int) -> Block: @@ -644,7 +653,7 @@ class Blocks(BlockContext): derived_fields = ["types"] - with Blocks() as blocks: + with Blocks(theme=theme) as blocks: # ID 0 should be the root Blocks component original_mapping[0] = Context.root_block or blocks @@ -1138,6 +1147,7 @@ class Blocks(BlockContext): "is_colab": utils.colab_check(), "stylesheets": self.stylesheets, "root": self.root, + "theme": self.theme.name, } def getLayout(block): diff --git a/gradio/test_data/blocks_configs.py b/gradio/test_data/blocks_configs.py index d9d2df2e83..4e255bc2dc 100644 --- a/gradio/test_data/blocks_configs.py +++ b/gradio/test_data/blocks_configs.py @@ -3,6 +3,7 @@ XRAY_CONFIG = { "mode": "blocks", "dev_mode": True, "analytics_enabled": False, + "theme": "default", "components": [ { "id": 1, @@ -260,6 +261,7 @@ XRAY_CONFIG_DIFF_IDS = { "mode": "blocks", "dev_mode": True, "analytics_enabled": False, + "theme": "default", "components": [ { "id": 1, @@ -516,6 +518,7 @@ XRAY_CONFIG_WITH_MISTAKE = { "mode": "blocks", "dev_mode": True, "analytics_enabled": False, + "theme": "default", "components": [ { "id": 1, diff --git a/gradio/version.txt b/gradio/version.txt index 107f0fd3f5..f7b9dee139 100644 --- a/gradio/version.txt +++ b/gradio/version.txt @@ -1 +1 @@ -3.23.1b1 +3.23.1b3 \ No newline at end of file diff --git a/test/test_external.py b/test/test_external.py index 6eae11f0ff..ca9d09abfe 100644 --- a/test/test_external.py +++ b/test/test_external.py @@ -216,6 +216,7 @@ class TestLoadInterface: try: output = io("male", 77, 10) assert json.load(open(output))["label"] == "Perishes" + assert io.theme.name == "soft" except TooManyRequestsError: pass @@ -284,6 +285,7 @@ class TestLoadInterface: try: output = io("abc") assert output == "abc" + assert io.theme.name == "gradio/monochrome" except TooManyRequestsError: pass @@ -312,6 +314,7 @@ class TestLoadInterface: io = gr.load( "spaces/gradio-tests/test-loading-examples-private", api_key=api_key ) + assert io.theme.name == "default" app, _, _ = io.launch(prevent_thread_lock=True) test_client = TestClient(app) r = test_client.get(