Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make panel and panel.io lazy imports #7208

Draft
wants to merge 37 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
ccd6e00
Block imports and remove Pandas
hoxbro Aug 30, 2024
31b2cdb
Merge branch 'main' into speed_import
hoxbro Aug 30, 2024
0bacdd4
Lazy import modules
hoxbro Aug 30, 2024
7c00952
Don't set curdoc during init of _config
hoxbro Aug 30, 2024
9c81c68
Update chat imports
hoxbro Aug 30, 2024
ab7b6e3
Lazy import bokeh and numpy in key modules
hoxbro Aug 30, 2024
5f8f9a4
Switch to BaseException as pytest.fails raise BaseException
hoxbro Aug 30, 2024
67f9456
Wait importing widgets in param.py
hoxbro Aug 30, 2024
e74c57c
fix imports
hoxbro Aug 30, 2024
1ef4784
Rename
hoxbro Aug 30, 2024
ffbf602
Make panel and panel.io lazy imports
hoxbro Aug 30, 2024
5ca6521
Update depends logic
hoxbro Aug 30, 2024
911c044
Add test
hoxbro Aug 30, 2024
fc32f61
Lazily work-around interact docs
hoxbro Aug 30, 2024
723900f
Import template
hoxbro Aug 30, 2024
7d66b7f
Add theme
hoxbro Aug 30, 2024
886d5f8
Fix init serve
hoxbro Aug 31, 2024
0f9044d
Wait to load panel.io.state
hoxbro Aug 31, 2024
82b3972
Clean up imports
hoxbro Aug 31, 2024
dcc3b57
Lazy import layout
hoxbro Aug 31, 2024
8699984
Lazy import widgets
hoxbro Aug 31, 2024
0dfaab5
Lazy import panes
hoxbro Aug 31, 2024
0b5bd22
Move imports which can't be imported outside
hoxbro Aug 31, 2024
5db4b75
Update panel/__init__.py
hoxbro Aug 31, 2024
5748b5e
Update imports
hoxbro Aug 31, 2024
8286744
Make it possible to add custom mappings
hoxbro Sep 1, 2024
2ed8b8d
Merge branch 'speed_import' into lazy_import
hoxbro Sep 1, 2024
4fe1298
Add test for lazy
hoxbro Sep 1, 2024
53f81a7
Add module walk for compile
hoxbro Sep 1, 2024
e79e6e6
Update to work with nested lazy
hoxbro Sep 1, 2024
5850d34
Move io import down into methods in panel/links.py
hoxbro Sep 2, 2024
09063d7
Don't import numpy and asyncio in panel/util
hoxbro Sep 2, 2024
bc02bc9
Wait with importing concurrent.futures
hoxbro Sep 2, 2024
8400206
Tuple not list
hoxbro Sep 2, 2024
a943fda
Add no_lazy import
hoxbro Sep 2, 2024
a2e2541
Merge branch 'main' into lazy_import
hoxbro Sep 2, 2024
0a6d5dd
Misc updates
hoxbro Sep 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions doc/how_to/interact/interact_abbreviations.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ To use `interact`, you need to define a function that you want to explore. Here

```{pyodide}
import panel as pn
from panel.interact import interact
from panel import widgets

pn.extension() # for notebook
Expand All @@ -26,7 +25,7 @@ def f(x):
When you pass this function to `interact` along with `x=10`, a slider is generated and bound to the function parameter, such that when you interact with the widget, the function is called.

```{pyodide}
interact(f, x=10)
pn.interact(f, x=10)
```

When you pass an integer-valued keyword argument of `10` (`x=10`) to `interact`, it generates an integer-valued slider control with a range of `[-10,+3*10]`. In this case, `10` is an *abbreviation* for an actual slider widget:
Expand All @@ -38,7 +37,7 @@ slider_widget = widgets.IntSlider(start=-10,end=30,step=1,value=10)
In fact, we can get the same result if we pass this `IntSlider` as the keyword argument for `x`:

```{pyodide}
interact(f, x=slider_widget)
pn.interact(f, x=slider_widget)
```

This examples clarifies how `interact` processes its keyword arguments:
Expand All @@ -64,35 +63,35 @@ If a 2-tuple of integers is passed `(min,max)`, an integer-valued slider is prod


```{pyodide}
interact(f, x=(0, 4))
pn.interact(f, x=(0, 4))
```

If a 3-tuple of integers is passed `(min,max,step)`, the step size can also be set.


```{pyodide}
interact(f, x=(0, 8, 2))
pn.interact(f, x=(0, 8, 2))
```

A float-valued slider is produced if the elements of the tuples are floats. Here the minimum is `0.0`, the maximum is `10.0` and step size is `0.1` (the default).


```{pyodide}
interact(f, x=(0.0, 10.0))
pn.interact(f, x=(0.0, 10.0))
```

The step size can be changed by passing a third element in the tuple.


```{pyodide}
interact(f, x=(0.0, 10.0, 0.01))
pn.interact(f, x=(0.0, 10.0, 0.01))
```

For both integer and float-valued sliders, you can pick the initial value of the widget by supplying a default keyword argument when you define the underlying Python function. Here we set the initial value of a float slider to `5.5`.


```{pyodide}
@interact(x=(0.0, 20.0, 0.5))
@pn.interact(x=(0.0, 20.0, 0.5))
def h(x=5.5):
return x

Expand All @@ -103,28 +102,28 @@ You can also set the initial value by passing a fourth element in the tuple.


```{pyodide}
interact(f, x=(0.0, 20.0, 0.5, 5.5))
pn.interact(f, x=(0.0, 20.0, 0.5, 5.5))
```

Use `None` as the third element to just set min, max, and value.


```{pyodide}
interact(f, x=(0.0, 20.0, None, 5.5))
pn.interact(f, x=(0.0, 20.0, None, 5.5))
```

Dropdown menus are constructed by passing a list of strings. In this case, the strings are both used as the names in the dropdown menu UI and passed to the underlying Python function.


```{pyodide}
interact(f, x=['apples', 'oranges'])
pn.interact(f, x=['apples', 'oranges'])
```

When working with numeric data ``interact`` will automatically add a discrete slider:


```{pyodide}
interact(f, x=dict([('one', 10), ('two', 20)]))
pn.interact(f, x=dict([('one', 10), ('two', 20)]))
```

## Related Resources
4 changes: 2 additions & 2 deletions doc/how_to/interact/interact_fix_values.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ First, let's declare a simple function.

```{pyodide}
import panel as pn
from panel.interact import fixed
from panel._interact import fixed
pn.extension() # for notebook

def f(x, y):
return x, y
```

Now, call `interact` using the `panel.interact.fixed` function to fix one of the values:
Now, call `interact` using the `panel._interact.fixed` function to fix one of the values:

```{pyodide}
pn.interact(f, x=1, y=fixed(10))
Expand Down
107 changes: 82 additions & 25 deletions panel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,34 +45,87 @@
To learn more about Panel check out
https://panel.holoviz.org/getting_started/index.html
"""
from typing import TYPE_CHECKING as _TC

from param import rx

from . import layout # noqa
from . import links # noqa
from . import pane # noqa
from . import param # noqa
from . import pipeline # noqa
from . import reactive # noqa
from . import template # noqa
from . import viewable # noqa
from . import widgets # noqa
from .config import __version__, config, panel_extension as extension # noqa
from .depends import bind, depends # noqa
from .interact import interact # noqa
from .io import ( # noqa
_jupyter_server_extension_paths, cache, ipywidget, serve, state,
)
from .layout import ( # noqa
Accordion, Card, Column, Feed, FlexBox, FloatPanel, GridBox, GridSpec,
GridStack, HSpacer, Row, Spacer, Swipe, Tabs, VSpacer, WidgetBox,
)
from .pane import panel # noqa
from .param import Param, ReactiveExpr # noqa
from .template import Template # noqa
from .widgets import indicators, widget # noqa
from .__version import __version__
from .config import config, panel_extension as extension
from .depends import bind, depends

if _TC:
from . import (
chat, custom, layout, links, pane, param, pipeline, reactive, template,
theme, viewable, widgets,
)
from ._interact import interact
from .io import serve, state
from .io.cache import cache
from .io.notebook import ( # noqa: F401
_jupyter_server_extension_paths, ipywidget,
)
from .layout import (
Accordion, Card, Column, Feed, FlexBox, FloatPanel, GridBox, GridSpec,
GridStack, HSpacer, Row, Spacer, Swipe, Tabs, VSpacer, WidgetBox,
)
from .pane import panel
from .param import Param, ReactiveExpr
from .template import Template
from .widgets import indicators, widget

_attrs = {
"Accordion": "panel.layout:Accordion",
"Card": "panel.layout:Card",
"Column": "panel.layout:Column",
"Feed": "panel.layout:Feed",
"FlexBox": "panel.layout:FlexBox",
"FloatPanel": "panel.layout:FloatPanel",
"GridBox": "panel.layout:GridBox",
"GridSpec": "panel.layout:GridSpec",
"GridStack": "panel.layout:GridStack",
"HSpacer": "panel.layout:HSpacer",
"Param": "panel.param:Param",
"ReactiveExpr": "panel.param:ReactiveExpr",
"Row": "panel.layout:Row",
"Spacer": "panel.layout:Spacer",
"Swipe": "panel.layout:Swipe",
"Tabs": "panel.layout:Tabs",
"Template": "panel.template:Template",
"VSpacer": "panel.layout:VSpacer",
"WidgetBox": "panel.layout:WidgetBox",
"_jupyter_server_extension_paths": "panel.io.notebook:_jupyter_server_extension_paths",
"cache": "panel.io.cache:cache",
"chat": "panel.chat",
"config": "panel.config:config",
"custom": "panel.custom",
"indicators": "panel.widgets:indicators",
"interact": "panel._interact:interact",
"ipywidget": "panel.io.notebook:ipywidget",
"layout": "panel.layout",
"links": "panel.links",
"pane": "panel.pane",
"panel": "panel.pane:panel",
"param": "panel.param",
hoxbro marked this conversation as resolved.
Show resolved Hide resolved
"pipeline": "panel.pipeline",
"reactive": "panel.reactive",
"serve": "panel.io:serve",
"state": "panel.io.state:state",
"template": "panel.template",
"theme": "panel.theme",
"viewable": "panel.viewable",
"widget": "panel.widgets:widget",
"widgets": "panel.widgets",
}


def __getattr__(name: str) -> object:
if name in _attrs:
import importlib
mod_name, _, attr_name = _attrs[name].partition(':')
mod = importlib.import_module(mod_name)
return getattr(mod, attr_name) if attr_name else mod
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

from . import custom # isort:skip noqa has to be after widgets
from . import chat # isort:skip noqa has to be after widgets

__all__ = (
"__version__",
Expand Down Expand Up @@ -111,11 +164,15 @@
"panel",
"param",
"pipeline",
"reactive",
"rx",
"serve",
"state",
"theme",
"template",
"viewable",
"widgets",
"widget"
)

__dir__ = lambda: list(__all__)
File renamed without changes.
26 changes: 15 additions & 11 deletions panel/chat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
https://panel.holoviz.org/reference/chat/ChatInterface.html
"""

import importlib as _importlib
from typing import TYPE_CHECKING

from .feed import ChatFeed # noqa
from .icon import ChatReactionIcons # noqa
Expand All @@ -38,16 +38,6 @@
from .message import ChatMessage # noqa
from .step import ChatStep # noqa


def __getattr__(name):
"""
Lazily import langchain module when accessed.
"""
if name == "langchain":
return _importlib.import_module("panel.chat.langchain")
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")


__all__ = (
"ChatAreaInput",
"ChatFeed",
Expand All @@ -57,3 +47,17 @@ def __getattr__(name):
"ChatStep",
"langchain",
)

def __getattr__(name):
"""
Lazily import langchain module when accessed.
"""
if name == "langchain":
from . import langchain
return langchain
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

__dir__ = lambda: list(__all__)

if TYPE_CHECKING:
from . import langchain
Loading
Loading