Forráskód Böngészése

Merge remote-tracking branch 'origin/plotly'

Rodja Trappe 2 éve
szülő
commit
decee11561

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 7 - 0
nicegui/elements/lib/plotly.min.js


+ 4 - 3
nicegui/elements/line_plot.py

@@ -1,14 +1,15 @@
 from typing import List
 
-from .plot import Plot
+from .pyplot import Pyplot
 
 
-class LinePlot(Plot):
+class LinePlot(Pyplot):
 
     def __init__(self, *, n: int = 1, limit: int = 100, update_every: int = 1, close: bool = True, **kwargs) -> None:
         """Line Plot
 
-        Create a line plot. The `push` method provides live updating when utilized in combination with `ui.timer`.
+        Create a line plot using pyplot.
+        The `push` method provides live updating when utilized in combination with `ui.timer`.
 
         :param n: number of lines
         :param limit: maximum number of datapoints per line (new points will displace the oldest)

+ 19 - 0
nicegui/elements/plotly.js

@@ -0,0 +1,19 @@
+export default {
+  template: `<div></div>`,
+  mounted() {
+    setTimeout(() => {
+      import(window.path_prefix + this.lib).then(() => {
+        Plotly.newPlot(this.$el.id, this.options.data, this.options.layout);
+      });
+    }, 0); // NOTE: wait for window.path_prefix to be set in app.mounted()
+  },
+  methods: {
+    update(options) {
+      Plotly.newPlot(this.$el.id, options.data, options.layout);
+    },
+  },
+  props: {
+    options: Object,
+    lib: String,
+  },
+};

+ 29 - 0
nicegui/elements/plotly.py

@@ -0,0 +1,29 @@
+import json
+
+import plotly.graph_objects as go
+
+from ..dependencies import js_dependencies, register_component
+from ..element import Element
+
+register_component('plotly', __file__, 'plotly.js', [], ['lib/plotly.min.js'])
+
+
+class Plotly(Element):
+
+    def __init__(self, figure: go.Figure) -> None:
+        """Plotly Element
+
+        Renders a plotly figure onto the page.
+
+        See `plotly documentation <https://plotly.com/python/>`_ for more information.
+
+        :param figure: the plotly figure to be displayed
+        """
+        super().__init__('plotly')
+        self.figure = figure
+        self._props['lib'] = [d.import_path for d in js_dependencies.values() if d.path.name == 'plotly.min.js'][0]
+        self.update()
+
+    def update(self) -> None:
+        self._props['options'] = json.loads(self.figure.to_json())
+        self.run_method('update', self._props['options'])

+ 2 - 2
nicegui/elements/plot.py → nicegui/elements/pyplot.py

@@ -7,10 +7,10 @@ from .. import background_tasks, globals
 from ..element import Element
 
 
-class Plot(Element):
+class Pyplot(Element):
 
     def __init__(self, *, close: bool = True, **kwargs) -> None:
-        """Plot Context
+        """Pyplot Context
 
         Create a context to configure a `Matplotlib <https://matplotlib.org/>`_ plot.
 

+ 3 - 1
nicegui/ui.py

@@ -32,6 +32,7 @@ from .elements.menu import Menu as menu
 from .elements.menu import MenuItem as menu_item
 from .elements.mermaid import Mermaid as mermaid
 from .elements.number import Number as number
+from .elements.plotly import Plotly as plotly
 from .elements.progress import CircularProgress as circular_progress
 from .elements.progress import LinearProgress as linear_progress
 from .elements.radio import Radio as radio
@@ -65,4 +66,5 @@ from .run_with import run_with
 
 if os.environ.get('MATPLOTLIB', 'true').lower() == 'true':
     from .elements.line_plot import LinePlot as line_plot
-    from .elements.plot import Plot as plot
+    from .elements.pyplot import Pyplot as plot  # NOTE: deprecated
+    from .elements.pyplot import Pyplot as pyplot

+ 24 - 2
poetry.lock

@@ -1126,6 +1126,13 @@ files = [
     {file = "Pillow-9.4.0-1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b8c2f6eb0df979ee99433d8b3f6d193d9590f735cf12274c108bd954e30ca858"},
     {file = "Pillow-9.4.0-1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b70756ec9417c34e097f987b4d8c510975216ad26ba6e57ccb53bc758f490dab"},
     {file = "Pillow-9.4.0-1-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:43521ce2c4b865d385e78579a082b6ad1166ebed2b1a2293c3be1d68dd7ca3b9"},
+    {file = "Pillow-9.4.0-2-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:9d9a62576b68cd90f7075876f4e8444487db5eeea0e4df3ba298ee38a8d067b0"},
+    {file = "Pillow-9.4.0-2-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:87708d78a14d56a990fbf4f9cb350b7d89ee8988705e58e39bdf4d82c149210f"},
+    {file = "Pillow-9.4.0-2-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:8a2b5874d17e72dfb80d917213abd55d7e1ed2479f38f001f264f7ce7bae757c"},
+    {file = "Pillow-9.4.0-2-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:83125753a60cfc8c412de5896d10a0a405e0bd88d0470ad82e0869ddf0cb3848"},
+    {file = "Pillow-9.4.0-2-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9e5f94742033898bfe84c93c831a6f552bb629448d4072dd312306bab3bd96f1"},
+    {file = "Pillow-9.4.0-2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:013016af6b3a12a2f40b704677f8b51f72cb007dac785a9933d5c86a72a7fe33"},
+    {file = "Pillow-9.4.0-2-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:99d92d148dd03fd19d16175b6d355cc1b01faf80dae93c6c3eb4163709edc0a9"},
     {file = "Pillow-9.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:2968c58feca624bb6c8502f9564dd187d0e1389964898f5e9e1fbc8533169157"},
     {file = "Pillow-9.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c5c1362c14aee73f50143d74389b2c158707b4abce2cb055b7ad37ce60738d47"},
     {file = "Pillow-9.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd752c5ff1b4a870b7661234694f24b1d2b9076b8bf337321a814c612665f343"},
@@ -1195,6 +1202,21 @@ files = [
 docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-issues (>=3.0.1)", "sphinx-removed-in", "sphinxext-opengraph"]
 tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
 
+[[package]]
+name = "plotly"
+version = "5.13.0"
+description = "An open-source, interactive data visualization library for Python"
+category = "main"
+optional = false
+python-versions = ">=3.6"
+files = [
+    {file = "plotly-5.13.0-py2.py3-none-any.whl", hash = "sha256:4ac5db72176ce144f1fcde8d1ef7bdbccf5bb7a53e3d366b16fcd7c85319fdfd"},
+    {file = "plotly-5.13.0.tar.gz", hash = "sha256:81a3aae4021d5ab91790fc71c3433791f41bfc71586e857f7777f429a955039a"},
+]
+
+[package.dependencies]
+tenacity = ">=6.2.0"
+
 [[package]]
 name = "pluggy"
 version = "1.0.0"
@@ -1724,7 +1746,7 @@ full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyam
 name = "tenacity"
 version = "6.3.1"
 description = "Retry code until it succeeds"
-category = "dev"
+category = "main"
 optional = false
 python-versions = "*"
 files = [
@@ -2052,4 +2074,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.7"
-content-hash = "d295b6331955c188539cab3df96edbc39a6c5329b5ca37d73733378473367126"
+content-hash = "dd6d3d193a7b258f8630f1b5fda203037f9867aae4a89da27deb8f44026f2086"

+ 1 - 0
pyproject.toml

@@ -25,6 +25,7 @@ vbuild = "^0.8.1"
 watchfiles = "^0.18.1"
 jinja2 = "^3.1.2"
 python-multipart = "^0.0.5"
+plotly = "^5.13.0"
 
 [tool.poetry.group.dev.dependencies]
 icecream = "^2.1.0"

+ 23 - 0
tests/test_plotly.py

@@ -0,0 +1,23 @@
+import plotly.graph_objects as go
+
+from nicegui import ui
+
+from .screen import Screen
+
+
+def test_plotly(screen: Screen):
+    fig = go.Figure(go.Scatter(x=[1, 2, 3], y=[1, 2, 3], name='Trace 1'))
+    fig.update_layout(title='Test Figure')
+    plot = ui.plotly(fig)
+
+    ui.button('Add trace', on_click=lambda: (
+        fig.add_trace(go.Scatter(x=[0, 1, 2], y=[2, 1, 0], name='Trace 2')),
+        plot.update()
+    ))
+
+    screen.open('/')
+    screen.should_contain('Test Figure')
+
+    screen.click('Add trace')
+    screen.should_contain('Trace 1')
+    screen.should_contain('Trace 2')

+ 11 - 3
website/reference.py

@@ -289,12 +289,12 @@ To overlay an SVG, make the `viewBox` exactly the size of the image and provide
 
         ui.button('Update', on_click=update)
 
-    @example(ui.plot, menu)
+    @example(ui.pyplot, menu)
     def plot_example():
         import numpy as np
         from matplotlib import pyplot as plt
 
-        with ui.plot(figsize=(3, 2)):
+        with ui.pyplot(figsize=(3, 2)):
             x = np.linspace(0.0, 5.0)
             y = np.cos(2 * np.pi * x) * np.exp(-x)
             plt.plot(x, y, '-')
@@ -328,6 +328,14 @@ To overlay an SVG, make the `viewBox` exactly the size of the image and provide
                 ui.timer(10.0, turn_off, once=True)
         line_checkbox.on('update:model-value', handle_change)
 
+    @example(ui.plotly, menu)
+    def plotly_example():
+        import plotly.express as px
+
+        fig = px.scatter(x=[1, 2, 3, 4], y=[1, 2, 3, 2.5])
+        fig.update_layout(width=280, height=210, margin=dict(l=0, r=0, t=0, b=0))
+        ui.plotly(fig)
+
     @example(ui.linear_progress, menu)
     def linear_progress_example():
         slider = ui.slider(min=0, max=1, step=0.01, value=0.5)
@@ -854,7 +862,7 @@ When NiceGUI is shut down or restarted, all tasks still in execution will be aut
 
 You can set the following environment variables to configure NiceGUI:
 
-- `MATPLOTLIB` (default: true) can be set to `false` to avoid the potentially costly import of Matplotlib. This will make `ui.plot` and `ui.line_plot` unavailable.
+- `MATPLOTLIB` (default: true) can be set to `false` to avoid the potentially costly import of Matplotlib. This will make `ui.pyplot` and `ui.line_plot` unavailable.
 - `MARKDOWN_CONTENT_CACHE_SIZE` (default: 1000): The maximum number of Markdown content snippets that are cached in memory.
 ''', menu)
     def env_var_example():

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott