remove all runtime asserts (#4019)
* remove all runtime asserts * Update reflex/testing.py Co-authored-by: Masen Furer <m_github@0x26.net> --------- Co-authored-by: Masen Furer <m_github@0x26.net>
This commit is contained in:
parent
62021b0b40
commit
23e979717f
@ -482,9 +482,8 @@ class App(MiddlewareMixin, LifespanMixin, Base):
|
|||||||
"""
|
"""
|
||||||
# If the route is not set, get it from the callable.
|
# If the route is not set, get it from the callable.
|
||||||
if route is None:
|
if route is None:
|
||||||
assert isinstance(
|
if not isinstance(component, Callable):
|
||||||
component, Callable
|
raise ValueError("Route must be set if component is not a callable.")
|
||||||
), "Route must be set if component is not a callable."
|
|
||||||
# Format the route.
|
# Format the route.
|
||||||
route = format.format_route(component.__name__)
|
route = format.format_route(component.__name__)
|
||||||
else:
|
else:
|
||||||
@ -1528,6 +1527,9 @@ class EventNamespace(AsyncNamespace):
|
|||||||
async def on_event(self, sid, data):
|
async def on_event(self, sid, data):
|
||||||
"""Event for receiving front-end websocket events.
|
"""Event for receiving front-end websocket events.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RuntimeError: If the Socket.IO is badly initialized.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
sid: The Socket.IO session id.
|
sid: The Socket.IO session id.
|
||||||
data: The event data.
|
data: The event data.
|
||||||
@ -1540,9 +1542,11 @@ class EventNamespace(AsyncNamespace):
|
|||||||
self.sid_to_token[sid] = event.token
|
self.sid_to_token[sid] = event.token
|
||||||
|
|
||||||
# Get the event environment.
|
# Get the event environment.
|
||||||
assert self.app.sio is not None
|
if self.app.sio is None:
|
||||||
|
raise RuntimeError("Socket.IO is not initialized.")
|
||||||
environ = self.app.sio.get_environ(sid, self.namespace)
|
environ = self.app.sio.get_environ(sid, self.namespace)
|
||||||
assert environ is not None
|
if environ is None:
|
||||||
|
raise RuntimeError("Socket.IO environ is not initialized.")
|
||||||
|
|
||||||
# Get the client headers.
|
# Get the client headers.
|
||||||
headers = {
|
headers = {
|
||||||
|
@ -44,6 +44,9 @@ def compile_import_statement(fields: list[ImportVar]) -> tuple[str, list[str]]:
|
|||||||
Args:
|
Args:
|
||||||
fields: The set of fields to import from the library.
|
fields: The set of fields to import from the library.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If there is more than one default import.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The libraries for default and rest.
|
The libraries for default and rest.
|
||||||
default: default library. When install "import def from library".
|
default: default library. When install "import def from library".
|
||||||
@ -54,7 +57,8 @@ def compile_import_statement(fields: list[ImportVar]) -> tuple[str, list[str]]:
|
|||||||
|
|
||||||
# Check for default imports.
|
# Check for default imports.
|
||||||
defaults = {field for field in fields_set if field.is_default}
|
defaults = {field for field in fields_set if field.is_default}
|
||||||
assert len(defaults) < 2
|
if len(defaults) >= 2:
|
||||||
|
raise ValueError("Only one default import is allowed.")
|
||||||
|
|
||||||
# Get the default import, and the specific imports.
|
# Get the default import, and the specific imports.
|
||||||
default = next(iter({field.name for field in defaults}), "")
|
default = next(iter({field.name for field in defaults}), "")
|
||||||
@ -92,6 +96,9 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]:
|
|||||||
Args:
|
Args:
|
||||||
import_dict: The import dict to compile.
|
import_dict: The import dict to compile.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If an import in the dict is invalid.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The list of import dict.
|
The list of import dict.
|
||||||
"""
|
"""
|
||||||
@ -106,8 +113,10 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if not lib:
|
if not lib:
|
||||||
assert not default, "No default field allowed for empty library."
|
if default:
|
||||||
assert rest is not None and len(rest) > 0, "No fields to import."
|
raise ValueError("No default field allowed for empty library.")
|
||||||
|
if rest is None or len(rest) == 0:
|
||||||
|
raise ValueError("No fields to import.")
|
||||||
for module in sorted(rest):
|
for module in sorted(rest):
|
||||||
import_dicts.append(get_import_dict(module))
|
import_dicts.append(get_import_dict(module))
|
||||||
continue
|
continue
|
||||||
|
@ -16,13 +16,15 @@ class Title(Component):
|
|||||||
def render(self) -> dict:
|
def render(self) -> dict:
|
||||||
"""Render the title component.
|
"""Render the title component.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the title is not a single string.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The rendered title component.
|
The rendered title component.
|
||||||
"""
|
"""
|
||||||
# Make sure the title is a single string.
|
# Make sure the title is a single string.
|
||||||
assert len(self.children) == 1 and isinstance(
|
if len(self.children) != 1 or not isinstance(self.children[0], Bare):
|
||||||
self.children[0], Bare
|
raise ValueError("Title must be a single string.")
|
||||||
), "Title must be a single string."
|
|
||||||
return super().render()
|
return super().render()
|
||||||
|
|
||||||
|
|
||||||
|
@ -1744,10 +1744,14 @@ class CustomComponent(Component):
|
|||||||
Args:
|
Args:
|
||||||
seen: The tags of the components that have already been seen.
|
seen: The tags of the components that have already been seen.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the tag is not set.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The set of custom components.
|
The set of custom components.
|
||||||
"""
|
"""
|
||||||
assert self.tag is not None, "The tag must be set."
|
if self.tag is None:
|
||||||
|
raise ValueError("The tag must be set.")
|
||||||
|
|
||||||
# Store the seen components in a set to avoid infinite recursion.
|
# Store the seen components in a set to avoid infinite recursion.
|
||||||
if seen is None:
|
if seen is None:
|
||||||
|
@ -138,13 +138,13 @@ def cond(condition: Any, c1: Any, c2: Any = None) -> Component | Var:
|
|||||||
"""
|
"""
|
||||||
# Convert the condition to a Var.
|
# Convert the condition to a Var.
|
||||||
cond_var = LiteralVar.create(condition)
|
cond_var = LiteralVar.create(condition)
|
||||||
assert cond_var is not None, "The condition must be set."
|
if cond_var is None:
|
||||||
|
raise ValueError("The condition must be set.")
|
||||||
|
|
||||||
# If the first component is a component, create a Cond component.
|
# If the first component is a component, create a Cond component.
|
||||||
if isinstance(c1, BaseComponent):
|
if isinstance(c1, BaseComponent):
|
||||||
assert c2 is None or isinstance(
|
if c2 is not None and not isinstance(c2, BaseComponent):
|
||||||
c2, BaseComponent
|
raise ValueError("Both arguments must be components.")
|
||||||
), "Both arguments must be components."
|
|
||||||
return Cond.create(cond_var, c1, c2)
|
return Cond.create(cond_var, c1, c2)
|
||||||
|
|
||||||
# Otherwise, create a conditional Var.
|
# Otherwise, create a conditional Var.
|
||||||
|
@ -124,7 +124,8 @@ class DataTable(Gridjs):
|
|||||||
if types.is_dataframe(type(self.data)):
|
if types.is_dataframe(type(self.data)):
|
||||||
# If given a pandas df break up the data and columns
|
# If given a pandas df break up the data and columns
|
||||||
data = serialize(self.data)
|
data = serialize(self.data)
|
||||||
assert isinstance(data, dict), "Serialized dataframe should be a dict."
|
if not isinstance(data, dict):
|
||||||
|
raise ValueError("Serialized dataframe should be a dict.")
|
||||||
self.columns = LiteralVar.create(data["columns"])
|
self.columns = LiteralVar.create(data["columns"])
|
||||||
self.data = LiteralVar.create(data["data"])
|
self.data = LiteralVar.create(data["data"])
|
||||||
|
|
||||||
|
@ -95,12 +95,16 @@ class Markdown(Component):
|
|||||||
*children: The children of the component.
|
*children: The children of the component.
|
||||||
**props: The properties of the component.
|
**props: The properties of the component.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the children are not valid.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The markdown component.
|
The markdown component.
|
||||||
"""
|
"""
|
||||||
assert (
|
if len(children) != 1 or not types._isinstance(children[0], Union[str, Var]):
|
||||||
len(children) == 1 and types._isinstance(children[0], Union[str, Var])
|
raise ValueError(
|
||||||
), "Markdown component must have exactly one child containing the markdown source."
|
"Markdown component must have exactly one child containing the markdown source."
|
||||||
|
)
|
||||||
|
|
||||||
# Update the base component map with the custom component map.
|
# Update the base component map with the custom component map.
|
||||||
component_map = {**get_base_component_map(), **props.pop("component_map", {})}
|
component_map = {**get_base_component_map(), **props.pop("component_map", {})}
|
||||||
|
@ -93,6 +93,9 @@ class Markdown(Component):
|
|||||||
custom_attrs: custom attribute
|
custom_attrs: custom attribute
|
||||||
**props: The properties of the component.
|
**props: The properties of the component.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the children are not valid.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The markdown component.
|
The markdown component.
|
||||||
"""
|
"""
|
||||||
|
@ -114,6 +114,9 @@ class IterTag(Tag):
|
|||||||
def render_component(self) -> Component:
|
def render_component(self) -> Component:
|
||||||
"""Render the component.
|
"""Render the component.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the render function takes more than 2 arguments.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The rendered component.
|
The rendered component.
|
||||||
"""
|
"""
|
||||||
@ -132,7 +135,8 @@ class IterTag(Tag):
|
|||||||
component = self.render_fn(arg)
|
component = self.render_fn(arg)
|
||||||
else:
|
else:
|
||||||
# If the render function takes the index as an argument.
|
# If the render function takes the index as an argument.
|
||||||
assert len(args) == 2
|
if len(args) != 2:
|
||||||
|
raise ValueError("The render function must take 2 arguments.")
|
||||||
component = self.render_fn(arg, index)
|
component = self.render_fn(arg, index)
|
||||||
|
|
||||||
# Nested foreach components or cond must be wrapped in fragments.
|
# Nested foreach components or cond must be wrapped in fragments.
|
||||||
|
@ -1062,6 +1062,9 @@ def fix_events(
|
|||||||
token: The user token.
|
token: The user token.
|
||||||
router_data: The optional router data to set in the event.
|
router_data: The optional router data to set in the event.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the event type is not what was expected.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The fixed events.
|
The fixed events.
|
||||||
"""
|
"""
|
||||||
@ -1085,7 +1088,8 @@ def fix_events(
|
|||||||
# Otherwise, create an event from the event spec.
|
# Otherwise, create an event from the event spec.
|
||||||
if isinstance(e, EventHandler):
|
if isinstance(e, EventHandler):
|
||||||
e = e()
|
e = e()
|
||||||
assert isinstance(e, EventSpec), f"Unexpected event type, {type(e)}."
|
if not isinstance(e, EventSpec):
|
||||||
|
raise ValueError(f"Unexpected event type, {type(e)}.")
|
||||||
name = format.format_event_handler(e.handler)
|
name = format.format_event_handler(e.handler)
|
||||||
payload = {k._js_expr: v._decode() for k, v in e.args} # type: ignore
|
payload = {k._js_expr: v._decode() for k, v in e.args} # type: ignore
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ def asset(relative_filename: str, subfolder: Optional[str] = None) -> str:
|
|||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
FileNotFoundError: If the file does not exist.
|
FileNotFoundError: If the file does not exist.
|
||||||
|
ValueError: If the module is None.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The relative URL to the copied asset.
|
The relative URL to the copied asset.
|
||||||
@ -31,7 +32,8 @@ def asset(relative_filename: str, subfolder: Optional[str] = None) -> str:
|
|||||||
# Determine the file by which the asset is exposed.
|
# Determine the file by which the asset is exposed.
|
||||||
calling_file = inspect.stack()[1].filename
|
calling_file = inspect.stack()[1].filename
|
||||||
module = inspect.getmodule(inspect.stack()[1][0])
|
module = inspect.getmodule(inspect.stack()[1][0])
|
||||||
assert module is not None
|
if module is None:
|
||||||
|
raise ValueError("Module is None")
|
||||||
caller_module_path = module.__name__.replace(".", "/")
|
caller_module_path = module.__name__.replace(".", "/")
|
||||||
|
|
||||||
subfolder = f"{caller_module_path}/{subfolder}" if subfolder else caller_module_path
|
subfolder = f"{caller_module_path}/{subfolder}" if subfolder else caller_module_path
|
||||||
|
@ -91,12 +91,16 @@ class ClientStateVar(Var):
|
|||||||
default: The default value of the variable.
|
default: The default value of the variable.
|
||||||
global_ref: Whether the state should be accessible in any Component and on the backend.
|
global_ref: Whether the state should be accessible in any Component and on the backend.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the var_name is not a string.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
ClientStateVar
|
ClientStateVar
|
||||||
"""
|
"""
|
||||||
if var_name is None:
|
if var_name is None:
|
||||||
var_name = get_unique_variable_name()
|
var_name = get_unique_variable_name()
|
||||||
assert isinstance(var_name, str), "var_name must be a string."
|
if not isinstance(var_name, str):
|
||||||
|
raise ValueError("var_name must be a string.")
|
||||||
if default is NoValue:
|
if default is NoValue:
|
||||||
default_var = Var(_js_expr="")
|
default_var = Var(_js_expr="")
|
||||||
elif not isinstance(default, Var):
|
elif not isinstance(default, Var):
|
||||||
|
@ -12,10 +12,12 @@ async def run_in_thread(func) -> Any:
|
|||||||
Args:
|
Args:
|
||||||
func (callable): The non-async function to run.
|
func (callable): The non-async function to run.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the function is an async function.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Any: The return value of the function.
|
Any: The return value of the function.
|
||||||
"""
|
"""
|
||||||
assert not asyncio.coroutines.iscoroutinefunction(
|
if asyncio.coroutines.iscoroutinefunction(func):
|
||||||
func
|
raise ValueError("func must be a non-async function")
|
||||||
), "func must be a non-async function"
|
|
||||||
return await asyncio.get_event_loop().run_in_executor(None, func)
|
return await asyncio.get_event_loop().run_in_executor(None, func)
|
||||||
|
@ -230,7 +230,8 @@ def _run(
|
|||||||
exec.run_frontend_prod,
|
exec.run_frontend_prod,
|
||||||
exec.run_backend_prod,
|
exec.run_backend_prod,
|
||||||
)
|
)
|
||||||
assert setup_frontend and frontend_cmd and backend_cmd, "Invalid env"
|
if not setup_frontend or not frontend_cmd or not backend_cmd:
|
||||||
|
raise ValueError("Invalid env")
|
||||||
|
|
||||||
# Post a telemetry event.
|
# Post a telemetry event.
|
||||||
telemetry.send(f"run-{env.value}")
|
telemetry.send(f"run-{env.value}")
|
||||||
|
@ -870,6 +870,9 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
def get_parent_state(cls) -> Type[BaseState] | None:
|
def get_parent_state(cls) -> Type[BaseState] | None:
|
||||||
"""Get the parent state.
|
"""Get the parent state.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If more than one parent state is found.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The parent state.
|
The parent state.
|
||||||
"""
|
"""
|
||||||
@ -878,9 +881,8 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
|
|||||||
for base in cls.__bases__
|
for base in cls.__bases__
|
||||||
if issubclass(base, BaseState) and base is not BaseState and not base._mixin
|
if issubclass(base, BaseState) and base is not BaseState and not base._mixin
|
||||||
]
|
]
|
||||||
assert (
|
if len(parent_states) >= 2:
|
||||||
len(parent_states) < 2
|
raise ValueError(f"Only one parent state is allowed {parent_states}.")
|
||||||
), f"Only one parent state is allowed {parent_states}."
|
|
||||||
return parent_states[0] if len(parent_states) == 1 else None # type: ignore
|
return parent_states[0] if len(parent_states) == 1 else None # type: ignore
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -340,6 +340,9 @@ class AppHarness:
|
|||||||
|
|
||||||
This is necessary when the backend is restarted and the state manager is a
|
This is necessary when the backend is restarted and the state manager is a
|
||||||
StateManagerRedis instance.
|
StateManagerRedis instance.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
RuntimeError: when the state manager cannot be reset
|
||||||
"""
|
"""
|
||||||
if (
|
if (
|
||||||
self.app_instance is not None
|
self.app_instance is not None
|
||||||
@ -354,7 +357,8 @@ class AppHarness:
|
|||||||
self.app_instance._state_manager = StateManagerRedis.create(
|
self.app_instance._state_manager = StateManagerRedis.create(
|
||||||
state=self.app_instance.state,
|
state=self.app_instance.state,
|
||||||
)
|
)
|
||||||
assert isinstance(self.app_instance.state_manager, StateManagerRedis)
|
if not isinstance(self.app_instance.state_manager, StateManagerRedis):
|
||||||
|
raise RuntimeError("Failed to reset state manager.")
|
||||||
|
|
||||||
def _start_frontend(self):
|
def _start_frontend(self):
|
||||||
# Set up the frontend.
|
# Set up the frontend.
|
||||||
@ -787,13 +791,13 @@ class AppHarness:
|
|||||||
Raises:
|
Raises:
|
||||||
RuntimeError: when the app hasn't started running
|
RuntimeError: when the app hasn't started running
|
||||||
TimeoutError: when the timeout expires before any states are seen
|
TimeoutError: when the timeout expires before any states are seen
|
||||||
|
ValueError: when the state_manager is not a memory state manager
|
||||||
"""
|
"""
|
||||||
if self.app_instance is None:
|
if self.app_instance is None:
|
||||||
raise RuntimeError("App is not running.")
|
raise RuntimeError("App is not running.")
|
||||||
state_manager = self.app_instance.state_manager
|
state_manager = self.app_instance.state_manager
|
||||||
assert isinstance(
|
if not isinstance(state_manager, (StateManagerMemory, StateManagerDisk)):
|
||||||
state_manager, (StateManagerMemory, StateManagerDisk)
|
raise ValueError("Only works with memory or disk state manager")
|
||||||
), "Only works with memory state manager"
|
|
||||||
if not self._poll_for(
|
if not self._poll_for(
|
||||||
target=lambda: state_manager.states,
|
target=lambda: state_manager.states,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
|
@ -345,6 +345,7 @@ def format_prop(
|
|||||||
Raises:
|
Raises:
|
||||||
exceptions.InvalidStylePropError: If the style prop value is not a valid type.
|
exceptions.InvalidStylePropError: If the style prop value is not a valid type.
|
||||||
TypeError: If the prop is not valid.
|
TypeError: If the prop is not valid.
|
||||||
|
ValueError: If the prop is not a string.
|
||||||
"""
|
"""
|
||||||
# import here to avoid circular import.
|
# import here to avoid circular import.
|
||||||
from reflex.event import EventChain
|
from reflex.event import EventChain
|
||||||
@ -391,7 +392,8 @@ def format_prop(
|
|||||||
raise TypeError(f"Could not format prop: {prop} of type {type(prop)}") from e
|
raise TypeError(f"Could not format prop: {prop} of type {type(prop)}") from e
|
||||||
|
|
||||||
# Wrap the variable in braces.
|
# Wrap the variable in braces.
|
||||||
assert isinstance(prop, str), "The prop must be a string."
|
if not isinstance(prop, str):
|
||||||
|
raise ValueError(f"Invalid prop: {prop}. Expected a string.")
|
||||||
return wrap(prop, "{", check_first=False)
|
return wrap(prop, "{", check_first=False)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user