Skip to content

Commit 6d80daa

Browse files
committed
Refactor hooks and component decorator structure
Moved hooks from flet/hooks to flet/components/hooks and updated all imports accordingly. Extracted the component decorator into a new component_decorator.py module. Replaced internal renderer/context utility functions with current_renderer and updated their usage throughout the codebase. These changes improve modularity and maintainability of the component and hooks system.
1 parent 42bad9b commit 6d80daa

13 files changed

Lines changed: 75 additions & 78 deletions

File tree

sdk/python/packages/flet/src/flet/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from flet.app import app, app_async, run, run_async
2-
from flet.components.component import Component, component
2+
from flet.components.component import Component
3+
from flet.components.component_decorator import component
34
from flet.components.memo import memo
45
from flet.components.observable import Observable, observable
56
from flet.controls import alignment, border, border_radius, margin, padding

sdk/python/packages/flet/src/flet/components/component.py

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@
44
import weakref
55
from collections import defaultdict
66
from dataclasses import dataclass, field
7-
from functools import wraps
8-
from typing import Any, Callable, ParamSpec, TypeVar
7+
from typing import Any, Callable, TypeVar
98

9+
from flet.components.hooks.hook import Hook
10+
from flet.components.hooks.use_effect import EffectHook
1011
from flet.components.observable import Observable, ObservableSubscription
1112
from flet.components.utils import (
1213
_CURRENT_RENDERER,
13-
_get_renderer,
1414
shallow_compare_args_and_kwargs,
1515
)
1616
from flet.controls.base_control import BaseControl, control
1717
from flet.controls.context import context
18-
from flet.hooks.hook import Hook
19-
from flet.hooks.use_effect import EffectHook
2018

2119
logger = logging.getLogger("flet_components")
2220
logger.setLevel(logging.INFO)
@@ -238,41 +236,12 @@ def __str__(self):
238236
return f"{self._c}:{self.fn.__name__}({self._i} - {id(self)})"
239237

240238

241-
#
242-
# Component decorator
243-
#
244-
245-
246-
P = ParamSpec("P")
247-
R = TypeVar("R")
248-
249-
250-
def component(fn: Callable[P, R]) -> Callable[P, R]:
251-
"""
252-
Marks a function as a component. When called, it will render through
253-
the *current* Renderer.
254-
"""
255-
fn.__is_component__ = True
256-
257-
@wraps(fn)
258-
def component_wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
259-
key = kwargs.pop("key", None)
260-
r = _get_renderer()
261-
return r._render_component(fn, args, kwargs, key=key)
262-
263-
component_wrapper.__is_component__ = True
264-
component_wrapper.__component_impl__ = fn
265-
return component_wrapper
266-
267-
268239
#
269240
# Renderer
270241
#
271242

272243

273244
class Renderer:
274-
"""Owns fibers, stacks, and scheduling for a single session/page."""
275-
276245
_ROOT_TOKEN = ("__root__",)
277246

278247
def __init__(self, root_component=None):
@@ -284,11 +253,11 @@ def __init__(self, root_component=None):
284253
def set_memo(self):
285254
self._is_memo = True
286255

287-
def _push_context(self, key: object, value: object) -> None:
256+
def push_context(self, key: object, value: object) -> None:
288257
logger.debug("Renderer._push_context(%s, %s)", key, value)
289258
self._contexts[key].append(value)
290259

291-
def _pop_context(self, key: object) -> None:
260+
def pop_context(self, key: object) -> None:
292261
logger.debug("Renderer._pop_context(%s)", key)
293262
stack = self._contexts.get(key)
294263
if stack:
@@ -323,23 +292,7 @@ def render(self, root_fn: Callable[..., Any], *args, **kwargs):
323292
with self.with_context(), self._Frame(self, self._root_component):
324293
return root_fn(*args, **kwargs)
325294

326-
class _Frame:
327-
"""Context around entering a component; pushes/pops on renderer's stack."""
328-
329-
def __init__(self, renderer: Renderer, c: Component | None = None):
330-
self.r = renderer
331-
self.c = c
332-
333-
def __enter__(self):
334-
if self.c:
335-
self.r._render_stack.append(self.c)
336-
return self.c
337-
338-
def __exit__(self, exc_type, exc, tb):
339-
if self.c:
340-
self.r._render_stack.pop()
341-
342-
def _render_component(
295+
def render_component(
343296
self,
344297
fn: Callable[..., Any],
345298
args: tuple[Any, ...],
@@ -368,3 +321,19 @@ def _render_component(
368321
self._is_memo = False
369322

370323
return c
324+
325+
class _Frame:
326+
"""Context around entering a component; pushes/pops on renderer's stack."""
327+
328+
def __init__(self, renderer: Renderer, c: Component | None = None):
329+
self.r = renderer
330+
self.c = c
331+
332+
def __enter__(self):
333+
if self.c:
334+
self.r._render_stack.append(self.c)
335+
return self.c
336+
337+
def __exit__(self, exc_type, exc, tb):
338+
if self.c:
339+
self.r._render_stack.pop()
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from functools import wraps
2+
from typing import Callable, ParamSpec, TypeVar
3+
4+
from flet.components.utils import current_renderer
5+
6+
P = ParamSpec("P")
7+
R = TypeVar("R")
8+
9+
10+
def component(fn: Callable[P, R]) -> Callable[P, R]:
11+
"""
12+
Marks a function as a component. When called, it will render through
13+
the *current* Renderer.
14+
"""
15+
fn.__is_component__ = True
16+
17+
@wraps(fn)
18+
def component_wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
19+
key = kwargs.pop("key", None)
20+
r = current_renderer()
21+
return r.render_component(fn, args, kwargs, key=key)
22+
23+
component_wrapper.__is_component__ = True
24+
component_wrapper.__component_impl__ = fn
25+
return component_wrapper
File renamed without changes.

sdk/python/packages/flet/src/flet/hooks/use_callback.py renamed to sdk/python/packages/flet/src/flet/components/hooks/use_callback.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from collections.abc import Sequence
44
from typing import Any, Callable, ParamSpec, TypeVar
55

6-
from flet.hooks.use_memo import use_memo
6+
from flet.components.hooks.use_memo import use_memo
77

88
P = ParamSpec("P")
99
R = TypeVar("R")

sdk/python/packages/flet/src/flet/hooks/use_context.py renamed to sdk/python/packages/flet/src/flet/components/hooks/use_context.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55
from typing_extensions import Protocol
66

7+
from flet.components.hooks.hook import Hook
78
from flet.components.observable import Observable
8-
from flet.components.utils import _get_renderer, current_component
9-
from flet.hooks.hook import Hook
9+
from flet.components.utils import current_component, current_renderer
1010

1111

1212
@dataclass
@@ -37,12 +37,12 @@ def create_context(default_value: T) -> ContextProvider[T]:
3737
key = object()
3838

3939
def provider(value: T, callback: Callable[[], ProviderResultT]) -> ProviderResultT: # type: ignore[type-var]
40-
r = _get_renderer()
41-
r._push_context(key, value)
40+
r = current_renderer()
41+
r.push_context(key, value)
4242
try:
4343
return callback() # type: ignore[return-value]
4444
finally:
45-
r._pop_context(key)
45+
r.pop_context(key)
4646

4747
p = cast(ContextProvider[T], provider)
4848
p.default_value = default_value

sdk/python/packages/flet/src/flet/hooks/use_effect.py renamed to sdk/python/packages/flet/src/flet/components/hooks/use_effect.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from dataclasses import dataclass
44
from typing import Any
55

6+
from flet.components.hooks.hook import Hook
67
from flet.components.utils import current_component
7-
from flet.hooks.hook import Hook
88

99

1010
@dataclass

sdk/python/packages/flet/src/flet/hooks/use_memo.py renamed to sdk/python/packages/flet/src/flet/components/hooks/use_memo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
from dataclasses import dataclass
33
from typing import Any, Callable, Generic, TypeVar
44

5+
from flet.components.hooks.hook import Hook
56
from flet.components.utils import current_component, shallow_compare_args
6-
from flet.hooks.hook import Hook
77

88
MemoValueT = TypeVar("MemoValueT")
99

sdk/python/packages/flet/src/flet/hooks/use_state.py renamed to sdk/python/packages/flet/src/flet/components/hooks/use_state.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
from dataclasses import dataclass
33
from typing import Any, TypeVar
44

5+
from flet.components.hooks.hook import Hook
56
from flet.components.observable import Observable, ObservableSubscription
67
from flet.components.utils import current_component
7-
from flet.hooks.hook import Hook
88

99

1010
@dataclass

sdk/python/packages/flet/src/flet/components/memo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
from flet.components.utils import _get_renderer
1+
from flet.components.utils import current_renderer
22

33

44
def memo(fn):
55
def memo_wrapper(*args, **kwargs):
6-
r = _get_renderer()
6+
r = current_renderer()
77
r.set_memo()
88
return fn(*args, **kwargs)
99

0 commit comments

Comments
 (0)