Skip to content

Commit

Permalink
Merge branch 'main' into integration-test-framework
Browse files Browse the repository at this point in the history
  • Loading branch information
falkoschindler committed Aug 2, 2024
2 parents 66f0430 + c341f88 commit fb4d5aa
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 42 deletions.
4 changes: 2 additions & 2 deletions examples/authentication/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from fastapi.responses import RedirectResponse
from starlette.middleware.base import BaseHTTPMiddleware

from nicegui import Client, app, ui
from nicegui import app, ui

# in reality users passwords would obviously need to be hashed
passwords = {'user1': 'pass1', 'user2': 'pass2'}
Expand All @@ -27,7 +27,7 @@ class AuthMiddleware(BaseHTTPMiddleware):

async def dispatch(self, request: Request, call_next):
if not app.storage.user.get('authenticated', False):
if request.url.path in Client.page_routes.values() and request.url.path not in unrestricted_page_routes:
if not request.url.path.startswith('/_nicegui') and request.url.path not in unrestricted_page_routes:
app.storage.user['referrer_path'] = request.url.path # remember where the user wanted to go
return RedirectResponse('/login')
return await call_next(request)
Expand Down
23 changes: 11 additions & 12 deletions nicegui/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ def __init__(self, page: page, *, request: Optional[Request]) -> None:
self.on_air = False
self._disconnect_task: Optional[asyncio.Task] = None
self._deleted = False
self._has_warned_about_deleted_client = False
self.tab_id: Optional[str] = None

self.outbox = Outbox(self)
Expand Down Expand Up @@ -200,17 +199,17 @@ def run_javascript(self, code: str, *,
:return: AwaitableResponse that can be awaited to get the result of the JavaScript code
"""
if respond is True:
log.warning('The "respond" argument of run_javascript() has been removed. '
'Now the method always returns an AwaitableResponse that can be awaited. '
'Please remove the "respond=True" argument.')
helpers.warn_once('The "respond" argument of run_javascript() has been removed. '
'Now the method always returns an AwaitableResponse that can be awaited. '
'Please remove the "respond=True" argument.')
if respond is False:
raise ValueError('The "respond" argument of run_javascript() has been removed. '
'Now the method always returns an AwaitableResponse that can be awaited. '
'Please remove the "respond=False" argument and call the method without awaiting.')
if check_interval != 0.01:
log.warning('The "check_interval" argument of run_javascript() and similar methods has been removed. '
'Now the method automatically returns when receiving a response without checking regularly in an interval. '
'Please remove the "check_interval" argument.')
helpers.warn_once('The "check_interval" argument of run_javascript() and similar methods has been removed. '
'Now the method automatically returns when receiving a response without checking regularly in an interval. '
'Please remove the "check_interval" argument.')

request_id = str(uuid.uuid4())
target_id = self._temporary_socket_id or self.id
Expand Down Expand Up @@ -331,11 +330,11 @@ def delete(self) -> None:

def check_existence(self) -> None:
"""Check if the client still exists and print a warning if it doesn't."""
if self._deleted and not self._has_warned_about_deleted_client:
self._has_warned_about_deleted_client = True
log.warning('Client has been deleted but is still being used. This is most likely a bug in your application code. '
'See https://github.com/zauberzeug/nicegui/issues/3028 for more information.',
stack_info=True)
if self._deleted:
helpers.warn_once('Client has been deleted but is still being used. '
'This is most likely a bug in your application code. '
'See https://github.com/zauberzeug/nicegui/issues/3028 for more information.',
stack_info=True)

@contextmanager
def individual_target(self, socket_id: str) -> Iterator[None]:
Expand Down
8 changes: 4 additions & 4 deletions nicegui/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import TYPE_CHECKING, List

from .logging import log
from . import helpers
from .slot import Slot

if TYPE_CHECKING:
Expand All @@ -13,17 +13,17 @@ class Context:

def get_slot_stack(self) -> List[Slot]:
"""Return the slot stack of the current asyncio task. (DEPRECATED, use context.slot_stack instead)"""
log.warning('context.get_slot_stack() is deprecated, use context.slot_stack instead')
helpers.warn_once('context.get_slot_stack() is deprecated, use context.slot_stack instead')
return self.slot_stack

def get_slot(self) -> Slot:
"""Return the current slot. (DEPRECATED, use context.slot instead)"""
log.warning('context.get_slot() is deprecated, use context.slot instead')
helpers.warn_once('context.get_slot() is deprecated, use context.slot instead')
return self.slot

def get_client(self) -> Client:
"""Return the current client. (DEPRECATED, use context.client instead)"""
log.warning('context.get_client() is deprecated, use context.client instead')
helpers.warn_once('context.get_client() is deprecated, use context.client instead')
return self.client

@property
Expand Down
5 changes: 2 additions & 3 deletions nicegui/elements/highchart.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from .. import optional_features
from .. import helpers, optional_features
from ..element import Element
from ..logging import log
from .markdown import Markdown

try:
Expand All @@ -22,4 +21,4 @@ def __init__(self, *args, **kwargs) -> None: # pylint: disable=unused-argument
"""
super().__init__()
Markdown('Highcharts is not installed. Please run `pip install nicegui[highcharts]`.')
log.warning('Highcharts is not installed. Please run "pip install nicegui[highcharts]".')
helpers.warn_once('Highcharts is not installed. Please run "pip install nicegui[highcharts]".')
6 changes: 3 additions & 3 deletions nicegui/elements/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from typing_extensions import Self

from .. import helpers
from ..element import Element
from ..logging import log
from .context_menu import ContextMenu
from .item import Item
from .mixins.value_element import ValueElement
Expand Down Expand Up @@ -41,8 +41,8 @@ def props(self, add: Optional[str] = None, *, remove: Optional[str] = None) -> S
if 'touch-position' in self._props:
# https://github.com/zauberzeug/nicegui/issues/1738
del self._props['touch-position']
log.warning('The prop "touch-position" is not supported by `ui.menu`.\n'
'Use "ui.context_menu()" instead.')
helpers.warn_once('The prop "touch-position" is not supported by `ui.menu`.\n'
'Use "ui.context_menu()" instead.')
return self


Expand Down
6 changes: 3 additions & 3 deletions nicegui/elements/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from typing_extensions import Self

from .. import helpers
from ..element import Element
from ..events import GenericEventArguments, ValueChangeEventArguments, handle_event
from ..logging import log


class Tree(Element):
Expand Down Expand Up @@ -124,6 +124,6 @@ def props(self, add: Optional[str] = None, *, remove: Optional[str] = None) -> S
if 'default-expand-all' in self._props:
# https://github.com/zauberzeug/nicegui/issues/1385
del self._props['default-expand-all']
log.warning('The prop "default-expand-all" is not supported by `ui.tree`.\n'
'Use ".expand()" instead.')
helpers.warn_once('The prop "default-expand-all" is not supported by `ui.tree`.\n'
'Use ".expand()" instead.')
return self
5 changes: 2 additions & 3 deletions nicegui/functions/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
pass

from .. import helpers
from ..logging import log
from .html import add_head_html


Expand All @@ -25,8 +24,8 @@ def add_style(content: Union[str, Path], indented: bool = False) -> None: # DEP
content = Path(content).read_text()
if optional_features.has('sass'):
content = sass.compile(string=str(content).strip(), indented=indented)
log.warning("`ui.add_style` is deprecated, because it can't reliably detect the style language. "
'Use `ui.add_css`, `ui.add_scss` or `ui.add_sass` instead.')
helpers.warn_once("`ui.add_style` is deprecated, because it can't reliably detect the style language. "
'Use `ui.add_css`, `ui.add_scss` or `ui.add_sass` instead.')
add_head_html(f'<style>{content}</style>')


Expand Down
13 changes: 12 additions & 1 deletion nicegui/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@
import time
import webbrowser
from pathlib import Path
from typing import Any, Optional, Tuple, Union
from typing import Any, Optional, Set, Tuple, Union

from .logging import log

_shown_warnings: Set[str] = set()


def warn_once(message: str, *, stack_info: bool = False) -> None:
"""Print a warning message only once."""
if message not in _shown_warnings:
log.warning(message, stack_info=stack_info)
_shown_warnings.add(message)


def is_pytest() -> bool:
Expand Down
21 changes: 12 additions & 9 deletions website/documentation/content/overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,23 @@
''')

doc.text('Basic concepts', '''
NiceGUI provides UI _components_ (or _elements_) such as buttons, sliders, text, images, charts, and more.
NiceGUI provides UI _elements_ such as buttons, sliders, text, images, charts, and more.
Your app assembles these components into _pages_.
When the user interacts with an item on a page, NiceGUI triggers an _event_ (or _action_).
You define code to _handle_ each event, such as what to do when a user clicks a button named "Go".
You define code to _handle_ each event, such as what to do when a user clicks a button, modifies a value or operates a slider.
Elements can also be bound to a _model_ (data object), which automatically updates the user interface when the model value changes.
Components are arranged on a page using _layouts_.
Layouts provide things like grids, tabs, carousels, expansions, menus, and other tools to arrange your components.
Many components are linked to a _model_ (data object) in your code, which automatically updates the user interface when the value changes.
Elements are arranged on a page using a "declarative UI" or "code-based UI".
That means that you also write structures like grids, cards, tabs, carousels, expansions, menus, and other layout elements directly in code.
This concept has been made popular with Flutter and SwiftUI.
For readability, NiceGUI utilizes Python's `with ...` statement.
This context manager provides a nice way to indent the code to resemble the layout of the UI.
Styling and appearance can be controlled in several ways.
NiceGUI accepts optional arguments for certain styling, such as icons on buttons.
Other styling can be set with functions such as `.styles`, `.classes`, or `.props` that you'll learn about later.
Global styles like colors and fonts can be set with dedicated properties.
Or if you prefer, almost anything can be styled with CSS.
Most elements accept optional arguments for common styling and behavior changes, such as button icons or text color.
Because NiceGUI is a web framework, you can change almost any appearance of an element with CSS.
But elements also provide `.classes` and `.props` methods to apply Tailwind CSS and Quasar properties
which are more high-level and simpler to use day-to-day after you get the hang of it.
''')

doc.text('Actions, Events and Tasks', '''
Expand Down
4 changes: 2 additions & 2 deletions website/documentation/content/storage_documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
The user storage and browser storage are only available within `page builder functions </documentation/page>`_
because they are accessing the underlying `Request` object from FastAPI.
Additionally these two types require the `storage_secret` parameter in`ui.run()` to encrypt the browser session cookie.
Additionally these two types require the `storage_secret` parameter in`ui.run()` to sign the browser session cookie.
| Storage type | `tab` | `client` | `user` | `general` | `browser` |
|-----------------------------|--------|----------|--------|-----------|-----------|
Expand Down Expand Up @@ -97,7 +97,7 @@ def page_visits():


@doc.demo('Storing UI state', '''
Storage can also be used in combination with [`bindings`](/documentation/bindings).
Storage can also be used in combination with [`bindings`](/documentation/section_binding_properties).
Here we are storing the value of a textarea between visits.
The note is also shared between all tabs of the same user.
''')
Expand Down

0 comments on commit fb4d5aa

Please sign in to comment.