Skip to content

Commit c494f7d

Browse files
committed
Merge branch 'develop' into patch-signals-type-hint
2 parents f0b3a9a + d09b198 commit c494f7d

7 files changed

Lines changed: 64 additions & 31 deletions

File tree

.github/dependabot.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Keep GitHub Actions up to date with GitHub's Dependabot...
2+
# https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/secure-your-dependencies/keeping-your-actions-up-to-date-with-dependabot
3+
# https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-options-reference#package-ecosystem
4+
version: 2
5+
updates:
6+
- package-ecosystem: github-actions
7+
directory: /
8+
groups:
9+
github-actions:
10+
patterns:
11+
- "*" # Group all Actions updates into a single larger pull request
12+
schedule:
13+
interval: weekly

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
33
# Ruff version.
4-
rev: v0.15.2
4+
rev: v0.15.4
55
hooks:
66
# Run the linter.
77
- id: ruff-check

pyproject.toml

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,20 @@ dev = [
5959
[tool.ruff]
6060
line-length = 99
6161
lint.select = [
62-
# Annotations
63-
"ANN",
64-
# flake8-bugbear
65-
"B",
66-
"D",
67-
# pycodestyle
68-
"E",
69-
# Pyflakes
70-
"F",
71-
# isort
72-
"I",
73-
# Ruff specific
74-
"RUF",
75-
# flake8-simplify
76-
"SIM",
77-
# pyupgrade
78-
"UP",
62+
"ANN", # annotations
63+
"B", # flake8-bugbear
64+
"D", # pydocstyle
65+
"DTZ", # flake8-datetimez
66+
"E", # pycodestyle
67+
"F", # Pyflakes
68+
"FURB", # refurb
69+
"I", # isort
70+
"PL", # Pylint
71+
"PYI", # flake8-pyi
72+
"RUF", # Ruff-specific rules
73+
"SIM", # flake8-simplify
74+
"SLOT", # flake8-slots
75+
"UP", # pyupgrade
7976
]
8077
lint.ignore = [
8178
"D100", # undocumented-public-module
@@ -90,5 +87,6 @@ lint.ignore = [
9087
"D415", # Duplicate of D400
9188
"E501",
9289
]
93-
lint.per-file-ignores."examples/**/*.py" = [ "ANN" ]
90+
lint.per-file-ignores."examples/**/*.py" = [ "ANN", "DTZ005", "PLC0415" ]
9491
lint.fixable = [ "ALL" ]
92+
lint.pylint.allow-magic-value-types = [ "int", "str" ]

src/datastar_py/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def _read_signals(
1515
) -> dict[str, Any] | None:
1616
if "Datastar-Request" not in headers:
1717
return None
18-
if method == "GET":
18+
if method in ("GET", "DELETE"):
1919
data = params.get("datastar")
2020
elif headers.get("Content-Type") == "application/json":
2121
data = body

src/datastar_py/attributes.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,13 @@ def signals(
127127
:param expressions_: If True, the values of the signals will be evaluated as expressions
128128
rather than literals.
129129
"""
130-
signals = {**(signals_dict if signals_dict else {}), **signals}
130+
signals = {**(signals_dict or {}), **signals}
131131
val = _js_object(signals) if expressions_ else json.dumps(signals)
132132
return SignalsAttr(value=val, alias=self._alias)
133133

134134
def computed(self, computed_dict: Mapping | None = None, /, **computed: str) -> BaseAttr:
135135
"""Create signals that are computed based on an expression."""
136-
computed = {**(computed_dict if computed_dict else {}), **computed}
136+
computed = {**(computed_dict or {}), **computed}
137137
first, *rest = (
138138
BaseAttr("computed", key=sig, value=expr, alias=self._alias)
139139
for sig, expr in computed.items()
@@ -152,16 +152,16 @@ def ignore(self) -> IgnoreAttr:
152152

153153
def attr(self, attr_dict: Mapping | None = None, /, **attrs: str) -> BaseAttr:
154154
"""Set the value of any HTML attributes to expressions, and keep them in sync."""
155-
attrs = {**(attr_dict if attr_dict else {}), **attrs}
155+
attrs = {**(attr_dict or {}), **attrs}
156156
return BaseAttr("attr", value=_js_object(attrs), alias=self._alias)
157157

158158
def bind(self, signal_name: str) -> BaseAttr:
159159
"""Set up two-way data binding between a signal and an element's value."""
160-
return BaseAttr("bind", value=signal_name, alias=self._alias)
160+
return BindAttr(value=signal_name, alias=self._alias)
161161

162162
def class_(self, class_dict: Mapping | None = None, /, **classes: str) -> BaseAttr:
163163
"""Add or removes classes to or from an element based on expressions."""
164-
classes = {**(class_dict if class_dict else {}), **classes}
164+
classes = {**(class_dict or {}), **classes}
165165
return BaseAttr("class", value=_js_object(classes), alias=self._alias)
166166

167167
def init(self, expression: str) -> InitAttr:
@@ -216,7 +216,7 @@ def show(self, expression: str) -> BaseAttr:
216216

217217
def style(self, style_dict: Mapping | None = None, /, **styles: str) -> BaseAttr:
218218
"""Set the value of inline CSS styles on an element based on an expression, and keeps them in sync."""
219-
styles = {**(style_dict if style_dict else {}), **styles}
219+
styles = {**(style_dict or {}), **styles}
220220
return BaseAttr("style", value=_js_object(styles), alias=self._alias)
221221

222222
def text(self, expression: str) -> BaseAttr:
@@ -432,6 +432,21 @@ def self(self) -> Self:
432432
return self
433433

434434

435+
class BindAttr(BaseAttr):
436+
_attr = "bind"
437+
438+
def prop(self, prop: str) -> Self:
439+
"""Bind to a specified property."""
440+
self._mods["prop"] = [prop]
441+
return self
442+
443+
def event(self, event: str | Iterable[str]) -> Self:
444+
"""Only update the signal when the specified events are fired."""
445+
events = [event] if isinstance(event, str) else list(event)
446+
self._mods["event"] = events
447+
return self
448+
449+
435450
class OnAttr(BaseAttr, TimingMod, DelayMod, ViewtransitionMod):
436451
_attr = "on"
437452

@@ -459,6 +474,12 @@ def window(self) -> Self:
459474
self._mods["window"] = []
460475
return self
461476

477+
@property
478+
def document(self) -> Self:
479+
"""Attach the event listener to the document element."""
480+
self._mods["document"] = []
481+
return self
482+
462483
@property
463484
def outside(self) -> Self:
464485
"""Trigger when the event is outside the element."""
@@ -633,7 +654,7 @@ def threshold(self, threshold: int) -> Self:
633654
class OnIntervalAttr(BaseAttr, ViewtransitionMod):
634655
_attr = "on-interval"
635656

636-
def duration(self, duration: int | float | str, *, leading: bool = False) -> Self:
657+
def duration(self, duration: float | str, *, leading: bool = False) -> Self:
637658
"""Set the interval duration."""
638659
self._mods["duration"] = [str(duration)]
639660
if leading:

src/datastar_py/litestar.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def __init__(
4646
status_code = status_code or 204
4747
content = tuple()
4848
else:
49+
status_code = status_code or 200
4950
headers = {**self.default_headers, **(headers or {})}
5051
if isinstance(content, DatastarEvent):
5152
content = (content,)

src/datastar_py/sse.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
from itertools import chain
66
from typing import Literal, Protocol, TypeAlias, overload, runtime_checkable
77

8-
import datastar_py.consts as consts
9-
from datastar_py.attributes import _escape, SignalValue
8+
from datastar_py import consts
9+
from datastar_py.attributes import SignalValue, _escape
1010

1111
SSE_HEADERS: dict[str, str] = {
1212
"Cache-Control": "no-cache",
@@ -28,7 +28,7 @@ def __html__(self) -> str: ...
2828

2929

3030
class DatastarEvent(str):
31-
pass
31+
__slots__ = ()
3232

3333

3434
# 0..N datastar events
@@ -83,7 +83,7 @@ def patch_elements(
8383
retry_duration: int | None = None,
8484
) -> DatastarEvent: ...
8585
@classmethod
86-
def patch_elements(
86+
def patch_elements( # noqa: PLR0913 too many arguments
8787
cls,
8888
elements: str | _HtmlProvider | None = None,
8989
selector: str | None = None,

0 commit comments

Comments
 (0)