Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into lendemor/add_PERF_rules
Browse files Browse the repository at this point in the history
  • Loading branch information
masenf committed Dec 13, 2024
2 parents 3525d76 + 61cb725 commit 291b6f8
Show file tree
Hide file tree
Showing 46 changed files with 924 additions and 265 deletions.
3 changes: 2 additions & 1 deletion benchmarks/benchmark_compile_times.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import argparse
import json
import os
from pathlib import Path

from utils import send_data_to_posthog

Expand All @@ -18,7 +19,7 @@ def extract_stats_from_json(json_file: str) -> list[dict]:
Returns:
list[dict]: The stats for each test.
"""
with open(json_file, "r") as file:
with Path(json_file).open() as file:
json_data = json.load(file)

# Load the JSON data if it is a string, otherwise assume it's already a dictionary
Expand Down
3 changes: 2 additions & 1 deletion benchmarks/benchmark_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import argparse
import json
import os
from pathlib import Path

from utils import send_data_to_posthog

Expand All @@ -18,7 +19,7 @@ def extract_stats_from_json(json_file: str) -> dict:
Returns:
dict: The stats for each test.
"""
with open(json_file, "r") as file:
with Path(json_file).open() as file:
json_data = json.load(file)

# Load the JSON data if it is a string, otherwise assume it's already a dictionary
Expand Down
31 changes: 12 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,19 @@ version = "0.6.7dev1"
description = "Web apps in pure Python."
license = "Apache-2.0"
authors = [
"Nikhil Rao <nikhil@reflex.dev>",
"Alek Petuskey <alek@reflex.dev>",
"Masen Furer <masen@reflex.dev>",
"Elijah Ahianyo <elijah@reflex.dev>",
"Thomas Brandého <thomas@reflex.dev>",
"Nikhil Rao <nikhil@reflex.dev>",
"Alek Petuskey <alek@reflex.dev>",
"Masen Furer <masen@reflex.dev>",
"Elijah Ahianyo <elijah@reflex.dev>",
"Thomas Brandého <thomas@reflex.dev>",
]
readme = "README.md"
homepage = "https://reflex.dev"
repository = "https://github.com/reflex-dev/reflex"
documentation = "https://reflex.dev/docs/getting-started/introduction"
keywords = [
"web",
"framework",
]
classifiers = [
"Development Status :: 4 - Beta",
]
packages = [
{include = "reflex"}
]
keywords = ["web", "framework"]
classifiers = ["Development Status :: 4 - Beta"]
packages = [{ include = "reflex" }]

[tool.poetry.dependencies]
python = "^3.9"
Expand All @@ -42,11 +35,11 @@ uvicorn = ">=0.20.0"
starlette-admin = ">=0.11.0,<1.0"
alembic = ">=1.11.1,<2.0"
platformdirs = ">=3.10.0,<5.0"
distro = {version = ">=1.8.0,<2.0", platform = "linux"}
distro = { version = ">=1.8.0,<2.0", platform = "linux" }
python-engineio = "!=4.6.0"
wrapt = [
{version = ">=1.14.0,<2.0", python = ">=3.11"},
{version = ">=1.11.0,<2.0", python = "<3.11"},
{ version = ">=1.14.0,<2.0", python = ">=3.11" },
{ version = ">=1.11.0,<2.0", python = "<3.11" },
]
packaging = ">=23.1,<25.0"
reflex-hosting-cli = ">=0.1.29,<2.0"
Expand Down Expand Up @@ -94,7 +87,7 @@ build-backend = "poetry.core.masonry.api"
target-version = "py39"
output-format = "concise"
lint.isort.split-on-trailing-comma = false
lint.select = ["B", "D", "E", "F", "I", "SIM", "W", "RUF", "FURB", "PERF", "ERA"]
lint.select = ["B", "C4", "D", "E", "ERA", "F", "FURB", "I", "PERF", "PTH", "RUF", "SIM", "W"]
lint.ignore = ["B008", "D205", "E501", "F403", "SIM115", "RUF006", "RUF012"]
lint.pydocstyle.convention = "google"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ export function {{tag_name}} () {
{{ hook }}
{% endfor %}

{% for hook, data in component._get_all_hooks().items() if not data.position or data.position == const.hook_position.PRE_TRIGGER %}
{{ hook }}
{% endfor %}

{% for hook in memo_trigger_hooks %}
{{ hook }}
{% endfor %}

{% for hook in component._get_all_hooks() %}
{% for hook, data in component._get_all_hooks().items() if data.position and data.position == const.hook_position.POST_TRIGGER %}
{{ hook }}
{% endfor %}

Expand Down
2 changes: 1 addition & 1 deletion reflex/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ def _add_cors(self):
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
allow_origins=["*"],
allow_origins=get_config().cors_allowed_origins,
)

@property
Expand Down
1 change: 1 addition & 0 deletions reflex/compiler/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def __init__(self) -> None:
"on_load_internal": constants.CompileVars.ON_LOAD_INTERNAL,
"update_vars_internal": constants.CompileVars.UPDATE_VARS_INTERNAL,
"frontend_exception_state": constants.CompileVars.FRONTEND_EXCEPTION_STATE_FULL,
"hook_position": constants.Hooks.HookPosition,
}


Expand Down
2 changes: 1 addition & 1 deletion reflex/compiler/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]:
default, rest = compile_import_statement(fields)

# prevent lib from being rendered on the page if all imports are non rendered kind
if not any({f.render for f in fields}): # type: ignore
if not any(f.render for f in fields): # type: ignore
continue

if not lib:
Expand Down
65 changes: 44 additions & 21 deletions reflex/components/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ def _iter_parent_classes_with_method(cls, method: str) -> Iterator[Type[Componen
Yields:
The parent classes that define the method (differently than the base).
"""
seen_methods = set([getattr(Component, method)])
seen_methods = {getattr(Component, method)}
for clz in cls.mro():
if clz is Component:
break
Expand Down Expand Up @@ -1368,7 +1368,9 @@ def _get_hooks_imports(self) -> ParsedImportDict:
if user_hooks_data is not None:
other_imports.append(user_hooks_data.imports)
other_imports.extend(
hook_imports for hook_imports in self._get_added_hooks().values()
hook_vardata.imports
for hook_vardata in self._get_added_hooks().values()
if hook_vardata is not None
)

return imports.merge_imports(_imports, *other_imports)
Expand All @@ -1390,15 +1392,9 @@ def _get_imports(self) -> ParsedImportDict:

# Collect imports from Vars used directly by this component.
var_datas = [var._get_all_var_data() for var in self._get_vars()]
var_imports: List[ImmutableParsedImportDict] = list(
map(
lambda var_data: var_data.imports,
filter(
None,
var_datas,
),
)
)
var_imports: List[ImmutableParsedImportDict] = [
var_data.imports for var_data in var_datas if var_data is not None
]

added_import_dicts: list[ParsedImportDict] = []
for clz in self._iter_parent_classes_with_method("add_imports"):
Expand Down Expand Up @@ -1523,7 +1519,7 @@ def _get_hooks_internal(self) -> dict[str, None]:
**self._get_special_hooks(),
}

def _get_added_hooks(self) -> dict[str, ImportDict]:
def _get_added_hooks(self) -> dict[str, VarData | None]:
"""Get the hooks added via `add_hooks` method.
Returns:
Expand All @@ -1532,17 +1528,15 @@ def _get_added_hooks(self) -> dict[str, ImportDict]:
code = {}

def extract_var_hooks(hook: Var):
_imports = {}
var_data = VarData.merge(hook._get_all_var_data())
if var_data is not None:
for sub_hook in var_data.hooks:
code[sub_hook] = {}
if var_data.imports:
_imports = var_data.imports
code[sub_hook] = None

if str(hook) in code:
code[str(hook)] = imports.merge_imports(code[str(hook)], _imports)
code[str(hook)] = VarData.merge(var_data, code[str(hook)])
else:
code[str(hook)] = _imports
code[str(hook)] = var_data

# Add the hook code from add_hooks for each parent class (this is reversed to preserve
# the order of the hooks in the final output)
Expand All @@ -1551,7 +1545,7 @@ def extract_var_hooks(hook: Var):
if isinstance(hook, Var):
extract_var_hooks(hook)
else:
code[hook] = {}
code[hook] = None

return code

Expand Down Expand Up @@ -1593,8 +1587,7 @@ def _get_all_hooks(self) -> dict[str, None]:
if hooks is not None:
code[hooks] = None

for hook in self._get_added_hooks():
code[hook] = None
code.update(self._get_added_hooks())

# Add the hook code for the children.
for child in self.children:
Expand Down Expand Up @@ -2196,6 +2189,31 @@ def _get_hook_deps(hook: str) -> list[str]:
]
return [var_name]

@staticmethod
def _get_deps_from_event_trigger(event: EventChain | EventSpec | Var) -> set[str]:
"""Get the dependencies accessed by event triggers.
Args:
event: The event trigger to extract deps from.
Returns:
The dependencies accessed by the event triggers.
"""
events: list = [event]
deps = set()

if isinstance(event, EventChain):
events.extend(event.events)

for ev in events:
if isinstance(ev, EventSpec):
for arg in ev.args:
for a in arg:
var_datas = VarData.merge(a._get_all_var_data())
if var_datas and var_datas.deps is not None:
deps |= {str(dep) for dep in var_datas.deps}
return deps

@classmethod
def _get_memoized_event_triggers(
cls,
Expand Down Expand Up @@ -2232,6 +2250,11 @@ def _get_memoized_event_triggers(

# Calculate Var dependencies accessed by the handler for useCallback dep array.
var_deps = ["addEvents", "Event"]

# Get deps from event trigger var data.
var_deps.extend(cls._get_deps_from_event_trigger(event))

# Get deps from hooks.
for arg in event_args:
var_data = arg._get_all_var_data()
if var_data is None:
Expand Down
18 changes: 10 additions & 8 deletions reflex/components/core/clipboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@

from reflex.components.base.fragment import Fragment
from reflex.components.tags.tag import Tag
from reflex.constants.compiler import Hooks
from reflex.event import EventChain, EventHandler, passthrough_event_spec
from reflex.utils.format import format_prop, wrap
from reflex.utils.imports import ImportVar
from reflex.vars import get_unique_variable_name
from reflex.vars.base import Var
from reflex.vars.base import Var, VarData


class Clipboard(Fragment):
Expand Down Expand Up @@ -72,7 +73,7 @@ def add_imports(self) -> dict[str, ImportVar]:
),
}

def add_hooks(self) -> list[str]:
def add_hooks(self) -> list[str | Var[str]]:
"""Add hook to register paste event listener.
Returns:
Expand All @@ -83,13 +84,14 @@ def add_hooks(self) -> list[str]:
return []
if isinstance(on_paste, EventChain):
on_paste = wrap(str(format_prop(on_paste)).strip("{}"), "(")
hook_expr = f"usePasteHandler({self.targets!s}, {self.on_paste_event_actions!s}, {on_paste!s})"

return [
"usePasteHandler(%s, %s, %s)"
% (
str(self.targets),
str(self.on_paste_event_actions),
on_paste,
)
Var(
hook_expr,
_var_type="str",
_var_data=VarData(position=Hooks.HookPosition.POST_TRIGGER),
),
]


Expand Down
2 changes: 1 addition & 1 deletion reflex/components/core/clipboard.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ class Clipboard(Fragment):
...

def add_imports(self) -> dict[str, ImportVar]: ...
def add_hooks(self) -> list[str]: ...
def add_hooks(self) -> list[str | Var[str]]: ...

clipboard = Clipboard.create
7 changes: 5 additions & 2 deletions reflex/components/datadisplay/dataeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,11 @@ def add_hooks(self) -> list[str]:
editor_id = get_unique_variable_name()

# Define the name of the getData callback associated with this component and assign to get_cell_content.
data_callback = f"getData_{editor_id}"
self.get_cell_content = Var(_js_expr=data_callback) # type: ignore
if self.get_cell_content is not None:
data_callback = self.get_cell_content._js_expr
else:
data_callback = f"getData_{editor_id}"
self.get_cell_content = Var(_js_expr=data_callback) # type: ignore

code = [f"function {data_callback}([col, row])" "{"]

Expand Down
11 changes: 11 additions & 0 deletions reflex/components/radix/themes/components/context_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from reflex.vars.base import Var

from ..base import LiteralAccentColor, RadixThemesComponent
from .checkbox import Checkbox

LiteralDirType = Literal["ltr", "rtl"]

Expand Down Expand Up @@ -232,6 +233,15 @@ class ContextMenuSeparator(RadixThemesComponent):
tag = "ContextMenu.Separator"


class ContextMenuCheckbox(Checkbox):
"""The component that contains the checkbox."""

tag = "ContextMenu.CheckboxItem"

# Text to render as shortcut.
shortcut: Var[str]


class ContextMenu(ComponentNamespace):
"""Menu representing a set of actions, displayed at the origin of a pointer right-click or long-press."""

Expand All @@ -243,6 +253,7 @@ class ContextMenu(ComponentNamespace):
sub_content = staticmethod(ContextMenuSubContent.create)
item = staticmethod(ContextMenuItem.create)
separator = staticmethod(ContextMenuSeparator.create)
checkbox = staticmethod(ContextMenuCheckbox.create)


context_menu = ContextMenu()
Loading

0 comments on commit 291b6f8

Please sign in to comment.