pfund-plot 0.0.3__tar.gz → 0.0.5__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.
Files changed (57) hide show
  1. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/PKG-INFO +1 -1
  2. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/pyproject.toml +1 -1
  3. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/__init__.py +8 -0
  4. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/cli/commands/gallery/gallery_marimo.py +2 -2
  5. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/layout/tabs/panel.py +12 -1
  6. pfund_plot-0.0.5/src/pfund_plot/plots/panel.py +45 -0
  7. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/plot.py +16 -8
  8. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/utils/__init__.py +10 -0
  9. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/README.md +0 -0
  10. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/__main__.py +0 -0
  11. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/cli/__init__.py +0 -0
  12. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/cli/commands/gallery/__init__.py +0 -0
  13. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/cli/commands/serve.py +0 -0
  14. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/cli/main.py +0 -0
  15. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/config.py +0 -0
  16. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/enums/__init__.py +0 -0
  17. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/enums/dataframe_backend.py +0 -0
  18. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/enums/display_mode.py +0 -0
  19. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/enums/panel_design.py +0 -0
  20. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/enums/panel_theme.py +0 -0
  21. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/enums/plotting_backend.py +0 -0
  22. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/js_tap/components/candlestick.js +0 -0
  23. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/mixins/streaming_market_feed_mixin.py +0 -0
  24. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/altair.py +0 -0
  25. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/area/__init__.py +0 -0
  26. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/area/bokeh.py +0 -0
  27. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/bar/__init__.py +0 -0
  28. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/bar/bokeh.py +0 -0
  29. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/bokeh.py +0 -0
  30. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/candlestick/__init__.py +0 -0
  31. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/candlestick/bokeh.py +0 -0
  32. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/candlestick/svelte.py +0 -0
  33. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/holoviews.py +0 -0
  34. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/label/__init__.py +0 -0
  35. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/label/bokeh.py +0 -0
  36. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/layout/__init__.py +0 -0
  37. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/layout/layout.py +0 -0
  38. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/layout/panel.py +0 -0
  39. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/layout/tabs/__init__.py +0 -0
  40. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/lazy.py +0 -0
  41. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/line/__init__.py +0 -0
  42. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/line/bokeh.py +0 -0
  43. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/matplotlib.py +0 -0
  44. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/plotly.py +0 -0
  45. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/scatter/__init__.py +0 -0
  46. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/scatter/bokeh.py +0 -0
  47. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/scatter/marker.py +0 -0
  48. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/plots/ta.py +0 -0
  49. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/renderers/base.py +0 -0
  50. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/renderers/browser.py +0 -0
  51. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/renderers/desktop.py +0 -0
  52. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/renderers/notebook.py +0 -0
  53. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/typing.py +0 -0
  54. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/utils/bokeh.py +0 -0
  55. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/widgets/base.py +0 -0
  56. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/widgets/datetime_widget.py +0 -0
  57. {pfund_plot-0.0.3 → pfund_plot-0.0.5}/src/pfund_plot/widgets/ticker_widget.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pfund-plot
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: A library for financial data visualization
5
5
  Keywords: financial data,plotting,dashboards,charts,data visualization,graphs,plots
6
6
  Author: Stephen Yau
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pfund-plot"
3
- version = "0.0.3"
3
+ version = "0.0.5"
4
4
  description = "A library for financial data visualization"
5
5
  license = "Apache-2.0"
6
6
  authors = [
@@ -51,6 +51,9 @@ if TYPE_CHECKING:
51
51
  from pfund_plot.plots.matplotlib import (
52
52
  Matplotlib as mpl,
53
53
  )
54
+ from pfund_plot.plots.panel import (
55
+ Panel as panel,
56
+ )
54
57
  from pfund_plot.plots.plotly import (
55
58
  Plotly as plotly,
56
59
  )
@@ -93,6 +96,10 @@ def __getattr__(name: str):
93
96
  from pfund_plot.plots.plotly import Plotly
94
97
 
95
98
  return Plotly
99
+ elif name == "panel":
100
+ from pfund_plot.plots.panel import Panel
101
+
102
+ return Panel
96
103
  elif name in ("candlestick", "ohlc", "kline"):
97
104
  from pfund_plot.plots.candlestick import Candlestick
98
105
 
@@ -167,6 +174,7 @@ __all__ = (
167
174
  "matplotlib",
168
175
  "mpl",
169
176
  "ohlc",
177
+ "panel",
170
178
  "plotly",
171
179
  "scatter",
172
180
  "tabs",
@@ -5,7 +5,7 @@ import marimo
5
5
  __generated_with = "0.23.9"
6
6
  app = marimo.App(width="columns")
7
7
 
8
- with app.setup:
8
+ with app.setup(hide_code=True):
9
9
  from threading import Thread
10
10
 
11
11
  import altair as alt
@@ -72,7 +72,7 @@ with app.setup:
72
72
  )
73
73
 
74
74
 
75
- @app.cell
75
+ @app.cell(hide_code=True)
76
76
  def _():
77
77
  mo.md("""
78
78
  # Gallery
@@ -41,8 +41,19 @@ def plot(
41
41
  control: dict[str, Any],
42
42
  **kwargs: Any,
43
43
  ) -> Tabs:
44
+ # In the marimo + svelte combo the plot's component is a mo.vstack (see
45
+ # Candlestick._create_component), which carries no name, so Panel assigns a
46
+ # default tab label like "Column01805". Panel's Tabs accepts a (name, object)
47
+ # tuple to label a tab explicitly, so pass the plot's name in that case.
48
+ # Every other component is a pn.Column that already carries its own name.
49
+ items = [
50
+ (plot.name, plot.component)
51
+ if plot._plot._is_using_marimo_svelte_combo()
52
+ else plot.component
53
+ for plot in plots
54
+ ]
44
55
  return Tabs(
45
- *[plot.component for plot in plots],
56
+ *items,
46
57
  height=style["height"],
47
58
  width=style["width"],
48
59
  dynamic=control["dynamic"],
@@ -0,0 +1,45 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar, Literal
4
+
5
+ if TYPE_CHECKING:
6
+ from panel.viewable import Viewable
7
+
8
+ import panel as pn
9
+
10
+ from pfund_plot.enums import PlottingBackend
11
+ from pfund_plot.plots.plot import BasePlot
12
+
13
+
14
+ class Panel(BasePlot):
15
+ """Wraps a pre-built Panel ``Viewable`` so it can participate in layouts.
16
+
17
+ Combining plots with ``+`` or ``|`` produces a ``LazyRow``/``LazyColumn``
18
+ (raw Panel components), not a ``LazyPlot``. This adapter lets such a
19
+ component be dropped into ``plt.tabs`` / ``plt.layout`` like any other plot.
20
+ """
21
+
22
+ SUPPORTED_BACKENDS: ClassVar[list[Literal[PlottingBackend.panel]]] = [
23
+ PlottingBackend.panel
24
+ ]
25
+ REQUIRED_DATA: ClassVar[bool] = False
26
+
27
+ def __init__(self, viewable: Viewable, name: str | None = None):
28
+ super().__init__(data=None, name=name)
29
+ self._viewable: Viewable = viewable
30
+
31
+ # the viewable is already fully built — no plot/pane construction needed
32
+ def _create_plot(self) -> None:
33
+ pass
34
+
35
+ def _create_pane(self) -> None:
36
+ pass
37
+
38
+ def _create_component(self) -> None:
39
+ # The viewable is already a finished component (no plot/pane layer here),
40
+ # but Panel makes `name` a constant param — it can't be renamed after
41
+ # construction, and the pre-built viewable keeps Panel's auto name like
42
+ # "LazyRow03407". So wrap it in a named pn.Column (the only way to attach a
43
+ # name); that name is what plt.tabs shows as the tab label. With no name=
44
+ # passed, self.name falls back to the class name "panel".
45
+ self._component = pn.Column(self._viewable, name=self.name)
@@ -78,7 +78,7 @@ class BasePlot:
78
78
  @staticmethod
79
79
  def _check_if_inject_streaming_mixin(
80
80
  cls: type[BasePlot], data: Any
81
- ) -> type[BasePlot]: # pyright: ignore[reportSelfClsParameterName]
81
+ ) -> type[BasePlot]:
82
82
  """Dynamically inject streaming mixin based on feed type if not already in MRO."""
83
83
  if not cls.SUPPORT_STREAMING:
84
84
  return cls
@@ -272,6 +272,16 @@ class BasePlot:
272
272
  )
273
273
  return df
274
274
 
275
+ def _widgets_enabled(self) -> bool:
276
+ """Whether interactive widgets are active for this plot."""
277
+ from pfund_plot.config import get_config
278
+
279
+ return not (
280
+ get_config().disable_widgets
281
+ or self._control is None
282
+ or not self._control.get("widgets", True)
283
+ )
284
+
275
285
  def _create_widgets(self) -> None:
276
286
  def _has_required_cols(WidgetClass: type[BaseWidget]) -> bool:
277
287
  """Check if the df has the columns required by the widget."""
@@ -280,13 +290,7 @@ class BasePlot:
280
290
  return True
281
291
  return all(col in self._df.columns for col in required)
282
292
 
283
- from pfund_plot.config import get_config
284
-
285
- if (
286
- get_config().disable_widgets
287
- or self._control is None
288
- or not self._control.get("widgets", True)
289
- ):
293
+ if not self._widgets_enabled():
290
294
  return
291
295
 
292
296
  for WidgetClass in self._ChosenWidgetClasses:
@@ -1055,10 +1059,14 @@ class BasePlot:
1055
1059
  self._plot = self._build_plot(df=self._df)
1056
1060
 
1057
1061
  def _create_pane(self):
1062
+ # num_data is the initial value of the DatetimeRangeWidget slider, so it
1063
+ # only applies when widgets are active. With widgets disabled there is no
1064
+ # slider to reveal the rest of the data, so show the full df instead.
1058
1065
  if (
1059
1066
  self._df is not None
1060
1067
  and self._control
1061
1068
  and self._control.get("num_data") is not None
1069
+ and self._widgets_enabled()
1062
1070
  ):
1063
1071
  df = self._df.tail(self._control["num_data"])
1064
1072
  else:
@@ -173,4 +173,14 @@ def convert_to_lazy_plot(
173
173
  except ImportError:
174
174
  pass
175
175
 
176
+ # Panel Viewable (e.g. the LazyRow/LazyColumn produced by combining plots
177
+ # with + or |, or any raw Panel component)
178
+ try:
179
+ from panel.viewable import Viewable
180
+
181
+ if isinstance(obj, Viewable):
182
+ return plt.panel(obj)
183
+ except ImportError:
184
+ pass
185
+
176
186
  return obj
File without changes