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

WIP: lazily import pandas #13849

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ dependencies = [
"contourpy >=1.2",
"numpy >=1.16",
"packaging >=16.8",
"pandas >=1.2",
"pillow >=7.1.0",
"PyYAML >=3.10",
"tornado >=6.2",
Expand Down
7 changes: 4 additions & 3 deletions src/bokeh/models/sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
String,
)
from ..model import Model
from ..util.dependencies import get_pandas
from ..util.deprecation import deprecated
from ..util.serialization import convert_datetime_array
from ..util.warnings import BokehUserWarning, warn
Expand Down Expand Up @@ -232,11 +233,11 @@ def __init__(self, *args: TAny, **kwargs: TAny) -> None:
# TODO (bev) invalid to pass args and "data", check and raise exception
raw_data: DataDict = kwargs.pop("data", {})

import pandas as pd
pd = get_pandas()
if not isinstance(raw_data, dict):
if isinstance(raw_data, pd.DataFrame):
if pd is not None and isinstance(raw_data, pd.DataFrame):
raw_data = self._data_from_df(raw_data)
elif isinstance(raw_data, pd.core.groupby.GroupBy):
elif pd is not None and isinstance(raw_data, pd.core.groupby.GroupBy):
raw_data = self._data_from_groupby(raw_data)
else:
raise ValueError(f"expected a dict or pandas.DataFrame, got {raw_data}")
Expand Down
8 changes: 4 additions & 4 deletions src/bokeh/plotting/_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
Range1d,
Scale,
)
from ..util.dependencies import get_pandas

if TYPE_CHECKING:
import pandas as pd
Expand Down Expand Up @@ -77,16 +78,15 @@
#-----------------------------------------------------------------------------

def get_range(range_input: Range | tuple[float, float] | Sequence[str] | pd.Series[Any] | GroupBy | None) -> Range:
import pandas as pd
from pandas.core.groupby import GroupBy
pandas = get_pandas()

if range_input is None:
return DataRange1d()
if isinstance(range_input, GroupBy):
if pandas is not None and isinstance(range_input, pandas.core.groupby.GroupBy):
return FactorRange(factors=sorted(list(range_input.groups.keys())))
if isinstance(range_input, Range):
return range_input
if isinstance(range_input, pd.Series):
if pandas is not None and isinstance(range_input, pandas.Series):
range_input = range_input.values
if isinstance(range_input, (Sequence, np.ndarray)):
if all(isinstance(x, str) for x in range_input):
Expand Down
16 changes: 15 additions & 1 deletion src/bokeh/util/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
# Standard library imports
from importlib import import_module
from types import ModuleType
from typing import Any
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
import pandas as pd

#-----------------------------------------------------------------------------
# Globals and constants
Expand All @@ -32,6 +35,7 @@
__all__ = (
'import_optional',
'import_required',
'get_pandas',
'uses_pandas',
)

Expand Down Expand Up @@ -92,6 +96,16 @@ def uses_pandas(obj: Any) -> bool:
module = type(obj).__module__
return module is not None and module.startswith("pandas.")

def get_pandas() -> pd | None:
"""
Import pandas (if available, else return None).
"""
try:
import pandas
except ImportError:
return None
return pandas

#-----------------------------------------------------------------------------
# Dev API
#-----------------------------------------------------------------------------
Expand Down
12 changes: 7 additions & 5 deletions src/bokeh/util/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
# Bokeh imports
from ..core.types import ID
from ..settings import settings
from ..util.dependencies import get_pandas
from .strings import format_docstring

if TYPE_CHECKING:
Expand All @@ -52,13 +53,14 @@

@lru_cache(None)
def _compute_datetime_types() -> set[type]:
import pandas as pd
pd = get_pandas()

result = {dt.time, dt.datetime, np.datetime64}
result.add(pd.Timestamp)
result.add(pd.Timedelta)
result.add(pd.Period)
result.add(type(pd.NaT))
if pd is not None:
result.add(pd.Timestamp)
result.add(pd.Timedelta)
result.add(pd.Period)
result.add(type(pd.NaT))
return result

def __getattr__(name: str) -> Any:
Expand Down