Skip to content

Commit 3c4e7e3

Browse files
committed
Merge branch 'main' into yogesh-xxx-fix-vega-warnings2
2 parents a75a725 + 8bd30e2 commit 3c4e7e3

File tree

16 files changed

+141
-79
lines changed

16 files changed

+141
-79
lines changed

.github/workflows/publish.yml

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: Package and Publish
33
on:
44
release:
55
types: [published]
6+
workflow_dispatch:
67

78
jobs:
89
python-tests:
@@ -11,6 +12,9 @@ jobs:
1112
fail-fast: false
1213
matrix:
1314
python-version: ["3.10", "3.11", "3.12"]
15+
defaults:
16+
run:
17+
working-directory: chartlets.py
1418

1519
steps:
1620
- uses: actions/checkout@v3
@@ -23,7 +27,7 @@ jobs:
2327
- name: Install dependencies
2428
run: |
2529
python -m pip install --upgrade pip
26-
pip install .[dev]
30+
pip install .[dev,demo]
2731
2832
- name: Lint with flake8
2933
run: |
@@ -45,6 +49,9 @@ jobs:
4549
name: Publish Python Package to PyPI
4650
runs-on: ubuntu-latest
4751
needs: python-tests
52+
defaults:
53+
run:
54+
working-directory: chartlets.py
4855

4956
steps:
5057
- uses: actions/checkout@v4
@@ -62,20 +69,25 @@ jobs:
6269
- name: Build package
6370
run: |
6471
python -m build
65-
66-
- name: Publish to PyPI
67-
run: |
68-
pip install twine
69-
python -m twine upload --username __token__ --password ${{ secrets.PYPI_API_TOKEN }} dist/*
72+
73+
- name: Publish package to PyPI
74+
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
75+
with:
76+
user: __token__
77+
password: ${{ secrets.PYPI_API_TOKEN }}
78+
packages_dir: chartlets.py/dist
79+
verbose: true
7080

7181
npm-tests:
7282
runs-on: ubuntu-latest
73-
7483
strategy:
7584
matrix:
7685
node-version: [16.x, 18.x, 20.x]
7786
# See supported Node.js release schedule at
7887
# https://nodejs.org/en/about/releases/
88+
defaults:
89+
run:
90+
working-directory: chartlets.js
7991

8092
steps:
8193
- uses: actions/checkout@v3
@@ -84,6 +96,8 @@ jobs:
8496
with:
8597
node-version: ${{ matrix.node-version }}
8698
cache: 'npm'
99+
cache-dependency-path: chartlets.js/package-lock.json
100+
87101
- run: npm ci
88102
- run: npm run lint
89103
- run: npm run build
@@ -93,6 +107,9 @@ jobs:
93107
name: Publish TS-React Package to npmjs
94108
runs-on: ubuntu-latest
95109
needs: npm-tests
110+
defaults:
111+
run:
112+
working-directory: chartlets.js
96113

97114
steps:
98115
- uses: actions/checkout@v4
@@ -102,6 +119,9 @@ jobs:
102119
with:
103120
node-version: '18.x'
104121
registry-url: 'https://registry.npmjs.org'
122+
cache: 'npm'
123+
cache-dependency-path: chartlets.js/package-lock.json
124+
105125
- run: npm ci
106126
- run: npm run build
107127
- run: npm publish --access public

chartlets.js/CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Version 0.0.28 (from 2024/11/26)
2+
3+
* Updated docs.
4+
15
## Version 0.0.27 (from 2024/11/25)
26

37
* Added component `IconButton` and enhanced other components' attributes.

chartlets.js/TODO.md

Lines changed: 0 additions & 15 deletions
This file was deleted.

chartlets.js/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chartlets.js/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "chartlets",
3-
"version": "0.0.27",
3+
"version": "0.0.28",
44
"description": "An experimental library for integrating interactive charts into existing JavaScript applications.",
55
"type": "module",
66
"files": [

chartlets.py/CHANGES.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
## Version 0.0.x (in development)
1+
## Version 0.0.28 (from 2024/11/26)
2+
3+
* Updated docs.
24

35
* Added component `IconButton` and enhanced other components' attributes.
46

chartlets.py/chartlets/callback.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def from_decorator(
2222
decorator_name: str,
2323
decorator_args: tuple[Any, ...],
2424
function: Any,
25-
outputs_allowed: bool = False,
25+
states_only: bool = False,
2626
) -> "Callback":
2727
try:
2828
signature = inspect.signature(function)
@@ -45,22 +45,22 @@ def from_decorator(
4545
inputs: list[Input | State] = []
4646
outputs: list[Output] = []
4747
for arg in decorator_args:
48-
if isinstance(arg, (Input, State)):
49-
inputs.append(arg)
50-
elif outputs_allowed and isinstance(arg, Output):
51-
outputs.append(arg)
52-
elif outputs_allowed:
48+
if states_only and not isinstance(arg, State):
5349
raise TypeError(
5450
f"arguments for decorator {decorator_name!r}"
55-
f" must be of type Input, State, Output, AppInput,"
56-
f" or AppOutput, but got {arg.__class__.__name__!r}"
51+
f" must be of type State,"
52+
f" but got {arg.__class__.__name__!r}"
5753
)
58-
else:
54+
if not isinstance(arg, (Input, State, Output)):
5955
raise TypeError(
6056
f"arguments for decorator {decorator_name!r}"
61-
f" must be of type Input,"
57+
f" must be of type Input, State, or Output,"
6258
f" but got {arg.__class__.__name__!r}"
6359
)
60+
if isinstance(arg, Output):
61+
outputs.append(arg)
62+
else:
63+
inputs.append(arg)
6464

6565
num_params = len(signature.parameters) - 1
6666
num_inputs = len(inputs)

chartlets.py/chartlets/contribution.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from abc import ABC
33

44
from .callback import Callback
5-
from .channel import Channel
5+
from .channel import Input, State, Output
66

77

88
class Contribution(ABC):
@@ -20,7 +20,7 @@ class Contribution(ABC):
2020
"""
2121

2222
# noinspection PyShadowingBuiltins
23-
def __init__(self, name: str, **initial_state):
23+
def __init__(self, name: str, **initial_state: Any):
2424
self.name = name
2525
self.initial_state = initial_state
2626
self.extension: str | None = None
@@ -47,7 +47,7 @@ def to_dict(self) -> dict[str, Any]:
4747
d.update(callbacks=[cb.to_dict() for cb in self.callbacks])
4848
return d
4949

50-
def layout(self, *args) -> Callable[[Callable], Callable]:
50+
def layout(self, *args: State) -> Callable[[Callable], Callable]:
5151
"""Provides a decorator for a user-provided function that
5252
returns the initial user interface layout.
5353
@@ -65,13 +65,12 @@ def layout(self, *args) -> Callable[[Callable], Callable]:
6565
called `ctx`.
6666
6767
Other parameters of the decorated function are user-defined
68-
and must have a corresponding `chartlets.Input` or
69-
`chartlets.State` arguments in the `layout` decorator in the
70-
same order.
68+
and must have a corresponding `chartlets.State` arguments
69+
in the `layout` decorator in the same order.
7170
7271
Args:
7372
args:
74-
`chartlets.Input` or `chartlets.State` objects that
73+
`chartlets.State` objects that
7574
define the source of the value for the corresponding
7675
parameter of the decorated function. Optional.
7776
@@ -81,13 +80,13 @@ def layout(self, *args) -> Callable[[Callable], Callable]:
8180

8281
def decorator(function: Callable) -> Callable:
8382
self.layout_callback = Callback.from_decorator(
84-
"layout", args, function, outputs_allowed=False
83+
"layout", args, function, states_only=True
8584
)
8685
return function
8786

8887
return decorator
8988

90-
def callback(self, *args: Channel) -> Callable[[Callable], Callable]:
89+
def callback(self, *args: Input | State | Output) -> Callable[[Callable], Callable]:
9190
"""Provide a decorator for a user-provided callback function.
9291
9392
Callback functions are event handlers that react
@@ -125,7 +124,7 @@ def callback(self, *args: Channel) -> Callable[[Callable], Callable]:
125124
def decorator(function: Callable) -> Callable:
126125
self.callbacks.append(
127126
Callback.from_decorator(
128-
"callback", args, function, outputs_allowed=True
127+
"callback", args, function, states_only=False
129128
)
130129
)
131130
return function

chartlets.py/chartlets/demo/server.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,18 @@
1919
from chartlets.demo.contribs import Panel
2020
from chartlets.demo.utils import NumpyJSONEncoder
2121

22-
DASHI_CONTEXT_KEY = "chartlets.context"
2322

2423
# This would be done by a xcube server extension
2524
Extension.add_contrib_point("panels", Panel)
2625

2726

27+
_CONTEXT_KEY = "chartlets.context"
28+
29+
2830
class DashiHandler(tornado.web.RequestHandler):
2931
@property
3032
def ext_ctx(self) -> ExtensionContext:
31-
return self.settings[DASHI_CONTEXT_KEY]
33+
return self.settings[_CONTEXT_KEY]
3234

3335
def set_default_headers(self):
3436
self.set_header("Access-Control-Allow-Origin", "*")
@@ -97,7 +99,7 @@ def print_usage(app, port):
9799
print(f"Listening on {url}...")
98100
print(f"API:")
99101
print(f"- {url}/chartlets/contributions")
100-
ext_ctx: ExtensionContext = app.settings[DASHI_CONTEXT_KEY]
102+
ext_ctx: ExtensionContext = app.settings[_CONTEXT_KEY]
101103
for contrib_point_name, contributions in ext_ctx.contributions.items():
102104
for i in range(len(contributions)):
103105
print(f"- {url}/chartlets/layout/{contrib_point_name}/{i}")
@@ -120,7 +122,7 @@ def make_app():
120122

121123
# Load extensions
122124
ext_ctx = ExtensionContext.load(Context(), server_config.get("extensions", []))
123-
app.settings[DASHI_CONTEXT_KEY] = ext_ctx
125+
app.settings[_CONTEXT_KEY] = ext_ctx
124126

125127
return app
126128

chartlets.py/chartlets/extension.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,29 @@
44

55

66
class Extension:
7-
"""A UI Extension."""
7+
"""An extension for a UI application that
8+
uses the Chartlets JS framework."""
89

910
_contrib_points: dict[type[Contribution], str] = {}
1011

1112
@classmethod
1213
def add_contrib_point(cls, name: str, item_type: type[Contribution]):
14+
"""Add a contribution point.
15+
16+
Args:
17+
name: The name of the contribution point.
18+
item_type: The type of items that can be added
19+
to the new contribution point.
20+
"""
1321
cls._contrib_points[item_type] = name
1422

1523
@classmethod
1624
def get_contrib_point_names(cls) -> tuple[str, ...]:
25+
"""Get names of all known contribution points added
26+
by the `add_contrib_point()` method.
27+
28+
Returns: Tuple of registered contribution point names.
29+
"""
1730
values = cls._contrib_points.values()
1831
# noinspection PyTypeChecker
1932
return tuple(values)
@@ -26,6 +39,13 @@ def __init__(self, name: str, version: str = "0.0.0"):
2639
setattr(self, contrib_point_name, [])
2740

2841
def add(self, contribution: Contribution):
42+
"""Add a contribution to this extension.
43+
44+
Args:
45+
contribution: The contribution.
46+
Its type must be an instance of one of the
47+
registered contribution types.
48+
"""
2949
contrib_type = type(contribution)
3050
contrib_point_name = self._contrib_points.get(contrib_type)
3151
if contrib_point_name is None:
@@ -37,6 +57,10 @@ def add(self, contribution: Contribution):
3757
contributions.append(contribution)
3858

3959
def to_dict(self) -> dict[str, Any]:
60+
"""Convert this extension into a JSON-serializable dictionary.
61+
62+
Returns: A dictionary representing this extension.
63+
"""
4064
return dict(
4165
name=self.name,
4266
version=self.version,

0 commit comments

Comments
 (0)