Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions sdk/python/examples/apps/controls-gallery/main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import logging

import flet as ft
import flet.version
from components.gallery_view import GalleryView
from gallerydata import GalleryData

import flet as ft
import flet.version

gallery = GalleryData()

logging.basicConfig(level=logging.DEBUG)

# ft.UpdateBehavior.disable_auto_update()
ft.context.disable_auto_update()


def main(page: ft.Page):
Expand Down
2 changes: 2 additions & 0 deletions sdk/python/examples/apps/counter/counter.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import flet as ft

ft.context.disable_auto_update()


def main(page: ft.Page):
page.title = "Flet counter example"
Expand Down
2 changes: 1 addition & 1 deletion sdk/python/examples/controls/canvas/brush.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def handle_pan_start(e: ft.DragStartEvent):
state.y = e.local_position.y

async def handle_pan_update(e: ft.DragUpdateEvent):
ft.UpdateBehavior.disable_auto_update()
ft.context.disable_auto_update()
canvas.shapes.append(
cv.Line(
x1=state.x,
Expand Down
18 changes: 18 additions & 0 deletions sdk/python/examples/controls/types/context/disable_auto_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import flet as ft


def main(page: ft.Page):
def button_click():
ft.context.disable_auto_update()
b.content = "Button clicked!"
# update just the button
b.update()

page.controls.append(ft.Text("This won't appear"))
# no page.update() will be called here

page.controls.append(b := ft.Button("Action!", on_click=button_click))
# page.update() - auto-update is enabled by default


ft.run(main)
11 changes: 11 additions & 0 deletions sdk/python/examples/controls/types/context/get_page.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import flet as ft


def main(page: ft.Page):
def button_click(e):
print("Page width:", ft.context.page.width)

page.add(ft.Button("Get page width", on_click=button_click))


ft.run(main)
15 changes: 7 additions & 8 deletions sdk/python/packages/flet-web/src/flet_web/fastapi/flet_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

import msgpack
from fastapi import WebSocket, WebSocketDisconnect

import flet_web.fastapi as flet_fastapi
from flet.controls.base_control import BaseControl
from flet.controls.context import _context_page
from flet.controls.context import _context_page, context
from flet.controls.exceptions import FletPageDisconnectedException
from flet.controls.update_behavior import UpdateBehavior
from flet.messaging.connection import Connection
from flet.messaging.protocol import (
ClientAction,
Expand All @@ -28,8 +29,6 @@
)
from flet.messaging.session import Session
from flet.utils import random_string, sha1

import flet_web.fastapi as flet_fastapi
from flet_web.fastapi.flet_app_manager import app_manager
from flet_web.fastapi.oauth_state import OAuthState
from flet_web.uploads import build_upload_url
Expand Down Expand Up @@ -140,24 +139,24 @@ async def __on_session_created(self):
try:
assert self.__main is not None
_context_page.set(self.__session.page)
UpdateBehavior.reset()
context.reset_auto_update()

if asyncio.iscoroutinefunction(self.__main):
await self.__main(self.__session.page)

elif inspect.isasyncgenfunction(self.__main):
async for _ in self.__main(self.__session.page):
if UpdateBehavior.auto_update_enabled():
if context.auto_update_enabled():
await self.__session.auto_update(self.__session.page)

elif inspect.isgeneratorfunction(self.__main):
for _ in self.__main(self.__session.page):
if UpdateBehavior.auto_update_enabled():
if context.auto_update_enabled():
await self.__session.auto_update(self.__session.page)
else:
self.__main(self.__session.page)

if UpdateBehavior.auto_update_enabled():
if context.auto_update_enabled():
await self.__session.auto_update(self.__session.page)
except FletPageDisconnectedException:
logger.debug(
Expand Down
1 change: 1 addition & 0 deletions sdk/python/packages/flet/docs/types/aliases.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
::: flet.BorderSideStrokeAlignValue
::: flet.BoxShadowValue
::: flet.ColorValue
::: flet.context
::: flet.ControlEvent
::: flet.ControlEventHandler
::: flet.ControlStateValue
Expand Down
1 change: 1 addition & 0 deletions sdk/python/packages/flet/docs/types/cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: flet.cache
20 changes: 20 additions & 0 deletions sdk/python/packages/flet/docs/types/context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Manages the context for Flet controls, including page reference
and auto-update behavior.

Context instance is accessed via [`ft.context`][flet.context].

## Examples

### Get page

```python
--8<-- "../../examples/controls/types/context/get_page.py"
```

### Disable auto update

```python
--8<-- "../../examples/controls/types/context/disable_auto_update.py"
```

::: flet.Context
1 change: 1 addition & 0 deletions sdk/python/packages/flet/docs/types/control.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
::: flet.control
3 changes: 0 additions & 3 deletions sdk/python/packages/flet/docs/types/updatebehavior.md

This file was deleted.

38 changes: 38 additions & 0 deletions sdk/python/packages/flet/integration_tests/apps/autoupdate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import flet as ft


def main(page: ft.Page):
page.title = "Autoupdate test"

def auto_update_global_enabled_click(e):
assert ft.context.page
page.controls.append(ft.Text("Global auto update"))

def disable_autoupdate_no_update_click(e):
ft.context.disable_auto_update()
page.controls.append(ft.Text("Auto update no update"))

def disable_autoupdate_with_update_click(e):
ft.context.disable_auto_update()
page.controls.append(ft.Text("Auto update with update"))
page.update()

assert ft.context.page
page.add(
ft.Text(f"Auto update enabled: {ft.context.auto_update_enabled()}"),
ft.Button(
"auto_update_global_enabled", on_click=auto_update_global_enabled_click
),
ft.Button(
"disable_autoupdate_no_update",
on_click=disable_autoupdate_no_update_click,
),
ft.Button(
"disable_autoupdate_with_update",
on_click=disable_autoupdate_with_update_click,
),
)


if __name__ == "__main__":
ft.run(main)
45 changes: 45 additions & 0 deletions sdk/python/packages/flet/integration_tests/test_context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import apps.autoupdate as app
import pytest

import flet as ft
import flet.testing as ftt


@pytest.mark.parametrize(
"flet_app",
[
{
"flet_app_main": app.main,
}
],
indirect=True,
)
class TestApp:
@pytest.mark.asyncio(loop_scope="module")
async def test_auto_update(self, flet_app: ftt.FletTestApp):
tester = flet_app.tester
await tester.pump_and_settle()
auto_update_enabled = await tester.find_by_text("Auto update enabled: True")
assert auto_update_enabled.count == 1

# tap 1st button
await tester.tap(await tester.find_by_text("auto_update_global_enabled"))
await tester.pump_and_settle()
assert (await tester.find_by_text("Global auto update")).count == 1

# tap 2nd button
await tester.tap(await tester.find_by_text("disable_autoupdate_no_update"))
await tester.pump_and_settle()
assert (await tester.find_by_text("Auto update no update")).count == 0

# tap 3rd button
await tester.tap(await tester.find_by_text("disable_autoupdate_with_update"))
await tester.pump_and_settle()
assert (await tester.find_by_text("Auto update with update")).count == 1
assert (await tester.find_by_text("Auto update no update")).count == 1


@pytest.mark.asyncio(loop_scope="module")
async def test_context_throws_exception_outside_flet_app():
with pytest.raises(Exception, match="The context is not associated with any page."):
p = ft.context.page # noqa: F841
6 changes: 5 additions & 1 deletion sdk/python/packages/flet/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,9 @@ nav:
- Tooltip: types/tooltip.md
- Url: types/url.md
- UnderlineTabIndicator: types/underlinetabindicator.md
- Decorators:
- cache: types/cache.md
- control: types/control.md
- Enums:
- AnimatedSwitcherTransition: types/animatedswitchertransition.md
- AnimationCurve: types/animationcurve.md
Expand Down Expand Up @@ -591,7 +594,6 @@ nav:
- TileAffinity: types/tileaffinity.md
- TimePickerEntryMode: types/timepickerentrymode.md
- TooltipTriggerMode: types/tooltiptriggermode.md
- UpdateBehavior: types/updatebehavior.md
- UrlTarget: types/urltarget.md
- VerticalAlignment: types/verticalalignment.md
- VisualDensity: types/visualdensity.md
Expand Down Expand Up @@ -651,6 +653,8 @@ nav:
# - types/pubsub/index.md
- PubSubClient: types/pubsub/pubsubclient.md
- PubSubHub: types/pubsub/pubsubhub.md
- Utility:
- Context: types/context.md
- Environment Variables: environment-variables.md
- Publish:
- Build and Publish a Flet app: publish/index.md
Expand Down
9 changes: 4 additions & 5 deletions sdk/python/packages/flet/src/flet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,10 @@
ShapeBorder,
StadiumBorder,
)
from flet.controls.cache import cache
from flet.controls.colors import Colors
from flet.controls.constrained_control import ConstrainedControl
from flet.controls.context import context
from flet.controls.context import Context, context
from flet.controls.control import Control
from flet.controls.control_builder import ControlBuilder
from flet.controls.control_event import (
Expand Down Expand Up @@ -182,7 +183,6 @@
CupertinoTimerPickerMode,
)
from flet.controls.cupertino.cupertino_tinted_button import CupertinoTintedButton
from flet.controls.data_view import data_view
from flet.controls.dialog_control import DialogControl
from flet.controls.duration import (
DateTimeValue,
Expand Down Expand Up @@ -494,7 +494,6 @@
VisualDensity,
WebRenderer,
)
from flet.controls.update_behavior import UpdateBehavior
from flet.pubsub.pubsub_client import PubSubClient
from flet.pubsub.pubsub_hub import PubSubHub

Expand Down Expand Up @@ -575,6 +574,7 @@
"Column",
"ConstrainedControl",
"Container",
"Context",
"ContinuousRectangleBorder",
"Control",
"ControlBuilder",
Expand Down Expand Up @@ -897,7 +897,6 @@
"TooltipValue",
"TransparentPointer",
"UnderlineTabIndicator",
"UpdateBehavior",
"Url",
"UrlLauncher",
"UrlTarget",
Expand All @@ -918,11 +917,11 @@
"app_async",
"border",
"border_radius",
"cache",
"context",
"control",
"cupertino_colors",
"cupertino_icons",
"data_view",
"dropdown",
"dropdownm2",
"icons",
Expand Down
11 changes: 5 additions & 6 deletions sdk/python/packages/flet/src/flet/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, Optional, Union

from flet.controls.context import _context_page
from flet.controls.context import _context_page, context
from flet.controls.page import Page
from flet.controls.types import AppView, RouteUrlStrategy, WebRenderer
from flet.controls.update_behavior import UpdateBehavior
from flet.messaging.session import Session
from flet.utils import (
get_bool_env_var,
Expand Down Expand Up @@ -254,24 +253,24 @@ async def on_session_created(session: Session):
try:
assert main is not None
_context_page.set(session.page)
UpdateBehavior.reset()
context.reset_auto_update()
if asyncio.iscoroutinefunction(main):
await main(session.page)

elif inspect.isasyncgenfunction(main):
async for _ in main(session.page):
if UpdateBehavior.auto_update_enabled():
if context.auto_update_enabled():
await session.auto_update(session.page)

elif inspect.isgeneratorfunction(main):
for _ in main(session.page):
if UpdateBehavior.auto_update_enabled():
if context.auto_update_enabled():
await session.auto_update(session.page)
else:
# run synchronously
main(session.page)

if UpdateBehavior.auto_update_enabled():
if context.auto_update_enabled():
await session.auto_update(session.page)

except Exception as e:
Expand Down
Loading