reacton 1.8.3__tar.gz → 1.9.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {reacton-1.8.3 → reacton-1.9.0}/PKG-INFO +7 -5
- {reacton-1.8.3 → reacton-1.9.0}/pyproject.toml +5 -9
- {reacton-1.8.3 → reacton-1.9.0}/reacton/__init__.py +2 -0
- reacton-1.9.0/reacton/_version.py +1 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/bqplot.py +0 -39
- {reacton-1.8.3 → reacton-1.9.0}/reacton/core.py +53 -40
- {reacton-1.8.3 → reacton-1.9.0}/reacton/core_test.py +66 -4
- {reacton-1.8.3 → reacton-1.9.0}/reacton/deprecated/ipyvuetify.py +1 -1
- {reacton-1.8.3 → reacton-1.9.0}/reacton/generate.py +21 -7
- {reacton-1.8.3 → reacton-1.9.0}/reacton/generate_test.py +6 -4
- {reacton-1.8.3 → reacton-1.9.0}/reacton/ipycanvas.py +0 -2
- reacton-1.9.0/reacton/ipyvuetify.py +7 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/ipywidgets.py +0 -9
- {reacton-1.8.3 → reacton-1.9.0}/reacton/logging.py +1 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/utils_test.py +0 -1
- reacton-1.8.3/reacton/_version.py +0 -1
- reacton-1.8.3/reacton/ipyvuetify.py +0 -7
- {reacton-1.8.3 → reacton-1.9.0}/.gitignore +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/LICENSE +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/react_ipywidgets/__init__.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/react_ipywidgets/core.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/deprecated/__init__.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/find.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/find_test.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/ipyvue.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/patch.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/patch_display.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/py.typed +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/rx.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/test.vue +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/test_rx.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/utils.py +0 -0
- {reacton-1.8.3 → reacton-1.9.0}/reacton/work.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: reacton
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.0
|
|
4
|
+
Dynamic: Summary
|
|
4
5
|
Project-URL: Home, https://www.github.com/widgetti/reacton
|
|
5
6
|
Project-URL: Documentation, https://reacton.solara.dev
|
|
6
7
|
Project-URL: Source code, https://www.github.com/widgetti/reacton
|
|
@@ -36,24 +37,25 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
36
37
|
Classifier: Programming Language :: Python :: 3.9
|
|
37
38
|
Classifier: Programming Language :: Python :: 3.10
|
|
38
39
|
Classifier: Programming Language :: Python :: 3.11
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
42
|
Classifier: Topic :: Software Development :: User Interfaces
|
|
40
43
|
Requires-Dist: ipywidgets
|
|
41
44
|
Requires-Dist: typing-extensions>=4.1.1
|
|
42
45
|
Provides-Extra: dev
|
|
43
|
-
Requires-Dist: black; extra == 'dev'
|
|
44
46
|
Requires-Dist: bqplot; extra == 'dev'
|
|
45
47
|
Requires-Dist: bump2version; extra == 'dev'
|
|
46
48
|
Requires-Dist: coverage; extra == 'dev'
|
|
47
|
-
Requires-Dist: flake8; extra == 'dev'
|
|
48
49
|
Requires-Dist: ipykernel; extra == 'dev'
|
|
49
50
|
Requires-Dist: ipyvuetify; extra == 'dev'
|
|
50
51
|
Requires-Dist: jinja2; extra == 'dev'
|
|
51
52
|
Requires-Dist: mypy; extra == 'dev'
|
|
52
|
-
Requires-Dist: numpy; extra == 'dev'
|
|
53
|
+
Requires-Dist: numpy<2; extra == 'dev'
|
|
53
54
|
Requires-Dist: pandas; extra == 'dev'
|
|
54
55
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
55
56
|
Requires-Dist: pytest; extra == 'dev'
|
|
56
57
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
58
|
+
Requires-Dist: ruff; (python_version > '3.6') and extra == 'dev'
|
|
57
59
|
Provides-Extra: generate
|
|
58
60
|
Requires-Dist: black; extra == 'generate'
|
|
59
61
|
Requires-Dist: bqplot; extra == 'generate'
|
|
@@ -22,6 +22,8 @@ classifiers = [
|
|
|
22
22
|
"Programming Language :: Python :: 3.9",
|
|
23
23
|
"Programming Language :: Python :: 3.10",
|
|
24
24
|
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
25
27
|
"Framework :: Jupyter",
|
|
26
28
|
"Topic :: Software Development :: User Interfaces",
|
|
27
29
|
"Environment :: Web Environment",
|
|
@@ -39,15 +41,14 @@ packages = ["react_ipywidgets", "reacton"]
|
|
|
39
41
|
|
|
40
42
|
[project.optional-dependencies]
|
|
41
43
|
dev = [
|
|
42
|
-
"
|
|
43
|
-
"black",
|
|
44
|
+
"ruff; python_version > '3.6'",
|
|
44
45
|
"mypy",
|
|
45
46
|
"pre-commit",
|
|
46
47
|
"coverage",
|
|
47
48
|
"pytest",
|
|
48
49
|
"pytest-cov",
|
|
49
50
|
"bqplot",
|
|
50
|
-
"numpy",
|
|
51
|
+
"numpy<2",
|
|
51
52
|
"ipyvuetify",
|
|
52
53
|
"bump2version",
|
|
53
54
|
"jinja2",
|
|
@@ -67,11 +68,6 @@ Home = "https://www.github.com/widgetti/reacton"
|
|
|
67
68
|
Documentation = "https://reacton.solara.dev"
|
|
68
69
|
"Source code" = "https://www.github.com/widgetti/reacton"
|
|
69
70
|
|
|
70
|
-
[tool.black]
|
|
71
|
-
line-length = 160
|
|
72
|
-
|
|
73
71
|
[tool.ruff]
|
|
74
72
|
line-length = 160
|
|
75
|
-
|
|
76
|
-
[tool.isort]
|
|
77
|
-
profile = "black"
|
|
73
|
+
target-version = "py37"
|
|
@@ -11,6 +11,7 @@ from . import _version
|
|
|
11
11
|
|
|
12
12
|
__version__ = _version.__version__
|
|
13
13
|
from .core import (
|
|
14
|
+
Fragment,
|
|
14
15
|
component,
|
|
15
16
|
component_interactive,
|
|
16
17
|
create_context,
|
|
@@ -34,6 +35,7 @@ from .core import (
|
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
__all__ = [
|
|
38
|
+
"Fragment",
|
|
37
39
|
"__version__",
|
|
38
40
|
"component",
|
|
39
41
|
"value_component",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.9.0"
|
|
@@ -24,7 +24,6 @@ class FigureElement(Element[bqplot.Figure]):
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
if __name__ == "__main__":
|
|
27
|
-
|
|
28
27
|
from . import generate
|
|
29
28
|
|
|
30
29
|
class CodeGen(generate.CodeGen):
|
|
@@ -90,7 +89,6 @@ def _Albers(
|
|
|
90
89
|
|
|
91
90
|
@implements(_Albers)
|
|
92
91
|
def Albers(**kwargs):
|
|
93
|
-
|
|
94
92
|
widget_cls = bqplot.scales.Albers
|
|
95
93
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
96
94
|
return Element(comp, kwargs=kwargs)
|
|
@@ -130,7 +128,6 @@ def _AlbersUSA(
|
|
|
130
128
|
|
|
131
129
|
@implements(_AlbersUSA)
|
|
132
130
|
def AlbersUSA(**kwargs):
|
|
133
|
-
|
|
134
131
|
widget_cls = bqplot.scales.AlbersUSA
|
|
135
132
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
136
133
|
return Element(comp, kwargs=kwargs)
|
|
@@ -235,7 +232,6 @@ def _Axis(
|
|
|
235
232
|
|
|
236
233
|
@implements(_Axis)
|
|
237
234
|
def Axis(**kwargs):
|
|
238
|
-
|
|
239
235
|
widget_cls = bqplot.axes.Axis
|
|
240
236
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
241
237
|
return Element(comp, kwargs=kwargs)
|
|
@@ -402,7 +398,6 @@ def _Bars(
|
|
|
402
398
|
|
|
403
399
|
@implements(_Bars)
|
|
404
400
|
def Bars(**kwargs):
|
|
405
|
-
|
|
406
401
|
widget_cls = bqplot.marks.Bars
|
|
407
402
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
408
403
|
return Element(comp, kwargs=kwargs)
|
|
@@ -418,7 +413,6 @@ def _BaseAxis() -> Element[bqplot.axes.BaseAxis]:
|
|
|
418
413
|
|
|
419
414
|
@implements(_BaseAxis)
|
|
420
415
|
def BaseAxis(**kwargs):
|
|
421
|
-
|
|
422
416
|
widget_cls = bqplot.axes.BaseAxis
|
|
423
417
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
424
418
|
return Element(comp, kwargs=kwargs)
|
|
@@ -569,7 +563,6 @@ def _Bins(
|
|
|
569
563
|
|
|
570
564
|
@implements(_Bins)
|
|
571
565
|
def Bins(**kwargs):
|
|
572
|
-
|
|
573
566
|
widget_cls = bqplot.marks.Bins
|
|
574
567
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
575
568
|
return Element(comp, kwargs=kwargs)
|
|
@@ -659,7 +652,6 @@ def _Boxplot(
|
|
|
659
652
|
|
|
660
653
|
@implements(_Boxplot)
|
|
661
654
|
def Boxplot(**kwargs):
|
|
662
|
-
|
|
663
655
|
widget_cls = bqplot.marks.Boxplot
|
|
664
656
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
665
657
|
return Element(comp, kwargs=kwargs)
|
|
@@ -720,7 +712,6 @@ def _ColorAxis(
|
|
|
720
712
|
|
|
721
713
|
@implements(_ColorAxis)
|
|
722
714
|
def ColorAxis(**kwargs):
|
|
723
|
-
|
|
724
715
|
widget_cls = bqplot.axes.ColorAxis
|
|
725
716
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
726
717
|
return Element(comp, kwargs=kwargs)
|
|
@@ -781,7 +772,6 @@ def _ColorScale(
|
|
|
781
772
|
|
|
782
773
|
@implements(_ColorScale)
|
|
783
774
|
def ColorScale(**kwargs):
|
|
784
|
-
|
|
785
775
|
widget_cls = bqplot.scales.ColorScale
|
|
786
776
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
787
777
|
return Element(comp, kwargs=kwargs)
|
|
@@ -855,7 +845,6 @@ def _DateColorScale(
|
|
|
855
845
|
|
|
856
846
|
@implements(_DateColorScale)
|
|
857
847
|
def DateColorScale(**kwargs):
|
|
858
|
-
|
|
859
848
|
widget_cls = bqplot.scales.DateColorScale
|
|
860
849
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
861
850
|
return Element(comp, kwargs=kwargs)
|
|
@@ -899,7 +888,6 @@ def _DateScale(
|
|
|
899
888
|
|
|
900
889
|
@implements(_DateScale)
|
|
901
890
|
def DateScale(**kwargs):
|
|
902
|
-
|
|
903
891
|
widget_cls = bqplot.scales.DateScale
|
|
904
892
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
905
893
|
return Element(comp, kwargs=kwargs)
|
|
@@ -936,7 +924,6 @@ def _EquiRectangular(
|
|
|
936
924
|
|
|
937
925
|
@implements(_EquiRectangular)
|
|
938
926
|
def EquiRectangular(**kwargs):
|
|
939
|
-
|
|
940
927
|
widget_cls = bqplot.scales.EquiRectangular
|
|
941
928
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
942
929
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1168,7 +1155,6 @@ def _FlexLine(
|
|
|
1168
1155
|
|
|
1169
1156
|
@implements(_FlexLine)
|
|
1170
1157
|
def FlexLine(**kwargs):
|
|
1171
|
-
|
|
1172
1158
|
widget_cls = bqplot.marks.FlexLine
|
|
1173
1159
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1174
1160
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1195,7 +1181,6 @@ def _GeoScale(
|
|
|
1195
1181
|
|
|
1196
1182
|
@implements(_GeoScale)
|
|
1197
1183
|
def GeoScale(**kwargs):
|
|
1198
|
-
|
|
1199
1184
|
widget_cls = bqplot.scales.GeoScale
|
|
1200
1185
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1201
1186
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1241,7 +1226,6 @@ def _Gnomonic(
|
|
|
1241
1226
|
|
|
1242
1227
|
@implements(_Gnomonic)
|
|
1243
1228
|
def Gnomonic(**kwargs):
|
|
1244
|
-
|
|
1245
1229
|
widget_cls = bqplot.scales.Gnomonic
|
|
1246
1230
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1247
1231
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1366,7 +1350,6 @@ def _Graph(
|
|
|
1366
1350
|
|
|
1367
1351
|
@implements(_Graph)
|
|
1368
1352
|
def Graph(**kwargs):
|
|
1369
|
-
|
|
1370
1353
|
widget_cls = bqplot.marks.Graph
|
|
1371
1354
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1372
1355
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1500,7 +1483,6 @@ def _GridHeatMap(
|
|
|
1500
1483
|
|
|
1501
1484
|
@implements(_GridHeatMap)
|
|
1502
1485
|
def GridHeatMap(**kwargs):
|
|
1503
|
-
|
|
1504
1486
|
widget_cls = bqplot.marks.GridHeatMap
|
|
1505
1487
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1506
1488
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1579,7 +1561,6 @@ def _HeatMap(
|
|
|
1579
1561
|
|
|
1580
1562
|
@implements(_HeatMap)
|
|
1581
1563
|
def HeatMap(**kwargs):
|
|
1582
|
-
|
|
1583
1564
|
widget_cls = bqplot.marks.HeatMap
|
|
1584
1565
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1585
1566
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1687,7 +1668,6 @@ def _Hist(
|
|
|
1687
1668
|
|
|
1688
1669
|
@implements(_Hist)
|
|
1689
1670
|
def Hist(**kwargs):
|
|
1690
|
-
|
|
1691
1671
|
widget_cls = bqplot.marks.Hist
|
|
1692
1672
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1693
1673
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1761,7 +1741,6 @@ def _Image(
|
|
|
1761
1741
|
|
|
1762
1742
|
@implements(_Image)
|
|
1763
1743
|
def Image(**kwargs):
|
|
1764
|
-
|
|
1765
1744
|
widget_cls = bqplot.marks.Image
|
|
1766
1745
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1767
1746
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1794,7 +1773,6 @@ def _Interaction() -> Element[bqplot.interacts.Interaction]:
|
|
|
1794
1773
|
|
|
1795
1774
|
@implements(_Interaction)
|
|
1796
1775
|
def Interaction(**kwargs):
|
|
1797
|
-
|
|
1798
1776
|
widget_cls = bqplot.interacts.Interaction
|
|
1799
1777
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1800
1778
|
return Element(comp, kwargs=kwargs)
|
|
@@ -1948,7 +1926,6 @@ def _Label(
|
|
|
1948
1926
|
|
|
1949
1927
|
@implements(_Label)
|
|
1950
1928
|
def Label(**kwargs):
|
|
1951
|
-
|
|
1952
1929
|
widget_cls = bqplot.marks.Label
|
|
1953
1930
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
1954
1931
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2014,7 +1991,6 @@ def _LinearScale(
|
|
|
2014
1991
|
|
|
2015
1992
|
@implements(_LinearScale)
|
|
2016
1993
|
def LinearScale(**kwargs):
|
|
2017
|
-
|
|
2018
1994
|
widget_cls = bqplot.scales.LinearScale
|
|
2019
1995
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2020
1996
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2166,7 +2142,6 @@ def _Lines(
|
|
|
2166
2142
|
|
|
2167
2143
|
@implements(_Lines)
|
|
2168
2144
|
def Lines(**kwargs):
|
|
2169
|
-
|
|
2170
2145
|
widget_cls = bqplot.marks.Lines
|
|
2171
2146
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2172
2147
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2208,7 +2183,6 @@ def _LogScale(
|
|
|
2208
2183
|
|
|
2209
2184
|
@implements(_LogScale)
|
|
2210
2185
|
def LogScale(**kwargs):
|
|
2211
|
-
|
|
2212
2186
|
widget_cls = bqplot.scales.LogScale
|
|
2213
2187
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2214
2188
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2298,7 +2272,6 @@ def _Map(
|
|
|
2298
2272
|
|
|
2299
2273
|
@implements(_Map)
|
|
2300
2274
|
def Map(**kwargs):
|
|
2301
|
-
|
|
2302
2275
|
widget_cls = bqplot.marks.Map
|
|
2303
2276
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2304
2277
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2423,7 +2396,6 @@ def _Mark(
|
|
|
2423
2396
|
|
|
2424
2397
|
@implements(_Mark)
|
|
2425
2398
|
def Mark(**kwargs):
|
|
2426
|
-
|
|
2427
2399
|
widget_cls = bqplot.marks.Mark
|
|
2428
2400
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2429
2401
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2470,7 +2442,6 @@ def _Mercator(
|
|
|
2470
2442
|
|
|
2471
2443
|
@implements(_Mercator)
|
|
2472
2444
|
def Mercator(**kwargs):
|
|
2473
|
-
|
|
2474
2445
|
widget_cls = bqplot.scales.Mercator
|
|
2475
2446
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2476
2447
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2574,7 +2545,6 @@ def _OHLC(
|
|
|
2574
2545
|
|
|
2575
2546
|
@implements(_OHLC)
|
|
2576
2547
|
def OHLC(**kwargs):
|
|
2577
|
-
|
|
2578
2548
|
widget_cls = bqplot.marks.OHLC
|
|
2579
2549
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2580
2550
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2626,7 +2596,6 @@ def _OrdinalColorScale(
|
|
|
2626
2596
|
|
|
2627
2597
|
@implements(_OrdinalColorScale)
|
|
2628
2598
|
def OrdinalColorScale(**kwargs):
|
|
2629
|
-
|
|
2630
2599
|
widget_cls = bqplot.scales.OrdinalColorScale
|
|
2631
2600
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2632
2601
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2664,7 +2633,6 @@ def _OrdinalScale(
|
|
|
2664
2633
|
|
|
2665
2634
|
@implements(_OrdinalScale)
|
|
2666
2635
|
def OrdinalScale(**kwargs):
|
|
2667
|
-
|
|
2668
2636
|
widget_cls = bqplot.scales.OrdinalScale
|
|
2669
2637
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2670
2638
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2715,7 +2683,6 @@ def _Orthographic(
|
|
|
2715
2683
|
|
|
2716
2684
|
@implements(_Orthographic)
|
|
2717
2685
|
def Orthographic(**kwargs):
|
|
2718
|
-
|
|
2719
2686
|
widget_cls = bqplot.scales.Orthographic
|
|
2720
2687
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2721
2688
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2752,7 +2719,6 @@ def _PanZoom(
|
|
|
2752
2719
|
|
|
2753
2720
|
@implements(_PanZoom)
|
|
2754
2721
|
def PanZoom(**kwargs):
|
|
2755
|
-
|
|
2756
2722
|
widget_cls = bqplot.interacts.PanZoom
|
|
2757
2723
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2758
2724
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2893,7 +2859,6 @@ def _Pie(
|
|
|
2893
2859
|
|
|
2894
2860
|
@implements(_Pie)
|
|
2895
2861
|
def Pie(**kwargs):
|
|
2896
|
-
|
|
2897
2862
|
widget_cls = bqplot.marks.Pie
|
|
2898
2863
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2899
2864
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2935,7 +2900,6 @@ def _Scale(
|
|
|
2935
2900
|
|
|
2936
2901
|
@implements(_Scale)
|
|
2937
2902
|
def Scale(**kwargs):
|
|
2938
|
-
|
|
2939
2903
|
widget_cls = bqplot.scales.Scale
|
|
2940
2904
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2941
2905
|
return Element(comp, kwargs=kwargs)
|
|
@@ -3149,7 +3113,6 @@ def _Scatter(
|
|
|
3149
3113
|
|
|
3150
3114
|
@implements(_Scatter)
|
|
3151
3115
|
def Scatter(**kwargs):
|
|
3152
|
-
|
|
3153
3116
|
widget_cls = bqplot.marks.Scatter
|
|
3154
3117
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
3155
3118
|
return Element(comp, kwargs=kwargs)
|
|
@@ -3264,7 +3227,6 @@ def _ScatterGL(
|
|
|
3264
3227
|
|
|
3265
3228
|
@implements(_ScatterGL)
|
|
3266
3229
|
def ScatterGL(**kwargs):
|
|
3267
|
-
|
|
3268
3230
|
widget_cls = bqplot.marks.ScatterGL
|
|
3269
3231
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
3270
3232
|
return Element(comp, kwargs=kwargs)
|
|
@@ -3315,7 +3277,6 @@ def _Stereographic(
|
|
|
3315
3277
|
|
|
3316
3278
|
@implements(_Stereographic)
|
|
3317
3279
|
def Stereographic(**kwargs):
|
|
3318
|
-
|
|
3319
3280
|
widget_cls = bqplot.scales.Stereographic
|
|
3320
3281
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
3321
3282
|
return Element(comp, kwargs=kwargs)
|
|
@@ -6,6 +6,7 @@ ReactJS - ipywidgets relation:
|
|
|
6
6
|
* Component -- function
|
|
7
7
|
|
|
8
8
|
"""
|
|
9
|
+
|
|
9
10
|
import contextlib
|
|
10
11
|
import copy
|
|
11
12
|
import functools
|
|
@@ -230,6 +231,7 @@ class Element(Generic[W]):
|
|
|
230
231
|
self._meta = {}
|
|
231
232
|
# for debugging/testing only
|
|
232
233
|
self._render_count = 0
|
|
234
|
+
self._key_frozen: bool = False
|
|
233
235
|
|
|
234
236
|
rc = _get_render_context(required=False)
|
|
235
237
|
if rc is not None and rc.container_adders:
|
|
@@ -269,6 +271,8 @@ class Element(Generic[W]):
|
|
|
269
271
|
|
|
270
272
|
This can help render performance. See documentation for details.
|
|
271
273
|
"""
|
|
274
|
+
if self._key_frozen:
|
|
275
|
+
raise RuntimeError("Element keys should not be mutated after rendering")
|
|
272
276
|
self._key = value
|
|
273
277
|
return self
|
|
274
278
|
|
|
@@ -333,7 +337,7 @@ class Element(Generic[W]):
|
|
|
333
337
|
|
|
334
338
|
def __enter__(self):
|
|
335
339
|
rc = _get_render_context()
|
|
336
|
-
ca = ContainerAdder[
|
|
340
|
+
ca = ContainerAdder[W](self, "children")
|
|
337
341
|
assert rc.context is not None
|
|
338
342
|
rc.container_adders.append(ca)
|
|
339
343
|
return self
|
|
@@ -475,11 +479,9 @@ class Element(Generic[W]):
|
|
|
475
479
|
|
|
476
480
|
|
|
477
481
|
class Value(Generic[V], Protocol):
|
|
478
|
-
def get(self) -> V:
|
|
479
|
-
...
|
|
482
|
+
def get(self) -> V: ...
|
|
480
483
|
|
|
481
|
-
def set(self, value: V):
|
|
482
|
-
...
|
|
484
|
+
def set(self, value: V): ...
|
|
483
485
|
|
|
484
486
|
|
|
485
487
|
class ValueElement(Generic[W, V], Element[W]):
|
|
@@ -677,18 +679,15 @@ class ComponentFunction(Component):
|
|
|
677
679
|
|
|
678
680
|
|
|
679
681
|
@overload
|
|
680
|
-
def component(obj: None = None, mime_bundle=...) -> Callable[[FuncT], FuncT]:
|
|
681
|
-
...
|
|
682
|
+
def component(obj: None = None, mime_bundle=...) -> Callable[[FuncT], FuncT]: ...
|
|
682
683
|
|
|
683
684
|
|
|
684
685
|
@overload
|
|
685
|
-
def component(obj: FuncT, mime_bundle=...) -> FuncT:
|
|
686
|
-
...
|
|
686
|
+
def component(obj: FuncT, mime_bundle=...) -> FuncT: ...
|
|
687
687
|
|
|
688
688
|
|
|
689
689
|
@overload
|
|
690
|
-
def component(obj: Callable[P, None], mime_bundle=...) -> Callable[P, Element]:
|
|
691
|
-
...
|
|
690
|
+
def component(obj: Callable[P, None], mime_bundle=...) -> Callable[P, Element]: ...
|
|
692
691
|
|
|
693
692
|
|
|
694
693
|
# it is actually this...
|
|
@@ -712,15 +711,13 @@ def component(obj: Union[Callable[P, None], FuncT] = None, mime_bundle: Dict[str
|
|
|
712
711
|
@overload
|
|
713
712
|
def value_component(
|
|
714
713
|
value_type: None, value_name="value", mime_bundle: Dict[str, Any] = mime_bundle_default
|
|
715
|
-
) -> Callable[[Callable[P, ValueElement[W, V]]], Callable[P, ValueElement[W, V]]]:
|
|
716
|
-
...
|
|
714
|
+
) -> Callable[[Callable[P, ValueElement[W, V]]], Callable[P, ValueElement[W, V]]]: ...
|
|
717
715
|
|
|
718
716
|
|
|
719
717
|
@overload
|
|
720
718
|
def value_component(
|
|
721
719
|
value_type: Type[V], value_name="value", mime_bundle: Dict[str, Any] = mime_bundle_default
|
|
722
|
-
) -> Callable[[Callable[P, Element[W]]], Callable[P, ValueElement[W, V]]]:
|
|
723
|
-
...
|
|
720
|
+
) -> Callable[[Callable[P, Element[W]]], Callable[P, ValueElement[W, V]]]: ...
|
|
724
721
|
|
|
725
722
|
|
|
726
723
|
def value_component(value_type: Union[Type[V], None], value_name="value", mime_bundle: Dict[str, Any] = mime_bundle_default):
|
|
@@ -835,13 +832,11 @@ def use_state_widget(widget: widgets.Widget, prop_name, key=None):
|
|
|
835
832
|
|
|
836
833
|
|
|
837
834
|
@overload
|
|
838
|
-
def get_render_context(required: Literal[True] = ...) -> "_RenderContext":
|
|
839
|
-
...
|
|
835
|
+
def get_render_context(required: Literal[True] = ...) -> "_RenderContext": ...
|
|
840
836
|
|
|
841
837
|
|
|
842
838
|
@overload
|
|
843
|
-
def get_render_context(required: Literal[False] = ...) -> Optional["_RenderContext"]:
|
|
844
|
-
...
|
|
839
|
+
def get_render_context(required: Literal[False] = ...) -> Optional["_RenderContext"]: ...
|
|
845
840
|
|
|
846
841
|
|
|
847
842
|
def get_render_context(required=True):
|
|
@@ -1588,6 +1583,7 @@ class _RenderContext:
|
|
|
1588
1583
|
key = el._key
|
|
1589
1584
|
if key is None:
|
|
1590
1585
|
key = default_key
|
|
1586
|
+
el._key_frozen = True
|
|
1591
1587
|
|
|
1592
1588
|
logger.debug("Render: (%s,%s) - %r", parent_key, key, element)
|
|
1593
1589
|
|
|
@@ -1697,7 +1693,6 @@ class _RenderContext:
|
|
|
1697
1693
|
# back the root element
|
|
1698
1694
|
root_element: Optional[Element] = None
|
|
1699
1695
|
try:
|
|
1700
|
-
stack = contextlib.ExitStack()
|
|
1701
1696
|
with contextlib.ExitStack() as stack:
|
|
1702
1697
|
for cm in context.context_managers:
|
|
1703
1698
|
stack.enter_context(cm)
|
|
@@ -1795,8 +1790,6 @@ class _RenderContext:
|
|
|
1795
1790
|
kwargs = el.kwargs.copy()
|
|
1796
1791
|
key = el._key
|
|
1797
1792
|
if key is None:
|
|
1798
|
-
if default_key == "/":
|
|
1799
|
-
default_key = "/"
|
|
1800
1793
|
key = default_key
|
|
1801
1794
|
assert key is not None
|
|
1802
1795
|
logger.debug("Reconsolidate: (%s,%s) %r", parent_key, key, el)
|
|
@@ -1807,7 +1800,6 @@ class _RenderContext:
|
|
|
1807
1800
|
|
|
1808
1801
|
already_reconsolidated = el in self._shared_elements
|
|
1809
1802
|
if already_reconsolidated and el is not self.element and el.is_shared:
|
|
1810
|
-
|
|
1811
1803
|
logger.debug("Reconsolidate: Using existing widget (prev = %r)", el_prev)
|
|
1812
1804
|
# keeping this for debugging
|
|
1813
1805
|
# logger.debug("Current:")
|
|
@@ -1891,6 +1883,9 @@ class _RenderContext:
|
|
|
1891
1883
|
context.needs_render = True
|
|
1892
1884
|
effect = child_context.effects[effect_index] = effect.next
|
|
1893
1885
|
try:
|
|
1886
|
+
if child_context.exceptions_self or child_context.exceptions_children:
|
|
1887
|
+
# we had an exception, so we skip the effect (not the cleanup)
|
|
1888
|
+
continue
|
|
1894
1889
|
effect()
|
|
1895
1890
|
except BaseException as e:
|
|
1896
1891
|
context.exceptions_self.append(e)
|
|
@@ -1899,6 +1894,9 @@ class _RenderContext:
|
|
|
1899
1894
|
context.needs_render = True
|
|
1900
1895
|
else:
|
|
1901
1896
|
try:
|
|
1897
|
+
if child_context.exceptions_self or child_context.exceptions_children:
|
|
1898
|
+
# we had an exception, so we skip the effect (not the cleanup)
|
|
1899
|
+
continue
|
|
1902
1900
|
effect()
|
|
1903
1901
|
except BaseException as e:
|
|
1904
1902
|
context.exceptions_self.append(e)
|
|
@@ -2044,12 +2042,12 @@ class _RenderContext:
|
|
|
2044
2042
|
raise
|
|
2045
2043
|
finally:
|
|
2046
2044
|
# this marks the work as 'done'
|
|
2045
|
+
# move from _elemens_next to _elements
|
|
2047
2046
|
context.elements[key] = context.elements_next.pop(key)
|
|
2048
2047
|
|
|
2049
2048
|
if el_prev in self._shared_elements:
|
|
2050
2049
|
self._shared_elements.remove(el_prev)
|
|
2051
2050
|
|
|
2052
|
-
# move from _elemens_next to _elements
|
|
2053
2051
|
if el.is_shared:
|
|
2054
2052
|
assert el not in self._shared_elements
|
|
2055
2053
|
self._shared_elements.add(el)
|
|
@@ -2082,8 +2080,6 @@ class _RenderContext:
|
|
|
2082
2080
|
def _remove_element(self, el: Element, default_key: str, parent_key):
|
|
2083
2081
|
key = el._key
|
|
2084
2082
|
if key is None:
|
|
2085
|
-
if default_key == "/":
|
|
2086
|
-
default_key = "/"
|
|
2087
2083
|
key = default_key
|
|
2088
2084
|
assert key is not None
|
|
2089
2085
|
assert self.context is not None
|
|
@@ -2123,6 +2119,17 @@ class _RenderContext:
|
|
|
2123
2119
|
new_parent_key = join_key(parent_key, key)
|
|
2124
2120
|
self._remove_element(self.context.root_element, "/", parent_key=new_parent_key)
|
|
2125
2121
|
finally:
|
|
2122
|
+
try:
|
|
2123
|
+
assert not child_context.elements, f"left over elements {child_context.elements}"
|
|
2124
|
+
assert not child_context.element_to_widget, f"left over element_to_widget {child_context.element_to_widget}"
|
|
2125
|
+
assert not child_context.widgets, f"left over widgets {child_context.widgets}"
|
|
2126
|
+
assert not child_context.children, f"left over children {child_context.children}"
|
|
2127
|
+
assert not child_context.owns, f"left over owns {child_context.owns}"
|
|
2128
|
+
# TODO: this is not the case when an exception occurs
|
|
2129
|
+
# assert not child_context.children_next, f"left over children {child_context.children_next}"
|
|
2130
|
+
except Exception as e:
|
|
2131
|
+
child_context.exceptions_self.append(e)
|
|
2132
|
+
|
|
2126
2133
|
# restore context
|
|
2127
2134
|
self.context = context
|
|
2128
2135
|
if child_context.exceptions_self or child_context.exceptions_children and not child_context.exception_handler:
|
|
@@ -2157,14 +2164,6 @@ class _RenderContext:
|
|
|
2157
2164
|
if el in context.element_to_widget:
|
|
2158
2165
|
del context.element_to_widget[el]
|
|
2159
2166
|
del context.elements[key]
|
|
2160
|
-
if isinstance(el.component, ComponentFunction):
|
|
2161
|
-
assert not child_context.elements, f"left over elements {child_context.elements}"
|
|
2162
|
-
assert not child_context.element_to_widget, f"left over element_to_widget {child_context.element_to_widget}"
|
|
2163
|
-
assert not child_context.widgets, f"left over widgets {child_context.widgets}"
|
|
2164
|
-
assert not child_context.children, f"left over children {child_context.children}"
|
|
2165
|
-
assert not child_context.owns, f"left over owns {child_context.owns}"
|
|
2166
|
-
# TODO: this is not the case when an exception occurs
|
|
2167
|
-
# assert not child_context.children_next, f"left over children {child_context.children_next}"
|
|
2168
2167
|
|
|
2169
2168
|
def _visit_children(self, el: Element, default_key: str, parent_key: str, f: Callable):
|
|
2170
2169
|
assert self.context is not None
|
|
@@ -2180,7 +2179,13 @@ class _RenderContext:
|
|
|
2180
2179
|
return f(value, key, parent_key)
|
|
2181
2180
|
elif isinstance(value, (list, tuple)):
|
|
2182
2181
|
was_tuple = isinstance(value, tuple)
|
|
2183
|
-
values = [
|
|
2182
|
+
values = []
|
|
2183
|
+
for index, v in enumerate(value):
|
|
2184
|
+
new_value = self._visit_children_values(v, f"{key}{index}/", parent_key, f)
|
|
2185
|
+
if isinstance(new_value, FragmentWidget):
|
|
2186
|
+
values.extend(new_value.children)
|
|
2187
|
+
else:
|
|
2188
|
+
values.append(new_value)
|
|
2184
2189
|
if was_tuple:
|
|
2185
2190
|
return tuple(values)
|
|
2186
2191
|
return values
|
|
@@ -2193,15 +2198,13 @@ class _RenderContext:
|
|
|
2193
2198
|
@overload
|
|
2194
2199
|
def render(
|
|
2195
2200
|
element: Element[T], container: None = None, children_trait="children", handle_error: bool = True, initial_state=None
|
|
2196
|
-
) -> Tuple[widgets.HBox, _RenderContext]:
|
|
2197
|
-
...
|
|
2201
|
+
) -> Tuple[widgets.HBox, _RenderContext]: ...
|
|
2198
2202
|
|
|
2199
2203
|
|
|
2200
2204
|
@overload
|
|
2201
2205
|
def render(
|
|
2202
2206
|
element: Element[T], container: None = None, children_trait="children", handle_error: bool = True, initial_state=None
|
|
2203
|
-
) -> Tuple[widgets.Widget, _RenderContext]:
|
|
2204
|
-
...
|
|
2207
|
+
) -> Tuple[widgets.Widget, _RenderContext]: ...
|
|
2205
2208
|
|
|
2206
2209
|
|
|
2207
2210
|
def render(element: Element[T], container: widgets.Widget = None, children_trait="children", handle_error: bool = True, initial_state=None):
|
|
@@ -2320,8 +2323,18 @@ def __getattr__(name):
|
|
|
2320
2323
|
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
2321
2324
|
|
|
2322
2325
|
|
|
2326
|
+
class FragmentWidget(widgets.VBox):
|
|
2327
|
+
def __init__(self, children, **kwargs):
|
|
2328
|
+
super().__init__(children=children, **kwargs)
|
|
2329
|
+
|
|
2330
|
+
|
|
2331
|
+
@component
|
|
2332
|
+
def Fragment(children: List[Element]):
|
|
2333
|
+
return FragmentWidget.element(children=children)
|
|
2334
|
+
|
|
2335
|
+
|
|
2323
2336
|
_last_interactive_vbox = None
|
|
2324
|
-
_default_container: Optional[Callable[..., Element]] =
|
|
2337
|
+
_default_container: Optional[Callable[..., Element]] = Fragment
|
|
2325
2338
|
# not a public api yet, used in solara for now only.
|
|
2326
2339
|
# lifecycle of context objects are linked to the lifecycle of the component
|
|
2327
2340
|
_component_context_manager_classes: List[Any] = []
|
|
@@ -378,7 +378,6 @@ def test_render_replace():
|
|
|
378
378
|
|
|
379
379
|
|
|
380
380
|
def test_render_conditional_child():
|
|
381
|
-
|
|
382
381
|
set_value = lambda x: None # noqa
|
|
383
382
|
|
|
384
383
|
@react.component
|
|
@@ -404,7 +403,6 @@ def test_render_conditional_child():
|
|
|
404
403
|
|
|
405
404
|
|
|
406
405
|
def test_render_conditional_replace_component_with_element():
|
|
407
|
-
|
|
408
406
|
set_value = lambda x: None # noqa
|
|
409
407
|
|
|
410
408
|
def Container():
|
|
@@ -1383,7 +1381,6 @@ def test_container_context_bqplot():
|
|
|
1383
1381
|
|
|
1384
1382
|
|
|
1385
1383
|
def test_get_widget(Container):
|
|
1386
|
-
|
|
1387
1384
|
button1 = None
|
|
1388
1385
|
button2 = None
|
|
1389
1386
|
|
|
@@ -1998,6 +1995,28 @@ def test_recover_exception_in_widget_update(Container1, Container2):
|
|
|
1998
1995
|
rc.close()
|
|
1999
1996
|
|
|
2000
1997
|
|
|
1998
|
+
def test_exception_in_child_no_run_effect():
|
|
1999
|
+
set_fail = None
|
|
2000
|
+
|
|
2001
|
+
mock = unittest.mock.Mock()
|
|
2002
|
+
|
|
2003
|
+
@react.component
|
|
2004
|
+
def Test():
|
|
2005
|
+
nonlocal set_fail
|
|
2006
|
+
children = v.Btn(children=[1])
|
|
2007
|
+
# we do not want to run this effect
|
|
2008
|
+
use_effect(mock, [])
|
|
2009
|
+
return children
|
|
2010
|
+
|
|
2011
|
+
box, rc = react.render(Test(), handle_error=True)
|
|
2012
|
+
assert not mock.called
|
|
2013
|
+
|
|
2014
|
+
assert not rc.find(ipyvuetify.Btn)
|
|
2015
|
+
assert "Traceback" in rc.find(ipywidgets.HTML).widget.value
|
|
2016
|
+
|
|
2017
|
+
rc.close()
|
|
2018
|
+
|
|
2019
|
+
|
|
2001
2020
|
def test_state_get():
|
|
2002
2021
|
set_value = None
|
|
2003
2022
|
|
|
@@ -2945,7 +2964,6 @@ def test_close_when_overridden():
|
|
|
2945
2964
|
|
|
2946
2965
|
|
|
2947
2966
|
def test_render_perf_child_only():
|
|
2948
|
-
|
|
2949
2967
|
render_child = unittest.mock.Mock()
|
|
2950
2968
|
render_main = unittest.mock.Mock()
|
|
2951
2969
|
set_text = lambda x: None # noqa
|
|
@@ -3142,3 +3160,47 @@ def test_memory_leak(component):
|
|
|
3142
3160
|
del rc
|
|
3143
3161
|
gc.collect()
|
|
3144
3162
|
assert weak_rc() is None
|
|
3163
|
+
|
|
3164
|
+
|
|
3165
|
+
def test_fragment():
|
|
3166
|
+
@reacton.component
|
|
3167
|
+
def Children():
|
|
3168
|
+
with reacton.Fragment():
|
|
3169
|
+
w.Button(description="1")
|
|
3170
|
+
w.Button(description="2")
|
|
3171
|
+
|
|
3172
|
+
@reacton.component
|
|
3173
|
+
def Test():
|
|
3174
|
+
with w.VBox():
|
|
3175
|
+
Children()
|
|
3176
|
+
|
|
3177
|
+
box, rc = react.render(Test(), handle_error=False)
|
|
3178
|
+
vbox = rc.find(widgets.VBox).widget
|
|
3179
|
+
assert len(vbox.children) == 2
|
|
3180
|
+
assert isinstance(vbox.children[0], widgets.Button)
|
|
3181
|
+
assert isinstance(vbox.children[1], widgets.Button)
|
|
3182
|
+
assert vbox.children[0].description == "1"
|
|
3183
|
+
assert vbox.children[1].description == "2"
|
|
3184
|
+
rc.close()
|
|
3185
|
+
|
|
3186
|
+
|
|
3187
|
+
def test_key_mutate_protection(Container):
|
|
3188
|
+
button = ButtonComponentFunction(description="Hi")
|
|
3189
|
+
set_state = lambda value: None # noqa
|
|
3190
|
+
|
|
3191
|
+
@react.component
|
|
3192
|
+
def Test():
|
|
3193
|
+
nonlocal set_state
|
|
3194
|
+
state, set_state = react.use_state(0)
|
|
3195
|
+
if state == 0:
|
|
3196
|
+
return Container(children=[button])
|
|
3197
|
+
else:
|
|
3198
|
+
return Container(children=[button.key("i_should_not_be_mutated")]).key("bla")
|
|
3199
|
+
|
|
3200
|
+
box, rc = react.render(Test(), handle_error=False)
|
|
3201
|
+
assert rc.find(widgets.Button).widget.description == "Hi"
|
|
3202
|
+
assert button._key is None
|
|
3203
|
+
with pytest.raises(RuntimeError, match="Element keys should not be mutated after rendering"):
|
|
3204
|
+
set_state(1)
|
|
3205
|
+
rc.render(w.HTML(value="recover").key("HTML"))
|
|
3206
|
+
rc.close()
|
|
@@ -5,7 +5,6 @@ from inspect import isclass
|
|
|
5
5
|
from textwrap import indent
|
|
6
6
|
from typing import Any, Dict, Generic, Type, TypeVar
|
|
7
7
|
|
|
8
|
-
import black
|
|
9
8
|
import bqplot
|
|
10
9
|
import ipywidgets
|
|
11
10
|
import ipywidgets as widgets # type: ignore
|
|
@@ -106,9 +105,28 @@ class CodeGen(Generic[W]):
|
|
|
106
105
|
def get_ignore_props(self, cls):
|
|
107
106
|
return self.ignore_props
|
|
108
107
|
|
|
108
|
+
# Replicated from https://gist.github.com/shner-elmo/b2639a4d1e04ceafaad120acfb31213c
|
|
109
|
+
def ruff_format(self, code: str) -> str:
|
|
110
|
+
import subprocess
|
|
111
|
+
from ruff.__main__ import find_ruff_bin
|
|
112
|
+
|
|
113
|
+
ruff_args = [
|
|
114
|
+
find_ruff_bin(),
|
|
115
|
+
"format",
|
|
116
|
+
"--stdin-filename",
|
|
117
|
+
"foo.py", # you can pass any random string, it wont use it...
|
|
118
|
+
# these two lines are optional, but this is how you can pass the config for ruff
|
|
119
|
+
"--line-length",
|
|
120
|
+
f"{MAX_LINE_LENGTH}",
|
|
121
|
+
]
|
|
122
|
+
proc = subprocess.run(ruff_args, input=code, text=True, capture_output=True)
|
|
123
|
+
proc.check_returncode() # raise an Exception if return code is not 0
|
|
124
|
+
return proc.stdout
|
|
125
|
+
|
|
109
126
|
def generate_component(self, cls: Type[widgets.Widget], blacken=True):
|
|
110
127
|
element_class_name = self.get_element_class(cls).__name__
|
|
111
128
|
ignore = self.get_ignore_props(cls)
|
|
129
|
+
|
|
112
130
|
traits = {key: value for key, value in cls.class_traits().items() if "output" not in value.metadata and not key.startswith("_") and key not in ignore}
|
|
113
131
|
|
|
114
132
|
def has_default(trait):
|
|
@@ -293,9 +311,8 @@ del _{{ method_name }}
|
|
|
293
311
|
)
|
|
294
312
|
|
|
295
313
|
if blacken:
|
|
296
|
-
mode = black.Mode(line_length=MAX_LINE_LENGTH)
|
|
297
314
|
try:
|
|
298
|
-
code =
|
|
315
|
+
code = self.ruff_format(code)
|
|
299
316
|
except Exception:
|
|
300
317
|
print("code:\n", code)
|
|
301
318
|
raise
|
|
@@ -325,10 +342,7 @@ del _{{ method_name }}
|
|
|
325
342
|
raise ValueError(f"Could not find new line after marker: {marker!r}")
|
|
326
343
|
code_total = current_code[: start + 1] + "\n" + code
|
|
327
344
|
if blacken:
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
mode = black.Mode(line_length=MAX_LINE_LENGTH)
|
|
331
|
-
code_total = black.format_file_contents(code_total, fast=False, mode=mode)
|
|
345
|
+
code_total = self.ruff_format(code_total)
|
|
332
346
|
only_valid = True
|
|
333
347
|
if only_valid:
|
|
334
348
|
try:
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
import ipywidgets as widgets
|
|
2
3
|
import traitlets
|
|
4
|
+
import pytest
|
|
3
5
|
|
|
4
6
|
from .generate import CodeGen
|
|
5
7
|
|
|
6
8
|
|
|
9
|
+
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Ruff does not support Python < 3.7")
|
|
7
10
|
def test_basic():
|
|
8
11
|
class MyTest(traitlets.HasTraits):
|
|
9
12
|
a = traitlets.traitlets.Int(1)
|
|
@@ -22,7 +25,6 @@ def _MyTest(
|
|
|
22
25
|
|
|
23
26
|
@implements(_MyTest)
|
|
24
27
|
def MyTest(**kwargs):
|
|
25
|
-
|
|
26
28
|
widget_cls = reacton.generate_test.MyTest
|
|
27
29
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
28
30
|
return Element(comp, kwargs=kwargs)
|
|
@@ -33,6 +35,7 @@ del _MyTest
|
|
|
33
35
|
assert code.strip() == code_expected.strip()
|
|
34
36
|
|
|
35
37
|
|
|
38
|
+
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Ruff does not support Python < 3.7")
|
|
36
39
|
def test_value():
|
|
37
40
|
class MyTest(traitlets.HasTraits):
|
|
38
41
|
a = traitlets.traitlets.Int(1)
|
|
@@ -51,7 +54,6 @@ def _MyTest(
|
|
|
51
54
|
|
|
52
55
|
@implements(_MyTest)
|
|
53
56
|
def MyTest(**kwargs):
|
|
54
|
-
|
|
55
57
|
widget_cls = reacton.generate_test.MyTest
|
|
56
58
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
57
59
|
return ValueElement("value", comp, kwargs=kwargs)
|
|
@@ -62,6 +64,7 @@ del _MyTest
|
|
|
62
64
|
assert code.strip() == code_expected.strip()
|
|
63
65
|
|
|
64
66
|
|
|
67
|
+
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Ruff does not support Python < 3.7")
|
|
65
68
|
def test_instance_non_widget():
|
|
66
69
|
class NonWidget:
|
|
67
70
|
def __init__(self, *args) -> None:
|
|
@@ -85,7 +88,6 @@ def _MyTest(
|
|
|
85
88
|
|
|
86
89
|
@implements(_MyTest)
|
|
87
90
|
def MyTest(**kwargs):
|
|
88
|
-
|
|
89
91
|
widget_cls = reacton.generate_test.MyTest
|
|
90
92
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
91
93
|
return Element(comp, kwargs=kwargs)
|
|
@@ -95,6 +97,7 @@ del _MyTest'''
|
|
|
95
97
|
assert code.strip() == code_expected.strip()
|
|
96
98
|
|
|
97
99
|
|
|
100
|
+
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Ruff does not support Python < 3.7")
|
|
98
101
|
def test_instance_widget():
|
|
99
102
|
class SomeWidget(widgets.Widget):
|
|
100
103
|
def __init__(self, *args) -> None:
|
|
@@ -116,7 +119,6 @@ def _MyTest(
|
|
|
116
119
|
|
|
117
120
|
@implements(_MyTest)
|
|
118
121
|
def MyTest(**kwargs):
|
|
119
|
-
|
|
120
122
|
widget_cls = reacton.generate_test.MyTest
|
|
121
123
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
122
124
|
return Element(comp, kwargs=kwargs)
|
|
@@ -11,7 +11,6 @@ from . import ipywidgets as w
|
|
|
11
11
|
from .utils import implements
|
|
12
12
|
|
|
13
13
|
if __name__ == "__main__":
|
|
14
|
-
|
|
15
14
|
from .generate import generate
|
|
16
15
|
|
|
17
16
|
generate(__file__, [ipycanvas])
|
|
@@ -176,7 +175,6 @@ def _Path2D(value: str = "", on_value: typing.Callable[[str], Any] = None) -> El
|
|
|
176
175
|
|
|
177
176
|
@implements(_Path2D)
|
|
178
177
|
def Path2D(**kwargs):
|
|
179
|
-
|
|
180
178
|
widget_cls = ipycanvas.canvas.Path2D
|
|
181
179
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
182
180
|
return Element(comp, kwargs=kwargs)
|
|
@@ -545,7 +545,6 @@ def _ButtonStyle(
|
|
|
545
545
|
|
|
546
546
|
@implements(_ButtonStyle)
|
|
547
547
|
def ButtonStyle(**kwargs):
|
|
548
|
-
|
|
549
548
|
widget_cls = ipywidgets.widgets.widget_button.ButtonStyle
|
|
550
549
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
551
550
|
return Element(comp, kwargs=kwargs)
|
|
@@ -746,7 +745,6 @@ def _CoreWidget() -> Element[ipywidgets.widgets.widget_core.CoreWidget]:
|
|
|
746
745
|
|
|
747
746
|
@implements(_CoreWidget)
|
|
748
747
|
def CoreWidget(**kwargs):
|
|
749
|
-
|
|
750
748
|
widget_cls = ipywidgets.widgets.widget_core.CoreWidget
|
|
751
749
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
752
750
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2016,7 +2014,6 @@ def _Layout(
|
|
|
2016
2014
|
|
|
2017
2015
|
@implements(_Layout)
|
|
2018
2016
|
def Layout(**kwargs):
|
|
2019
|
-
|
|
2020
2017
|
widget_cls = ipywidgets.widgets.widget_layout.Layout
|
|
2021
2018
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2022
2019
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2670,7 +2667,6 @@ def _SliderStyle(
|
|
|
2670
2667
|
|
|
2671
2668
|
@implements(_SliderStyle)
|
|
2672
2669
|
def SliderStyle(**kwargs):
|
|
2673
|
-
|
|
2674
2670
|
widget_cls = ipywidgets.widgets.widget_int.SliderStyle
|
|
2675
2671
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2676
2672
|
return Element(comp, kwargs=kwargs)
|
|
@@ -2686,7 +2682,6 @@ def _Style() -> Element[ipywidgets.widgets.widget_style.Style]:
|
|
|
2686
2682
|
|
|
2687
2683
|
@implements(_Style)
|
|
2688
2684
|
def Style(**kwargs):
|
|
2689
|
-
|
|
2690
2685
|
widget_cls = ipywidgets.widgets.widget_style.Style
|
|
2691
2686
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
2692
2687
|
return Element(comp, kwargs=kwargs)
|
|
@@ -3011,7 +3006,6 @@ def _ToggleButtonsStyle(
|
|
|
3011
3006
|
|
|
3012
3007
|
@implements(_ToggleButtonsStyle)
|
|
3013
3008
|
def ToggleButtonsStyle(**kwargs):
|
|
3014
|
-
|
|
3015
3009
|
widget_cls = ipywidgets.widgets.widget_selection.ToggleButtonsStyle
|
|
3016
3010
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
3017
3011
|
return Element(comp, kwargs=kwargs)
|
|
@@ -3210,7 +3204,6 @@ def _ValueWidget(value: Any = None, on_value: typing.Callable[[Any], Any] = None
|
|
|
3210
3204
|
|
|
3211
3205
|
@implements(_ValueWidget)
|
|
3212
3206
|
def ValueWidget(**kwargs):
|
|
3213
|
-
|
|
3214
3207
|
widget_cls = ipywidgets.widgets.valuewidget.ValueWidget
|
|
3215
3208
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
3216
3209
|
return ValueElement("value", comp, kwargs=kwargs)
|
|
@@ -3327,7 +3320,6 @@ def _DescriptionStyle(
|
|
|
3327
3320
|
|
|
3328
3321
|
@implements(_DescriptionStyle)
|
|
3329
3322
|
def DescriptionStyle(**kwargs):
|
|
3330
|
-
|
|
3331
3323
|
widget_cls = ipywidgets.widgets.widget_description.DescriptionStyle
|
|
3332
3324
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
3333
3325
|
return Element(comp, kwargs=kwargs)
|
|
@@ -3383,7 +3375,6 @@ def _ProgressStyle(
|
|
|
3383
3375
|
|
|
3384
3376
|
@implements(_ProgressStyle)
|
|
3385
3377
|
def ProgressStyle(**kwargs):
|
|
3386
|
-
|
|
3387
3378
|
widget_cls = ipywidgets.widgets.widget_int.ProgressStyle
|
|
3388
3379
|
comp = reacton.core.ComponentWidget(widget=widget_cls)
|
|
3389
3380
|
return Element(comp, kwargs=kwargs)
|
|
@@ -145,7 +145,6 @@ def test_isinstance_lazy():
|
|
|
145
145
|
assert isinstance_lazy(1, int)
|
|
146
146
|
assert isinstance_lazy(1, (int, "does.not.exist"))
|
|
147
147
|
assert not isinstance_lazy(1, "does.not.exist")
|
|
148
|
-
import pandas
|
|
149
148
|
|
|
150
149
|
sys.modules.pop("pandas", None)
|
|
151
150
|
assert not isinstance_lazy(1, "pandas.DataFrame")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "1.8.3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|