Skip to content

Commit

Permalink
Merge branch 'main' into add-typed-dict-type-checking
Browse files Browse the repository at this point in the history
  • Loading branch information
adhami3310 committed Nov 19, 2024
2 parents c6c56f3 + 3f58cee commit da628f8
Show file tree
Hide file tree
Showing 25 changed files with 720 additions and 335 deletions.
1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration_app_harness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
- run: poetry run uv pip install pyvirtualdisplay pillow pytest-split
- name: Run app harness tests
env:
SCREENSHOT_DIR: /tmp/screenshots
SCREENSHOT_DIR: /tmp/screenshots/${{ matrix.state_manager }}/${{ matrix.python-version }}/${{ matrix.split_index }}
REDIS_URL: ${{ matrix.state_manager == 'redis' && 'redis://localhost:6379' || '' }}
run: |
poetry run playwright install --with-deps
Expand Down
2 changes: 1 addition & 1 deletion docker-example/production-app-platform/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
# Stage 1: init
FROM python:3.11 as init

ARG uv=/root/.cargo/bin/uv
ARG uv=/root/.local/bin/uv

# Install `uv` for faster package boostrapping
ADD --chmod=755 https://astral.sh/uv/install.sh /install.sh
Expand Down
2 changes: 1 addition & 1 deletion docker-example/production-compose/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Stage 1: init
FROM python:3.11 as init

ARG uv=/root/.cargo/bin/uv
ARG uv=/root/.local/bin/uv

# Install `uv` for faster package boostrapping
ADD --chmod=755 https://astral.sh/uv/install.sh /install.sh
Expand Down
367 changes: 175 additions & 192 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "reflex"
version = "0.6.5dev1"
version = "0.6.6dev1"
description = "Web apps in pure Python."
license = "Apache-2.0"
authors = [
Expand Down Expand Up @@ -49,7 +49,7 @@ wrapt = [
{version = ">=1.11.0,<2.0", python = "<3.11"},
]
packaging = ">=23.1,<25.0"
reflex-hosting-cli = ">=0.1.5,<2.0"
reflex-hosting-cli = ">=0.1.16,<2.0"
charset-normalizer = ">=3.3.2,<4.0"
wheel = ">=0.42.0,<1.0"
build = ">=1.0.3,<2.0"
Expand All @@ -59,6 +59,7 @@ twine = ">=4.0.0,<6.0"
tomlkit = ">=0.12.4,<1.0"
lazy_loader = ">=0.4"
reflex-chakra = ">=0.6.0"
typing_extensions = ">=4.6.0"

[tool.poetry.group.dev.dependencies]
pytest = ">=7.1.2,<9.0"
Expand Down
3 changes: 2 additions & 1 deletion reflex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@
"components.moment": ["MomentDelta", "moment"],
"config": ["Config", "DBConfig"],
"constants": ["Env"],
"constants.colors": ["Color"],
"event": [
"EventChain",
"EventHandler",
Expand Down Expand Up @@ -338,7 +339,7 @@
],
"istate.wrappers": ["get_state"],
"style": ["Style", "toggle_color_mode"],
"utils.imports": ["ImportVar"],
"utils.imports": ["ImportDict", "ImportVar"],
"utils.serializers": ["serializer"],
"vars": ["Var", "field", "Field"],
}
Expand Down
2 changes: 2 additions & 0 deletions reflex/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ from .components.suneditor import editor as editor
from .config import Config as Config
from .config import DBConfig as DBConfig
from .constants import Env as Env
from .constants.colors import Color as Color
from .event import EventChain as EventChain
from .event import EventHandler as EventHandler
from .event import background as background
Expand Down Expand Up @@ -192,6 +193,7 @@ from .state import dynamic as dynamic
from .state import var as var
from .style import Style as Style
from .style import toggle_color_mode as toggle_color_mode
from .utils.imports import ImportDict as ImportDict
from .utils.imports import ImportVar as ImportVar
from .utils.serializers import serializer as serializer
from .vars import Field as Field
Expand Down
4 changes: 2 additions & 2 deletions reflex/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ def get_value(self, key: str) -> Any:
Returns:
The value of the field.
"""
if isinstance(key, str) and key in self.__fields__:
if isinstance(key, str):
# Seems like this function signature was wrong all along?
# If the user wants a field that we know of, get it and pass it off to _get_value
key = getattr(self, key)
return getattr(self, key, key)
return key
135 changes: 99 additions & 36 deletions reflex/components/base/error_boundary.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

from __future__ import annotations

from typing import Dict, List, Tuple
from typing import Dict, Tuple

from reflex.compiler.compiler import _compile_component
from reflex.components.component import Component
from reflex.components.el import div, p
from reflex.event import EventHandler
from reflex.components.datadisplay.logo import svg_logo
from reflex.components.el import a, button, details, div, h2, hr, p, pre, summary
from reflex.event import EventHandler, set_clipboard
from reflex.state import FrontendEventExceptionState
from reflex.vars.base import Var
from reflex.vars.function import ArgsFunctionOperation


def on_error_spec(
Expand Down Expand Up @@ -40,38 +41,7 @@ class ErrorBoundary(Component):
on_error: EventHandler[on_error_spec]

# Rendered instead of the children when an error is caught.
Fallback_component: Var[Component] = Var(_js_expr="Fallback")._replace(
_var_type=Component
)

def add_custom_code(self) -> List[str]:
"""Add custom Javascript code into the page that contains this component.
Custom code is inserted at module level, after any imports.
Returns:
The custom code to add.
"""
fallback_container = div(
p("Ooops...Unknown Reflex error has occured:"),
p(
Var(_js_expr="error.message"),
color="red",
),
p("Please contact the support."),
)

compiled_fallback = _compile_component(fallback_container)

return [
f"""
function Fallback({{ error, resetErrorBoundary }}) {{
return (
{compiled_fallback}
);
}}
"""
]
fallback_render: Var[Component]

@classmethod
def create(cls, *children, **props):
Expand All @@ -86,6 +56,99 @@ def create(cls, *children, **props):
"""
if "on_error" not in props:
props["on_error"] = FrontendEventExceptionState.handle_frontend_exception
if "fallback_render" not in props:
props["fallback_render"] = ArgsFunctionOperation.create(
("event_args",),
Var.create(
div(
div(
div(
h2(
"An error occurred while rendering this page.",
font_size="1.25rem",
font_weight="bold",
),
p(
"This is an error with the application itself.",
opacity="0.75",
),
details(
summary("Error message", padding="0.5rem"),
div(
div(
pre(
Var(
_js_expr="event_args.error.stack",
),
),
padding="0.5rem",
width="fit-content",
),
width="100%",
max_height="50vh",
overflow="auto",
background="#000",
color="#fff",
border_radius="0.25rem",
),
button(
"Copy",
on_click=set_clipboard(
Var(_js_expr="event_args.error.stack"),
),
padding="0.35rem 0.75rem",
margin="0.5rem",
background="#fff",
color="#000",
border="1px solid #000",
border_radius="0.25rem",
font_weight="bold",
),
),
display="flex",
flex_direction="column",
gap="1rem",
max_width="50ch",
border="1px solid #888888",
border_radius="0.25rem",
padding="1rem",
),
hr(
border_color="currentColor",
opacity="0.25",
),
a(
div(
"Built with ",
svg_logo("currentColor"),
display="flex",
align_items="baseline",
justify_content="center",
font_family="monospace",
gap="0.5rem",
),
href="https://reflex.dev",
),
display="flex",
flex_direction="column",
gap="1rem",
),
height="100%",
width="100%",
position="absolute",
display="flex",
align_items="center",
justify_content="center",
)
),
_var_type=Component,
)
else:
props["fallback_render"] = ArgsFunctionOperation.create(
("event_args",),
props["fallback_render"],
_var_type=Component,
)
return super().create(*children, **props)


Expand Down
7 changes: 3 additions & 4 deletions reflex/components/base/error_boundary.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ------------------- DO NOT EDIT ----------------------
# This file was generated by `reflex/utils/pyi_generator.py`!
# ------------------------------------------------------
from typing import Any, Dict, List, Optional, Tuple, Union, overload
from typing import Any, Dict, Optional, Tuple, Union, overload

from reflex.components.component import Component
from reflex.event import BASE_STATE, EventType
Expand All @@ -15,13 +15,12 @@ def on_error_spec(
) -> Tuple[Var[str], Var[str]]: ...

class ErrorBoundary(Component):
def add_custom_code(self) -> List[str]: ...
@overload
@classmethod
def create( # type: ignore
cls,
*children,
Fallback_component: Optional[Union[Component, Var[Component]]] = None,
fallback_render: Optional[Union[Component, Var[Component]]] = None,
style: Optional[Style] = None,
key: Optional[Any] = None,
id: Optional[Any] = None,
Expand Down Expand Up @@ -57,7 +56,7 @@ class ErrorBoundary(Component):
Args:
*children: The children of the component.
on_error: Fired when the boundary catches an error.
Fallback_component: Rendered instead of the children when an error is caught.
fallback_render: Rendered instead of the children when an error is caught.
style: The style of the component.
key: A unique key for the component.
id: The id for the component.
Expand Down
16 changes: 11 additions & 5 deletions reflex/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -1920,6 +1920,11 @@ def wrapper(*children, **props) -> CustomComponent:
class NoSSRComponent(Component):
"""A dynamic component that is not rendered on the server."""

def _get_import_name(self) -> None | str:
if not self.library:
return None
return f"${self.library}" if self.library.startswith("/") else self.library

def _get_imports(self) -> ParsedImportDict:
"""Get the imports for the component.
Expand All @@ -1933,8 +1938,9 @@ def _get_imports(self) -> ParsedImportDict:
_imports = super()._get_imports()

# Do NOT import the main library/tag statically.
if self.library is not None:
_imports[self.library] = [
import_name = self._get_import_name()
if import_name is not None:
_imports[import_name] = [
imports.ImportVar(
tag=None,
render=False,
Expand All @@ -1952,10 +1958,10 @@ def _get_dynamic_imports(self) -> str:
opts_fragment = ", { ssr: false });"

# extract the correct import name from library name
if self.library is None:
base_import_name = self._get_import_name()
if base_import_name is None:
raise ValueError("Undefined library for NoSSRComponent")

import_name = format.format_library_name(self.library)
import_name = format.format_library_name(base_import_name)

library_import = f"const {self.alias if self.alias else self.tag} = dynamic(() => import('{import_name}')"
mod_import = (
Expand Down
8 changes: 8 additions & 0 deletions reflex/components/core/cond.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ def create_var(cond_part):
)


@overload
def color_mode_cond(light: Component, dark: Component | None = None) -> Component: ... # type: ignore


@overload
def color_mode_cond(light: Any, dark: Any = None) -> Var: ...


def color_mode_cond(light: Any, dark: Any = None) -> Var | Component:
"""Create a component or Prop based on color_mode.
Expand Down
Loading

0 comments on commit da628f8

Please sign in to comment.