Explorar o código

remove numpy dependency where possible

Falko Schindler hai 1 ano
pai
achega
3b81379878

+ 0 - 1
examples/simpy/async_realtime_environment.py

@@ -2,7 +2,6 @@ import asyncio
 from time import monotonic
 from time import monotonic
 from typing import Any, Optional, Union
 from typing import Any, Optional, Union
 
 
-from numpy import Infinity
 from simpy.core import EmptySchedule, Environment, Infinity, SimTime, StopSimulation
 from simpy.core import EmptySchedule, Environment, Infinity, SimTime, StopSimulation
 from simpy.events import URGENT, Event
 from simpy.events import URGENT, Event
 from simpy.rt import RealtimeEnvironment
 from simpy.rt import RealtimeEnvironment

+ 1 - 1
nicegui/elements/plotly.py

@@ -43,7 +43,7 @@ class Plotly(Element, component='plotly.vue', libraries=['lib/plotly/plotly.min.
     def _get_figure_json(self) -> Dict:
     def _get_figure_json(self) -> Dict:
         if isinstance(self.figure, go.Figure):
         if isinstance(self.figure, go.Figure):
             # convert go.Figure to dict object which is directly JSON serializable
             # convert go.Figure to dict object which is directly JSON serializable
-            # orjson supports numpy array serialization
+            # orjson supports NumPy array serialization
             return self.figure.to_plotly_json()
             return self.figure.to_plotly_json()
 
 
         if isinstance(self.figure, dict):
         if isinstance(self.figure, dict):

+ 3 - 4
nicegui/elements/scene_objects.py

@@ -1,7 +1,6 @@
+import math
 from typing import List, Optional
 from typing import List, Optional
 
 
-import numpy as np
-
 from .scene_object3d import Object3D
 from .scene_object3d import Object3D
 
 
 
 
@@ -60,7 +59,7 @@ class Ring(Object3D):
                  theta_segments: int = 8,
                  theta_segments: int = 8,
                  phi_segments: int = 1,
                  phi_segments: int = 1,
                  theta_start: float = 0,
                  theta_start: float = 0,
-                 theta_length: float = 2 * np.pi,
+                 theta_length: float = 2 * math.pi,
                  wireframe: bool = False,
                  wireframe: bool = False,
                  ) -> None:
                  ) -> None:
         super().__init__('ring',
         super().__init__('ring',
@@ -164,7 +163,7 @@ class SpotLight(Object3D):
                  color: str = '#ffffff',
                  color: str = '#ffffff',
                  intensity: float = 1.0,
                  intensity: float = 1.0,
                  distance: float = 0.0,
                  distance: float = 0.0,
-                 angle: float = np.pi / 3,
+                 angle: float = math.pi / 3,
                  penumbra: float = 0.0,
                  penumbra: float = 0.0,
                  decay: float = 1.0,
                  decay: float = 1.0,
                  ) -> None:
                  ) -> None:

+ 2 - 2
nicegui/globals.py

@@ -4,7 +4,7 @@ import logging
 from contextlib import contextmanager
 from contextlib import contextmanager
 from enum import Enum
 from enum import Enum
 from pathlib import Path
 from pathlib import Path
-from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, Iterator, List, Optional, Union
+from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, Iterator, List, Optional, Set, Union
 
 
 from socketio import AsyncServer
 from socketio import AsyncServer
 from uvicorn import Server
 from uvicorn import Server
@@ -33,7 +33,7 @@ loop: Optional[asyncio.AbstractEventLoop] = None
 log: logging.Logger = logging.getLogger('nicegui')
 log: logging.Logger = logging.getLogger('nicegui')
 state: State = State.STOPPED
 state: State = State.STOPPED
 ui_run_has_been_called: bool = False
 ui_run_has_been_called: bool = False
-optional_features: List[str] = []
+optional_features: Set[str] = set()
 
 
 reload: bool
 reload: bool
 title: str
 title: str

+ 10 - 7
nicegui/json/builtin_wrapper.py

@@ -2,15 +2,18 @@ import json
 from datetime import date, datetime
 from datetime import date, datetime
 from typing import Any, Optional, Tuple
 from typing import Any, Optional, Tuple
 
 
-import numpy as np
 from fastapi import Response
 from fastapi import Response
 
 
+try:
+    import numpy as np
+except ImportError:
+    np = None
+
 
 
 def dumps(obj: Any, sort_keys: bool = False, separators: Optional[Tuple[str, str]] = None):
 def dumps(obj: Any, sort_keys: bool = False, separators: Optional[Tuple[str, str]] = None):
     """Serializes a Python object to a JSON-encoded string.
     """Serializes a Python object to a JSON-encoded string.
 
 
-    This implementation uses Python's default json module, but extends it
-    in order to support numpy arrays.
+    This implementation uses Python's default json module, but extends it in order to support NumPy arrays.
     """
     """
     if separators is None:
     if separators is None:
         separators = (',', ':')
         separators = (',', ':')
@@ -41,14 +44,14 @@ class NiceGUIJSONResponse(Response):
 
 
 
 
 class NumpyJsonEncoder(json.JSONEncoder):
 class NumpyJsonEncoder(json.JSONEncoder):
-    """Special json encoder that supports numpy arrays and date/datetime objects."""
+    """Special json encoder that supports NumPy arrays and date/datetime objects."""
 
 
     def default(self, obj):
     def default(self, obj):
-        if isinstance(obj, np.integer):
+        if np and isinstance(obj, np.integer):
             return int(obj)
             return int(obj)
-        if isinstance(obj, np.floating):
+        if np and isinstance(obj, np.floating):
             return float(obj)
             return float(obj)
-        if isinstance(obj, np.ndarray):
+        if np and isinstance(obj, np.ndarray):
             return obj.tolist()
             return obj.tolist()
         if isinstance(obj, (datetime, date)):
         if isinstance(obj, (datetime, date)):
             return obj.isoformat()
             return obj.isoformat()

+ 8 - 5
nicegui/json/orjson_wrapper.py

@@ -1,18 +1,21 @@
 from decimal import Decimal
 from decimal import Decimal
 from typing import Any, Optional, Tuple
 from typing import Any, Optional, Tuple
 
 
-import numpy as np
 import orjson
 import orjson
 from fastapi import Response
 from fastapi import Response
 
 
+try:
+    import numpy as np
+except ImportError:
+    np = None
+
 ORJSON_OPTS = orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_NON_STR_KEYS
 ORJSON_OPTS = orjson.OPT_SERIALIZE_NUMPY | orjson.OPT_NON_STR_KEYS
 
 
 
 
 def dumps(obj: Any, sort_keys: bool = False, separators: Optional[Tuple[str, str]] = None):
 def dumps(obj: Any, sort_keys: bool = False, separators: Optional[Tuple[str, str]] = None):
     """Serializes a Python object to a JSON-encoded string.
     """Serializes a Python object to a JSON-encoded string.
 
 
-    By default, this function supports serializing numpy arrays,
-    which Python's json module does not.
+    By default, this function supports serializing NumPy arrays, which Python's json module does not.
 
 
     Uses package `orjson` internally.
     Uses package `orjson` internally.
     """
     """
@@ -40,8 +43,8 @@ def loads(value: str) -> Any:
 
 
 
 
 def _orjson_converter(obj):
 def _orjson_converter(obj):
-    """Custom serializer/converter, e.g. for numpy object arrays."""
-    if isinstance(obj, np.ndarray) and obj.dtype == np.object_:
+    """Custom serializer/converter, e.g. for NumPy object arrays."""
+    if np and isinstance(obj, np.ndarray) and obj.dtype == np.object_:
         return obj.tolist()
         return obj.tolist()
     if isinstance(obj, Decimal):
     if isinstance(obj, Decimal):
         return float(obj)
         return float(obj)

+ 3 - 3
nicegui/ui.py

@@ -88,6 +88,7 @@ __all__ = [
     'run_with',
     'run_with',
 ]
 ]
 
 
+from . import globals
 from .deprecation import deprecated
 from .deprecation import deprecated
 from .element import Element as element
 from .element import Element as element
 from .elements.aggrid import AgGrid as aggrid
 from .elements.aggrid import AgGrid as aggrid
@@ -173,10 +174,9 @@ from .page_layout import RightDrawer as right_drawer
 from .run import run
 from .run import run
 from .run_with import run_with
 from .run_with import run_with
 
 
-from .globals import optional_features
 try:
 try:
     from .elements.plotly import Plotly as plotly
     from .elements.plotly import Plotly as plotly
-    optional_features.append('plotly')
+    globals.optional_features.add('plotly')
 except ImportError:
 except ImportError:
     def plotly(*args, **kwargs):
     def plotly(*args, **kwargs):
         raise ImportError('Plotly is not installed. Please run "pip install plotly".')
         raise ImportError('Plotly is not installed. Please run "pip install plotly".')
@@ -187,7 +187,7 @@ if os.environ.get('MATPLOTLIB', 'true').lower() == 'true':
         from .elements.line_plot import LinePlot as line_plot
         from .elements.line_plot import LinePlot as line_plot
         from .elements.pyplot import Pyplot as pyplot
         from .elements.pyplot import Pyplot as pyplot
         plot = deprecated(pyplot, 'ui.plot', 'ui.pyplot', 317)
         plot = deprecated(pyplot, 'ui.plot', 'ui.pyplot', 317)
-        optional_features.append('matplotlib')
+        globals.optional_features.add('matplotlib')
     except ImportError:
     except ImportError:
         def line_plot(*args, **kwargs):
         def line_plot(*args, **kwargs):
             raise ImportError('Matplotlib is not installed. Please run "pip install matplotlib".')
             raise ImportError('Matplotlib is not installed. Please run "pip install matplotlib".')

+ 3 - 3
nicegui/welcome.py

@@ -2,17 +2,17 @@ import os
 import socket
 import socket
 from typing import List
 from typing import List
 
 
-from .globals import optional_features
+from . import globals
 
 
 try:
 try:
     import netifaces
     import netifaces
-    optional_features.append('netifaces')
+    globals.optional_features.add('netifaces')
 except ImportError:
 except ImportError:
     pass
     pass
 
 
 
 
 def get_all_ips() -> List[str]:
 def get_all_ips() -> List[str]:
-    if not 'netifaces' in optional_features:
+    if 'netifaces' not in globals.optional_features:
         return [info[4][0] for info in socket.getaddrinfo(socket.gethostname(), None) if len(info[4]) == 2]
         return [info[4][0] for info in socket.getaddrinfo(socket.gethostname(), None) if len(info[4]) == 2]
     ips = []
     ips = []
     for interface in netifaces.interfaces():
     for interface in netifaces.interfaces():

+ 1 - 0
pyproject.toml

@@ -52,6 +52,7 @@ pandas = [
 ]
 ]
 secure = "^0.3.0"
 secure = "^0.3.0"
 webdriver-manager = "^3.8.6"
 webdriver-manager = "^3.8.6"
+numpy = "^1.25.0"
 
 
 [build-system]
 [build-system]
 requires = [
 requires = [

+ 1 - 1
tests/test_plotly.py

@@ -12,7 +12,7 @@ def test_plotly(screen: Screen):
     plot = ui.plotly(fig)
     plot = ui.plotly(fig)
 
 
     ui.button('Add trace', on_click=lambda: (
     ui.button('Add trace', on_click=lambda: (
-        # test numpy array support for value arrays
+        # test NumPy array support for value arrays
         fig.add_trace(go.Scatter(x=np.array([0, 1, 2]), y=np.array([2, 1, 0]), name='Trace 2')),
         fig.add_trace(go.Scatter(x=np.array([0, 1, 2]), y=np.array([2, 1, 0]), name='Trace 2')),
         plot.update()
         plot.update()
     ))
     ))

+ 2 - 2
website/more_documentation/chart_documentation.py

@@ -2,7 +2,7 @@ from nicegui import ui
 
 
 
 
 def main_demo() -> None:
 def main_demo() -> None:
-    from numpy.random import random
+    from random import random
 
 
     chart = ui.chart({
     chart = ui.chart({
         'title': False,
         'title': False,
@@ -15,7 +15,7 @@ def main_demo() -> None:
     }).classes('w-full h-64')
     }).classes('w-full h-64')
 
 
     def update():
     def update():
-        chart.options['series'][0]['data'][:] = random(2)
+        chart.options['series'][0]['data'][0] = random()
         chart.update()
         chart.update()
 
 
     ui.button('Update', on_click=update)
     ui.button('Update', on_click=update)

+ 3 - 4
website/more_documentation/line_plot_documentation.py

@@ -2,18 +2,17 @@ from nicegui import events, ui
 
 
 
 
 def main_demo() -> None:
 def main_demo() -> None:
+    import math
     from datetime import datetime
     from datetime import datetime
 
 
-    import numpy as np
-
     line_plot = ui.line_plot(n=2, limit=20, figsize=(3, 2), update_every=5) \
     line_plot = ui.line_plot(n=2, limit=20, figsize=(3, 2), update_every=5) \
         .with_legend(['sin', 'cos'], loc='upper center', ncol=2)
         .with_legend(['sin', 'cos'], loc='upper center', ncol=2)
 
 
     def update_line_plot() -> None:
     def update_line_plot() -> None:
         now = datetime.now()
         now = datetime.now()
         x = now.timestamp()
         x = now.timestamp()
-        y1 = np.sin(x)
-        y2 = np.cos(x)
+        y1 = math.sin(x)
+        y2 = math.cos(x)
         line_plot.push([now], [[y1], [y2]])
         line_plot.push([now], [[y1], [y2]])
 
 
     line_updates = ui.timer(0.1, update_line_plot, active=False)
     line_updates = ui.timer(0.1, update_line_plot, active=False)

+ 4 - 5
website/more_documentation/plotly_documentation.py

@@ -1,5 +1,3 @@
-import numpy as np
-
 from nicegui import ui
 from nicegui import ui
 
 
 from ..documentation_tools import text_demo
 from ..documentation_tools import text_demo
@@ -34,7 +32,7 @@ def more() -> None:
                     'type': 'scatter',
                     'type': 'scatter',
                     'name': 'Trace 2',
                     'name': 'Trace 2',
                     'x': [1, 2, 3, 4],
                     'x': [1, 2, 3, 4],
-                    'y': np.array([1.4, 1.8, 3.8, 3.2]),
+                    'y': [1.4, 1.8, 3.8, 3.2],
                     'line': {'dash': 'dot', 'width': 3},
                     'line': {'dash': 'dot', 'width': 3},
                 },
                 },
             ],
             ],
@@ -53,7 +51,8 @@ def more() -> None:
         To send the new plot to the browser, make sure to explicitly call `plot.update()` or `ui.update(plot)`.
         To send the new plot to the browser, make sure to explicitly call `plot.update()` or `ui.update(plot)`.
     ''')
     ''')
     def plot_updates():
     def plot_updates():
-        import numpy as np
+        from random import random
+
         import plotly.graph_objects as go
         import plotly.graph_objects as go
 
 
         fig = go.Figure()
         fig = go.Figure()
@@ -61,7 +60,7 @@ def more() -> None:
         plot = ui.plotly(fig).classes('w-full h-40')
         plot = ui.plotly(fig).classes('w-full h-40')
 
 
         def add_trace():
         def add_trace():
-            fig.add_trace(go.Scatter(x=np.arange(10), y=np.random.randn(10)))
+            fig.add_trace(go.Scatter(x=[1, 2, 3], y=[random(), random(), random()]))
             plot.update()
             plot.update()
 
 
         ui.button('Add trace', on_click=add_trace)
         ui.button('Add trace', on_click=add_trace)