Skip to content

Commit

Permalink
Merge branch 'main' into 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
falkoschindler committed Aug 16, 2024
2 parents baa97ac + cd9e547 commit 7d4d0cc
Show file tree
Hide file tree
Showing 42 changed files with 1,323 additions and 946 deletions.
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
20 changes: 9 additions & 11 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: set up Poetry
uses: abatilo/actions-poetry@v2.0.0
with:
poetry-version: "1.3.1"
uses: abatilo/actions-poetry@v3
- name: get version
id: get_version
run: echo "VERSION=$(echo ${GITHUB_REF/refs\/tags\//})" >> $GITHUB_ENV
Expand All @@ -30,7 +28,7 @@ jobs:
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }}
run: poetry publish --build
- name: Create GitHub release entry
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
id: create_release
with:
draft: true
Expand All @@ -48,7 +46,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Prepare
id: prep
run: |
Expand Down Expand Up @@ -79,7 +77,7 @@ jobs:
platforms: all
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
Expand All @@ -89,7 +87,7 @@ jobs:
with:
install: true
- name: Build
uses: docker/build-push-action@v2
uses: docker/build-push-action@v6
with:
context: .
file: ./release.dockerfile
Expand All @@ -114,12 +112,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
ref: main

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.11

Expand Down
12 changes: 5 additions & 7 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 40
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: set up Poetry
uses: abatilo/actions-poetry@v2.0.0
with:
poetry-version: "1.6.1"
uses: abatilo/actions-poetry@v3
- name: install dependencies
run: |
set -x
Expand All @@ -33,11 +31,11 @@ jobs:
- name: test startup
run: ./test_startup.sh
- name: setup chromedriver
uses: nanasess/setup-chromedriver@v2.2.0
uses: nanasess/setup-chromedriver@v2.2.2
- name: pytest
run: pytest
- name: upload screenshots
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down
6 changes: 3 additions & 3 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors:
given-names: Rodja
orcid: https://orcid.org/0009-0009-4735-6227
title: 'NiceGUI: Web-based user interfaces with Python. The nice way.'
version: v1.4.30
date-released: '2024-07-26'
version: v1.4.34
date-released: '2024-08-05'
url: https://github.com/zauberzeug/nicegui
doi: 10.5281/zenodo.12926830
doi: 10.5281/zenodo.13223152
2 changes: 1 addition & 1 deletion examples/authentication/test_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# pylint: disable=missing-function-docstring

pytest_plugins = ['nicegui.testing.plugin']
pytest_plugins = ['nicegui.testing.user_plugin']


@pytest.mark.module_under_test(main)
Expand Down
2 changes: 1 addition & 1 deletion examples/chat_app/test_chat_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from . import main

pytest_plugins = ['nicegui.testing.plugin']
pytest_plugins = ['nicegui.testing.user_plugin']


@pytest.mark.module_under_test(main)
Expand Down
2 changes: 1 addition & 1 deletion examples/todo_list/test_todo_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

# pylint: disable=missing-function-docstring

pytest_plugins = ['nicegui.testing.plugin']
pytest_plugins = ['nicegui.testing.user_plugin']


@pytest.mark.module_under_test(main)
Expand Down
2 changes: 1 addition & 1 deletion fly.dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.11.3-slim
FROM python:3.11-slim

LABEL maintainer="Zauberzeug GmbH <nicegui@zauberzeug.com>"

Expand Down
2 changes: 1 addition & 1 deletion nicegui/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def handle_event(self, msg: Dict) -> None:
"""Forward an event to the corresponding element."""
with self:
sender = self.elements.get(msg['id'])
if sender is not None:
if sender is not None and not sender.is_ignoring_events:
msg['args'] = [None if arg is None else json.loads(arg) for arg in msg.get('args', [])]
if len(msg['args']) == 1:
msg['args'] = msg['args'][0]
Expand Down
10 changes: 9 additions & 1 deletion nicegui/element_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from .elements.mixins.content_element import ContentElement
from .elements.mixins.source_element import SourceElement
from .elements.mixins.text_element import TextElement
from .elements.notification import Notification
from .elements.select import Select

T = TypeVar('T', bound=Element)

Expand Down Expand Up @@ -108,11 +110,17 @@ def __iter__(self) -> Iterator[T]:
element._props.get('icon'),
element._props.get('placeholder'),
element._props.get('value'),
element._props.get('options', {}).get('message'),
element.text if isinstance(element, TextElement) else None,
element.content if isinstance(element, ContentElement) else None,
element.source if isinstance(element, SourceElement) else None,
) if content]
if isinstance(element, Notification):
element_contents.append(element.message)
if isinstance(element, Select):
options = {option['value']: option['label'] for option in element._props.get('options', [])}
element_contents.append(options.get(element.value, ''))
if element.is_showing_popup:
element_contents.extend(options.values())
if any(all(needle not in str(haystack) for haystack in element_contents) for needle in self._contents):
continue
if any(needle in str(haystack) for haystack in element_contents for needle in self._exclude_content):
Expand Down
33 changes: 29 additions & 4 deletions nicegui/elements/scene.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export default {
this.objects = new Map();
this.objects.set("scene", this.scene);
this.draggable_objects = [];
this.is_initialized = false;

window["scene_" + this.$el.id] = this.scene; // NOTE: for selenium tests only

Expand Down Expand Up @@ -150,7 +151,6 @@ export default {
};
const handleDrag = (event) => {
this.drag_constraints.split(",").forEach((constraint) => applyConstraint(constraint, event.object.position));
if (event.type === "drag") return;
this.$emit(event.type, {
type: event.type,
object_id: event.object.object_id,
Expand All @@ -159,7 +159,8 @@ export default {
y: event.object.position.y,
z: event.object.position.z,
});
this.controls.enabled = event.type == "dragend";
if (event.type === "dragstart") this.controls.enabled = false;
if (event.type === "dragend") this.controls.enabled = true;
};
this.drag_controls.addEventListener("dragstart", handleDrag);
this.drag_controls.addEventListener("drag", handleDrag);
Expand Down Expand Up @@ -196,8 +197,7 @@ export default {
shift_key: mouseEvent.shiftKey,
});
};
this.$el.onclick = click_handler;
this.$el.ondblclick = click_handler;
this.click_events.forEach((event) => this.$el.addEventListener(event, click_handler));

this.texture_loader = new THREE.TextureLoader();
this.stl_loader = new STLLoader();
Expand All @@ -216,6 +216,7 @@ export default {

methods: {
create(type, id, parent_id, ...args) {
if (!this.is_initialized) return;
let mesh;
if (type == "group") {
mesh = new THREE.Group();
Expand Down Expand Up @@ -390,6 +391,11 @@ export default {
if (!this.objects.has(object_id)) return;
this.objects.get(object_id).geometry = texture_geometry(coords);
},
set_points(object_id, position, color) {
const geometry = this.objects.get(object_id).geometry;
geometry.setAttribute("position", new THREE.Float32BufferAttribute(position.flat(), 3));
geometry.setAttribute("color", new THREE.Float32BufferAttribute(color.flat(), 3));
},
move_camera(x, y, z, look_at_x, look_at_y, look_at_z, up_x, up_y, up_z, duration) {
if (this.camera_tween) this.camera_tween.stop();
this.camera_tween = new TWEEN.Tween([
Expand Down Expand Up @@ -426,6 +432,23 @@ export default {
})
.start();
},
get_camera() {
return {
position: this.camera.position,
up: this.camera.up,
rotation: this.camera.rotation,
quaternion: this.camera.quaternion,
type: this.camera.type,
fov: this.camera.fov,
aspect: this.camera.aspect,
near: this.camera.near,
far: this.camera.far,
left: this.camera.left,
right: this.camera.right,
top: this.camera.top,
bottom: this.camera.bottom,
};
},
resize() {
const { clientWidth, clientHeight } = this.$el;
this.renderer.setSize(clientWidth, clientHeight);
Expand All @@ -439,6 +462,7 @@ export default {
this.camera.updateProjectionMatrix();
},
init_objects(data) {
this.is_initialized = true;
for (const [
type,
id,
Expand Down Expand Up @@ -476,6 +500,7 @@ export default {
grid: Object,
camera_type: String,
camera_params: Object,
click_events: Array,
drag_constraints: String,
background_color: String,
},
Expand Down
21 changes: 12 additions & 9 deletions nicegui/elements/scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from typing_extensions import Self

from .. import binding
from ..awaitable_response import AwaitableResponse, NullResponse
from ..dataclasses import KWONLY_SLOTS
from ..element import Element
from ..events import (
Expand Down Expand Up @@ -75,6 +74,7 @@ def __init__(self,
grid: Union[bool, Tuple[int, int]] = True,
camera: Optional[SceneCamera] = None,
on_click: Optional[Callable[..., Any]] = None,
click_events: List[str] = ['click', 'dblclick'], # noqa: B006
on_drag_start: Optional[Callable[..., Any]] = None,
on_drag_end: Optional[Callable[..., Any]] = None,
drag_constraints: str = '',
Expand All @@ -91,7 +91,8 @@ def __init__(self,
:param height: height of the canvas
:param grid: whether to display a grid (boolean or tuple of ``size`` and ``divisions`` for `Three.js' GridHelper <https://threejs.org/docs/#api/en/helpers/GridHelper>`_, default: 100x100)
:param camera: camera definition, either instance of ``ui.scene.perspective_camera`` (default) or ``ui.scene.orthographic_camera``
:param on_click: callback to execute when a 3D object is clicked
:param on_click: callback to execute when a 3D object is clicked (use ``click_events`` to specify which events to subscribe to)
:param click_events: list of JavaScript click events to subscribe to (default: ``['click', 'dblclick']``)
:param on_drag_start: callback to execute when a 3D object is dragged
:param on_drag_end: callback to execute when a 3D object is dropped
:param drag_constraints: comma-separated JavaScript expression for constraining positions of dragged objects (e.g. ``'x = 0, z = y / 2'``)
Expand All @@ -108,9 +109,9 @@ def __init__(self,
self.objects: Dict[str, Object3D] = {}
self.stack: List[Union[Object3D, SceneObject]] = [SceneObject()]
self._click_handlers = [on_click] if on_click else []
self._props['click_events'] = click_events
self._drag_start_handlers = [on_drag_start] if on_drag_start else []
self._drag_end_handlers = [on_drag_end] if on_drag_end else []
self.is_initialized = False
self.on('init', self._handle_init)
self.on('click3d', self._handle_click)
self.on('dragstart', self._handle_drag)
Expand Down Expand Up @@ -167,7 +168,6 @@ def __getattribute__(self, name: str) -> Any:
return attribute

def _handle_init(self, e: GenericEventArguments) -> None:
self.is_initialized = True
with self.client.individual_target(e.args['socket_id']):
self.move_camera(duration=0)
self.run_method('init_objects', [obj.data for obj in self.objects.values()])
Expand All @@ -179,11 +179,6 @@ async def initialized(self) -> None:
await self.client.connected()
await event.wait()

def run_method(self, name: str, *args: Any, timeout: float = 1, check_interval: float = 0.01) -> AwaitableResponse:
if not self.is_initialized:
return NullResponse()
return super().run_method(name, *args, timeout=timeout, check_interval=check_interval)

def _handle_click(self, e: GenericEventArguments) -> None:
arguments = SceneClickEventArguments(
sender=self,
Expand Down Expand Up @@ -263,6 +258,14 @@ def move_camera(self,
self.camera.look_at_x, self.camera.look_at_y, self.camera.look_at_z,
self.camera.up_x, self.camera.up_y, self.camera.up_z, duration)

async def get_camera(self) -> Dict[str, Any]:
"""Get the current camera parameters.
In contrast to the `camera` property,
the result of this method includes the current camera pose caused by the user navigating the scene in the browser.
"""
return await self.run_method('get_camera')

def _handle_delete(self) -> None:
binding.remove(list(self.objects.values()))
super()._handle_delete()
Expand Down
6 changes: 6 additions & 0 deletions nicegui/elements/scene_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,9 @@ def __init__(self,
:param point_size: size of the points (default: 1.0)
"""
super().__init__('point_cloud', points, colors, point_size)

def set_points(self, points: List[List[float]], colors: List[List[float]]) -> None:
"""Change the points and colors of the point cloud."""
self.args[0] = points
self.args[1] = colors
self.scene.run_method('set_points', self.id, points, colors)
Loading

0 comments on commit 7d4d0cc

Please sign in to comment.