add next/image and next-video in next namespace (#2223)

This commit is contained in:
Thomas Brandého 2023-12-07 19:38:47 +01:00 committed by GitHub
parent d6374ca3f0
commit caf32605ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 747 additions and 83 deletions

View File

@ -4,10 +4,13 @@ Anything imported here will be available in the default Reflex import as `rx.*`.
To signal to typecheckers that something should be reexported,
we use the Flask "import name as name" syntax.
"""
from __future__ import annotations
import importlib
from typing import Type
from reflex.page import page as page
from reflex.utils import console
from reflex.utils.format import to_snake_case
_ALL_COMPONENTS = [
@ -181,10 +184,6 @@ _ALL_COMPONENTS = [
"StatGroup",
"StatHelpText",
"StatLabel",
"StatArrow",
"StatGroup",
"StatHelpText",
"StatLabel",
"StatNumber",
"Step",
"StepDescription",
@ -250,7 +249,7 @@ _MAPPING = {
"reflex.base": ["base", "Base"],
"reflex.compiler": ["compiler"],
"reflex.compiler.utils": ["get_asset_path"],
"reflex.components": _ALL_COMPONENTS,
"reflex.components": _ALL_COMPONENTS + ["chakra", "next"],
"reflex.components.component": ["memo"],
"reflex.components.graphing": ["recharts"],
"reflex.components.datadisplay.moment": ["MomentDelta"],
@ -286,7 +285,31 @@ _MAPPING = {
"reflex.utils": ["utils"],
"reflex.vars": ["vars", "cached_var", "Var"],
}
_MAPPING = {value: key for key, values in _MAPPING.items() for value in values}
def _reverse_mapping(mapping: dict[str, list]) -> dict[str, str]:
"""Reverse the mapping used to lazy loading, and check for conflicting name.
Args:
mapping: The mapping to reverse.
Returns:
The reversed mapping.
"""
reversed_mapping = {}
for key, values in mapping.items():
for value in values:
if value not in reversed_mapping:
reversed_mapping[value] = key
else:
console.warn(
f"Key {value} is present multiple times in the imports _MAPPING: {key} / {reversed_mapping[value]}"
)
return reversed_mapping
# _MAPPING = {value: key for key, values in _MAPPING.items() for value in values}
_MAPPING = _reverse_mapping(_MAPPING)
def _removeprefix(text, prefix):

View File

@ -440,6 +440,8 @@ from reflex.components import clear_selected_files as clear_selected_files
from reflex.components import EditorButtonList as EditorButtonList
from reflex.components import EditorOptions as EditorOptions
from reflex.components import NoSSRComponent as NoSSRComponent
from reflex.components import chakra as chakra
from reflex.components import next as next
from reflex.components.component import memo as memo
from reflex.components.graphing import recharts as recharts
from reflex.components.datadisplay.moment import MomentDelta as MomentDelta

View File

@ -1,7 +1,9 @@
"""Import all the components."""
from __future__ import annotations
from . import next as next
from .base import Script
from .chakra import *
from .component import Component
from .component import NoSSRComponent as NoSSRComponent
from .datadisplay import *

View File

@ -0,0 +1,23 @@
"""Chakra components."""
import importlib
from typing import Type
from .media.image import Image
image = Image.create
# _MAPPING = {
# "image": "media",
# }
# def __getattr__(name: str) -> Type:
# print(f"importing {name}")
# if name not in _MAPPING:
# return importlib.import_module(name)
# module = importlib.import_module(_MAPPING[name], package=".")
# return getattr(module, name) if name != _MAPPING[name].rsplit(".")[-1] else module

View File

@ -1,13 +1,10 @@
"""An image component."""
from __future__ import annotations
import base64
import io
from typing import Any, Optional, Union
from reflex.components.component import Component
from reflex.components.libs.chakra import ChakraComponent, LiteralImageLoading
from reflex.utils.serializers import serializer
from reflex.vars import Var
@ -15,7 +12,7 @@ class Image(ChakraComponent):
"""Display an image."""
tag = "Image"
alias = "ChakraImage"
# How to align the image within its bounds. It maps to css `object-position` property.
align: Var[str]
@ -79,27 +76,3 @@ class Image(ChakraComponent):
if src is not None and not isinstance(src, (Var)):
props["src"] = Var.create(value=src, _var_is_string=True)
return super().create(*children, **props)
try:
from PIL.Image import Image as Img
@serializer
def serialize_image(image: Img) -> str:
"""Serialize a plotly figure.
Args:
image: The image to serialize.
Returns:
The serialized image.
"""
buff = io.BytesIO()
image.save(buff, format=getattr(image, "format", None) or "PNG")
image_bytes = buff.getvalue()
base64_image = base64.b64encode(image_bytes).decode("utf-8")
mime_type = getattr(image, "get_format_mimetype", lambda: "image/png")()
return f"data:{mime_type};base64,{base64_image}"
except ImportError:
pass

View File

@ -0,0 +1,120 @@
"""Stub file for reflex/components/chakra/media/image.py"""
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `scripts/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from reflex.vars import Var, BaseVar, ComputedVar
from reflex.event import EventChain, EventHandler, EventSpec
from reflex.style import Style
from typing import Any, Optional, Union
from reflex.components.component import Component
from reflex.components.libs.chakra import ChakraComponent, LiteralImageLoading
from reflex.vars import Var
class Image(ChakraComponent):
def get_event_triggers(self) -> dict[str, Union[Var, Any]]: ...
@overload
@classmethod
def create( # type: ignore
cls,
*children,
align: Optional[Union[Var[str], str]] = None,
fallback: Optional[Component] = None,
fallback_src: Optional[Union[Var[str], str]] = None,
fit: Optional[Union[Var[str], str]] = None,
html_height: Optional[Union[Var[str], str]] = None,
html_width: Optional[Union[Var[str], str]] = None,
ignore_fallback: Optional[Union[Var[bool], bool]] = None,
loading: Optional[
Union[Var[Literal["eager", "lazy"]], Literal["eager", "lazy"]]
] = None,
src: Optional[Union[Var[Any], Any]] = None,
alt: Optional[Union[Var[str], str]] = None,
src_set: Optional[Union[Var[str], str]] = None,
style: Optional[Style] = None,
key: Optional[Any] = None,
id: Optional[Any] = None,
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
on_blur: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_context_menu: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_double_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_error: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_focus: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_load: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_down: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_enter: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_leave: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_move: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_out: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_over: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_up: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_scroll: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_unmount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
**props
) -> "Image":
"""Create an Image component.
Args:
*children: The children of the image.
align: How to align the image within its bounds. It maps to css `object-position` property.
fallback: Fallback Reflex component to show if image is loading or image fails.
fallback_src: Fallback image src to show if image is loading or image fails.
fit: How the image to fit within its bounds. It maps to css `object-fit` property.
html_height: The native HTML height attribute to the passed to the img.
html_width: The native HTML width attribute to the passed to the img.
ignore_fallback: If true, opt out of the fallbackSrc logic and use as img.
loading: "eager" | "lazy"
src: The path/url to the image or PIL image object.
alt: The alt text of the image.
src_set: Provide multiple sources for an image, allowing the browser to select the most appropriate source based on factors like screen resolution and device capabilities. Learn more _[here](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)_
style: The style of the component.
key: A unique key for the component.
id: The id for the component.
class_name: The class name for the component.
autofocus: Whether the component should take the focus once the page is loaded
custom_attrs: custom attribute
**props: The props of the image.
Returns:
The Image component.
"""
...

View File

@ -785,6 +785,10 @@ class Component(BaseComponent, ABC):
for child in self.children:
dynamic_imports |= child.get_dynamic_imports()
for prop in self.get_component_props():
if getattr(self, prop) is not None:
dynamic_imports |= getattr(self, prop).get_dynamic_imports()
# Return the dynamic imports
return dynamic_imports

View File

@ -3,7 +3,6 @@
from .audio import Audio
from .avatar import Avatar, AvatarBadge, AvatarGroup
from .icon import Icon
from .image import Image
from .video import Video
__all__ = [f for f in dir() if f[0].isupper()] # type: ignore

View File

@ -0,0 +1,8 @@
"""Namespace for components provided by next packages."""
from .base import NextComponent
from .image import Image
from .video import Video
image = Image.create
video = Video.create

View File

@ -0,0 +1,8 @@
"""Base for NextJS components."""
from reflex.components.component import Component
class NextComponent(Component):
"""A Component used as based for any NextJS component."""
...

View File

@ -0,0 +1,91 @@
"""Stub file for reflex/components/next/base.py"""
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `scripts/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from reflex.vars import Var, BaseVar, ComputedVar
from reflex.event import EventChain, EventHandler, EventSpec
from reflex.style import Style
from reflex.components.component import Component
class NextComponent(Component):
...
@overload
@classmethod
def create( # type: ignore
cls,
*children,
style: Optional[Style] = None,
key: Optional[Any] = None,
id: Optional[Any] = None,
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
on_blur: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_context_menu: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_double_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_focus: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_down: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_enter: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_leave: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_move: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_out: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_over: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_up: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_scroll: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_unmount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
**props
) -> "NextComponent":
"""Create the component.
Args:
*children: The children of the component.
style: The style of the component.
key: A unique key for the component.
id: The id for the component.
class_name: The class name for the component.
autofocus: Whether the component should take the focus once the page is loaded
custom_attrs: custom attribute
**props: The props of the component.
Returns:
The component.
Raises:
TypeError: If an invalid child is passed.
"""
...

View File

@ -0,0 +1,140 @@
"""Image component from next/image."""
import base64
import io
from typing import Any, Dict, Literal, Optional, Union
from reflex.utils import types
from reflex.utils.serializers import serializer
from reflex.vars import Var
from .base import NextComponent
class Image(NextComponent):
"""Display an image."""
tag = "Image"
library = "next/image"
is_default = True
# This can be either an absolute external URL, or an internal path
src: Var[Any]
# Represents the rendered width in pixels, so it will affect how large the image appears.
width: Var[Any]
# Represents the rendered height in pixels, so it will affect how large the image appears.
height: Var[Any]
# Used to describe the image for screen readers and search engines.
alt: Var[str]
# A custom function used to resolve image URLs.
loader: Var[Any]
# A boolean that causes the image to fill the parent element, which is useful when the width and height are unknown. Default to True
fill: Var[bool]
# A string, similar to a media query, that provides information about how wide the image will be at different breakpoints.
sizes: Var[str]
# The quality of the optimized image, an integer between 1 and 100, where 100 is the best quality and therefore largest file size. Defaults to 75.
quality: Var[int]
# When true, the image will be considered high priority and preload. Lazy loading is automatically disabled for images using priority.
priority: Var[bool]
# A placeholder to use while the image is loading. Possible values are blur, empty, or data:image/.... Defaults to empty.
placeholder: Var[str]
# Allows passing CSS styles to the underlying image element.
# style: Var[Any]
# The loading behavior of the image. Defaults to lazy. Can hurt performance, recommended to use `priority` instead.
loading: Var[Literal["lazy", "eager"]]
# A Data URL to be used as a placeholder image before the src image successfully loads. Only takes effect when combined with placeholder="blur".
blurDataURL: Var[str]
def get_event_triggers(self) -> Dict[str, Any]:
"""The event triggers of the component.
Returns:
The dict describing the event triggers.
"""
return {
**super().get_event_triggers(),
"on_load": lambda: [],
"on_error": lambda: [],
}
@classmethod
def create(
cls,
*children,
width: Optional[Union[int, str]] = None,
height: Optional[Union[int, str]] = None,
**props,
):
"""Create an Image component from next/image.
Args:
*children: The children of the component.
width: The width of the image.
height: The height of the image.
**props:The props of the component.
Returns:
_type_: _description_
"""
style = props.get("style", {})
DEFAULT_W_H = "100%"
def check_prop_type(prop_name, prop_value):
if types.check_prop_in_allowed_types(prop_value, allowed_types=[int]):
props[prop_name] = prop_value
elif types.check_prop_in_allowed_types(prop_value, allowed_types=[str]):
props[prop_name] = 0
style[prop_name] = prop_value
else:
props[prop_name] = 0
style[prop_name] = DEFAULT_W_H
check_prop_type("width", width)
check_prop_type("height", height)
props["style"] = style
# mysteriously, following `sizes` prop is needed to avoid blury images.
props["sizes"] = "100vw"
src = props.get("src", None)
if src is not None and not isinstance(src, (Var)):
props["src"] = Var.create(value=src, _var_is_string=True)
return super().create(*children, **props)
try:
from PIL.Image import Image as Img
@serializer
def serialize_image(image: Img) -> str:
"""Serialize a plotly figure.
Args:
image: The image to serialize.
Returns:
The serialized image.
"""
buff = io.BytesIO()
image.save(buff, format=getattr(image, "format", None) or "PNG")
image_bytes = buff.getvalue()
base64_image = base64.b64encode(image_bytes).decode("utf-8")
mime_type = getattr(image, "get_format_mimetype", lambda: "image/png")()
return f"data:{mime_type};base64,{base64_image}"
except ImportError:
pass

View File

@ -0,0 +1,134 @@
"""Stub file for reflex/components/next/image.py"""
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `scripts/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from reflex.vars import Var, BaseVar, ComputedVar
from reflex.event import EventChain, EventHandler, EventSpec
from reflex.style import Style
import base64
import io
from typing import Any, Dict, Literal, Optional, Union
from reflex.utils import types
from reflex.utils.serializers import serializer
from reflex.vars import Var
from .base import NextComponent
class Image(NextComponent):
def get_event_triggers(self) -> Dict[str, Any]: ...
@overload
@classmethod
def create( # type: ignore
cls,
*children,
width: Optional[Union[str, int]] = None,
height: Optional[Union[str, int]] = None,
src: Optional[Union[Var[Any], Any]] = None,
alt: Optional[Union[Var[str], str]] = None,
loader: Optional[Union[Var[Any], Any]] = None,
fill: Optional[Union[Var[bool], bool]] = None,
sizes: Optional[Union[Var[str], str]] = None,
quality: Optional[Union[Var[int], int]] = None,
priority: Optional[Union[Var[bool], bool]] = None,
placeholder: Optional[Union[Var[str], str]] = None,
loading: Optional[
Union[Var[Literal["lazy", "eager"]], Literal["lazy", "eager"]]
] = None,
blurDataURL: Optional[Union[Var[str], str]] = None,
style: Optional[Style] = None,
key: Optional[Any] = None,
id: Optional[Any] = None,
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
on_blur: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_context_menu: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_double_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_error: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_focus: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_load: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_down: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_enter: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_leave: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_move: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_out: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_over: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_up: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_scroll: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_unmount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
**props
) -> "Image":
"""Create an Image component from next/image.
Args:
*children: The children of the component.
width: The width of the image.
height: The height of the image.
src: This can be either an absolute external URL, or an internal path
alt: Used to describe the image for screen readers and search engines.
loader: A custom function used to resolve image URLs.
fill: A boolean that causes the image to fill the parent element, which is useful when the width and height are unknown. Default to True
sizes: A string, similar to a media query, that provides information about how wide the image will be at different breakpoints.
quality: The quality of the optimized image, an integer between 1 and 100, where 100 is the best quality and therefore largest file size. Defaults to 75.
priority: When true, the image will be considered high priority and preload. Lazy loading is automatically disabled for images using priority.
placeholder: A placeholder to use while the image is loading. Possible values are blur, empty, or data:image/.... Defaults to empty.
loading: Allows passing CSS styles to the underlying image element. style: Var[Any] The loading behavior of the image. Defaults to lazy. Can hurt performance, recommended to use `priority` instead.
blurDataURL: A Data URL to be used as a placeholder image before the src image successfully loads. Only takes effect when combined with placeholder="blur".
style: The style of the component.
key: A unique key for the component.
id: The id for the component.
class_name: The class name for the component.
autofocus: Whether the component should take the focus once the page is loaded
custom_attrs: custom attribute
**props:The props of the component.
Returns:
_type_: _description_
"""
...
try:
from PIL.Image import Image as Img
@serializer
def serialize_image(image: Img) -> str: ...
except ImportError:
pass

View File

@ -0,0 +1,33 @@
"""Wrapping of the next-video component."""
from typing import Optional
from reflex.components.component import Component
from reflex.vars import Var
from .base import NextComponent
class Video(NextComponent):
"""A video component from NextJS."""
tag = "Video"
library = "next-video"
is_default = True
# the URL
src: Var[str]
as_: Optional[Component]
@classmethod
def create(cls, *children, **props) -> NextComponent:
"""Create a Video component.
Args:
*children: The children of the component.
**props: The props of the component.
Returns:
The Video component.
"""
return super().create(*children, **props)

View File

@ -0,0 +1,92 @@
"""Stub file for reflex/components/next/video.py"""
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `scripts/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, Literal, Optional, Union, overload
from reflex.vars import Var, BaseVar, ComputedVar
from reflex.event import EventChain, EventHandler, EventSpec
from reflex.style import Style
from typing import Optional
from reflex.components.component import Component
from reflex.vars import Var
from .base import NextComponent
class Video(NextComponent):
@overload
@classmethod
def create( # type: ignore
cls,
*children,
src: Optional[Union[Var[str], str]] = None,
as_: Optional[Component] = None,
style: Optional[Style] = None,
key: Optional[Any] = None,
id: Optional[Any] = None,
class_name: Optional[Any] = None,
autofocus: Optional[bool] = None,
custom_attrs: Optional[Dict[str, Union[Var, str]]] = None,
on_blur: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_context_menu: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_double_click: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_focus: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_down: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_enter: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_leave: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_move: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_out: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_over: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_mouse_up: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_scroll: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
on_unmount: Optional[
Union[EventHandler, EventSpec, list, function, BaseVar]
] = None,
**props
) -> "Video":
"""Create a Video component.
Args:
*children: The children of the component.
src: the URL
style: The style of the component.
key: A unique key for the component.
id: The id for the component.
class_name: The class name for the component.
autofocus: Whether the component should take the focus once the page is loaded
custom_attrs: custom attribute
**props: The props of the component.
Returns:
The Video component.
"""
...

View File

@ -272,6 +272,23 @@ def check_type_in_allowed_types(value_type: Type, allowed_types: Iterable) -> bo
return get_base_class(value_type) in allowed_types
def check_prop_in_allowed_types(prop: Any, allowed_types: Iterable) -> bool:
"""Check that a prop value is in a list of allowed types.
Does the check in a way that works regardless if it's a raw value or a state Var.
Args:
prop: The prop to check.
allowed_types: The list of allowed types.
Returns:
If the prop type match one of the allowed_types.
"""
from reflex.vars import Var
type_ = prop._var_type if _isinstance(prop, Var) else type(prop)
return type_ in allowed_types
# Store this here for performance.
StateBases = get_base_class(StateVar)
StateIterBases = get_base_class(StateIterVar)

View File

@ -1,63 +1,58 @@
# PIL is only available in python 3.8+
import numpy as np
import PIL
import pytest
from PIL.Image import Image as Img
try:
# PIL is only available in python 3.8+
import numpy as np
import PIL
from PIL.Image import Image as Img
import reflex as rx
from reflex.components.next.image import Image, serialize_image # type: ignore
from reflex.utils.serializers import serialize
import reflex as rx
from reflex.components.media.image import Image, serialize_image # type: ignore
from reflex.utils.serializers import serialize
@pytest.fixture
def pil_image() -> Img:
"""Get an image.
@pytest.fixture
def pil_image() -> Img:
"""Get an image.
Returns:
A random PIL image.
"""
imarray = np.random.rand(100, 100, 3) * 255
return PIL.Image.fromarray(imarray.astype("uint8")).convert("RGBA") # type: ignore
Returns:
A random PIL image.
"""
imarray = np.random.rand(100, 100, 3) * 255
return PIL.Image.fromarray(imarray.astype("uint8")).convert("RGBA") # type: ignore
def test_serialize_image(pil_image: Img):
"""Test that serializing an image works.
Args:
pil_image: The image to serialize.
"""
data = serialize(pil_image)
assert isinstance(data, str)
assert data == serialize_image(pil_image)
assert data.startswith("data:image/png;base64,")
def test_serialize_image(pil_image: Img):
"""Test that serializing an image works.
def test_set_src_str():
"""Test that setting the src works."""
image = rx.image(src="pic2.jpeg")
assert str(image.src) == "{`pic2.jpeg`}" # type: ignore
Args:
pil_image: The image to serialize.
"""
data = serialize(pil_image)
assert isinstance(data, str)
assert data == serialize_image(pil_image)
assert data.startswith("data:image/png;base64,")
def test_set_src_img(pil_image: Img):
"""Test that setting the src works.
Args:
pil_image: The image to serialize.
"""
image = Image.create(src=pil_image)
assert str(image.src._var_name) == serialize_image(pil_image) # type: ignore
def test_set_src_str():
"""Test that setting the src works."""
image = rx.image(src="pic2.jpeg")
assert str(image.src) == "{`pic2.jpeg`}" # type: ignore
def test_render(pil_image: Img):
"""Test that rendering an image works.
Args:
pil_image: The image to serialize.
"""
image = Image.create(src=pil_image)
assert image.src._var_is_string # type: ignore
def test_set_src_img(pil_image: Img):
"""Test that setting the src works.
except ImportError:
Args:
pil_image: The image to serialize.
"""
image = Image.create(src=pil_image)
assert str(image.src._var_name) == serialize_image(pil_image) # type: ignore
def test_pillow_import():
"""Make sure the Python version is less than 3.8."""
import sys
assert sys.version_info < (3, 8)
def test_render(pil_image: Img):
"""Test that rendering an image works.
Args:
pil_image: The image to serialize.
"""
image = Image.create(src=pil_image)
assert image.src._var_is_string # type: ignore