Skip to content

Add seaborn stubs #10721

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

Merged
merged 23 commits into from
Oct 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3907b36
Add seaborn stubs
hamdanal Sep 17, 2023
bef89da
Special case pandas-stubs in pytype test
hamdanal Sep 17, 2023
6645729
Merge branch 'main' into seaborn
AlexWaygood Sep 21, 2023
ddf2f7d
revert special-casing in `pytype_test.py`, now unnecessary
AlexWaygood Sep 21, 2023
fa7cab9
More improvements
hamdanal Sep 23, 2023
fc95c41
Merge remote-tracking branch 'upstream/main' into seaborn
hamdanal Sep 23, 2023
575f56a
Merge remote-tracking branch 'origin/seaborn' into seaborn
hamdanal Sep 23, 2023
5fa2f99
Add `requires_python`
AlexWaygood Sep 24, 2023
f78f6bd
Merge branch 'main' into seaborn
AlexWaygood Sep 24, 2023
445c38c
Update to v0.13
hamdanal Oct 8, 2023
647a3d4
Merge remote-tracking branch 'upstream/main' into seaborn
hamdanal Oct 8, 2023
f240207
Now without type ignores
hamdanal Oct 8, 2023
2f97d1f
typo
hamdanal Oct 8, 2023
e8e11e9
CR and more precise formatter annotation
hamdanal Oct 13, 2023
1180702
Merge remote-tracking branch 'upstream/main' into seaborn
hamdanal Oct 13, 2023
eaa9b59
Fix palette types following seaborn discussion
hamdanal Oct 13, 2023
9bba1f7
wrong kind
hamdanal Oct 13, 2023
720a108
Address CR
hamdanal Oct 28, 2023
42eb1bc
Merge remote-tracking branch 'upstream/main' into seaborn
hamdanal Oct 28, 2023
e1581a7
Remove stubtest entry due to bug fixed in new mypy
hamdanal Oct 28, 2023
f088656
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 28, 2023
18b8d91
Merge remote-tracking branch 'upstream/main' into seaborn
AlexWaygood Oct 28, 2023
5bab6f1
Revert "[pre-commit.ci] auto fixes from pre-commit.com hooks"
AlexWaygood Oct 28, 2023
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
1 change: 1 addition & 0 deletions pyrightconfig.stricter.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"stubs/redis",
"stubs/requests",
"stubs/requests-oauthlib",
"stubs/seaborn",
"stubs/setuptools",
"stubs/stripe",
"stubs/tqdm",
Expand Down
3 changes: 3 additions & 0 deletions stubs/seaborn/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
seaborn._core.scales.(Pipeline|TransFuncs) # aliases defined in `if TYPE_CHECKING` block
seaborn.external.docscrape.ClassDoc.__init__ # stubtest doesn't like ABC class as default value
seaborn.external.docscrape.NumpyDocString.__str__ # weird signature
8 changes: 8 additions & 0 deletions stubs/seaborn/METADATA.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version = "0.13.*"
# Requires a version of numpy and matplotlib with a `py.typed` file
requires = ["matplotlib>=3.8", "numpy>=1.20", "pandas-stubs"]
# matplotlib>=3.8 requires Python >=3.9
requires_python = ">=3.9"

[tool.stubtest]
ignore_missing_stub = false
13 changes: 13 additions & 0 deletions stubs/seaborn/seaborn/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from . import cm as cm
from .axisgrid import *
from .categorical import *
from .colors import crayons as crayons, xkcd_rgb as xkcd_rgb
from .distributions import *
from .matrix import *
from .miscplot import *
from .palettes import *
from .rcmod import *
from .regression import *
from .relational import *
from .utils import *
from .widgets import *
Empty file.
26 changes: 26 additions & 0 deletions stubs/seaborn/seaborn/_core/data.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from _typeshed import Incomplete
from collections.abc import Mapping
from typing import TypeVar, overload

from pandas import DataFrame
from pandas.core.interchange.dataframe_protocol import DataFrame as DataFrameProtocol
from seaborn._core.typing import DataSource, VariableSpec

_T = TypeVar("_T", Mapping[Incomplete, Incomplete], None)

class PlotData:
frame: DataFrame
frames: dict[tuple[str, str], DataFrame]
names: dict[str, str | None]
ids: dict[str, str | int]
source_data: DataSource
source_vars: dict[str, VariableSpec]
def __init__(self, data: DataSource, variables: dict[str, VariableSpec]) -> None: ...
def __contains__(self, key: str) -> bool: ...
def join(self, data: DataSource, variables: dict[str, VariableSpec] | None) -> PlotData: ...

@overload
def handle_data_source(data: _T) -> _T: ...
@overload
def handle_data_source(data: DataFrameProtocol) -> DataFrame: ...
def convert_dataframe_to_pandas(data: object) -> DataFrame: ...
1 change: 1 addition & 0 deletions stubs/seaborn/seaborn/_core/exceptions.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
class PlotSpecError(RuntimeError): ...
10 changes: 10 additions & 0 deletions stubs/seaborn/seaborn/_core/groupby.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from _typeshed import Incomplete
from collections.abc import Callable

from pandas import DataFrame

class GroupBy:
order: dict[str, list[Incomplete] | None]
def __init__(self, order: list[str] | dict[str, list[Incomplete] | None]) -> None: ...
def agg(self, data: DataFrame, *args, **kwargs) -> DataFrame: ...
def apply(self, data: DataFrame, func: Callable[..., DataFrame], *args, **kwargs) -> DataFrame: ...
44 changes: 44 additions & 0 deletions stubs/seaborn/seaborn/_core/moves.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from _typeshed import Incomplete
from collections.abc import Callable
from dataclasses import dataclass
from typing import ClassVar

from pandas import DataFrame
from seaborn._core.groupby import GroupBy
from seaborn._core.scales import Scale
from seaborn._core.typing import Default

default: Default

@dataclass
class Move:
group_by_orient: ClassVar[bool]
def __call__(self, data: DataFrame, groupby: GroupBy, orient: str, scales: dict[str, Scale]) -> DataFrame: ...

@dataclass
class Jitter(Move):
width: float | Default = ...
x: float = 0
y: float = 0
seed: int | None = None

@dataclass
class Dodge(Move):
empty: str = "keep"
gap: float = 0
by: list[str] | None = None

@dataclass
class Stack(Move): ...

@dataclass
class Shift(Move):
x: float = 0
y: float = 0

@dataclass
class Norm(Move):
func: Callable[..., Incomplete] | str = "max"
where: str | None = None
by: list[str] | None = None
percent: bool = False
107 changes: 107 additions & 0 deletions stubs/seaborn/seaborn/_core/plot.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import inspect
import os
from _typeshed import Incomplete, SupportsKeysAndGetItem
from collections.abc import Callable, Generator
from contextlib import contextmanager
from typing import IO, Any, NoReturn, TypeVar
from typing_extensions import Literal, TypedDict

import matplotlib as mpl
from matplotlib.axes import Axes
from matplotlib.figure import Figure, SubFigure
from seaborn._core.data import PlotData
from seaborn._core.moves import Move
from seaborn._core.scales import Scale
from seaborn._core.typing import DataSource, Default, OrderSpec, VariableSpec, VariableSpecList
from seaborn._marks.base import Mark
from seaborn._stats.base import Stat

_ClsT = TypeVar("_ClsT", bound=type[Any])

default: Default

class Layer(TypedDict, total=False):
mark: Mark
stat: Stat | None
move: Move | list[Move] | None
data: PlotData
source: DataSource
vars: dict[str, VariableSpec]
orient: str
legend: bool
label: str | None

class FacetSpec(TypedDict, total=False):
variables: dict[str, VariableSpec]
structure: dict[str, list[str]]
wrap: int | None

class PairSpec(TypedDict, total=False):
variables: dict[str, VariableSpec]
structure: dict[str, list[str]]
cross: bool
wrap: int | None

@contextmanager
def theme_context(params: dict[str, Any]) -> Generator[None, None, None]: ...
def build_plot_signature(cls: _ClsT) -> _ClsT: ... # -> _ClsT & "__signature__ protocol"

class ThemeConfig(mpl.RcParams):
THEME_GROUPS: list[str]
def __init__(self) -> None: ...
def reset(self) -> None: ...
def update(self, __other: SupportsKeysAndGetItem[Incomplete, Incomplete] | None = None, **kwds: Incomplete) -> None: ... # type: ignore[override]

class DisplayConfig(TypedDict):
format: Literal["png", "svg"]
scaling: float
hidpi: bool

class PlotConfig:
def __init__(self) -> None: ...
@property
def theme(self) -> dict[str, Any]: ...
@property
def display(self) -> DisplayConfig: ...

@build_plot_signature
class Plot:
__signature__: inspect.Signature
config: PlotConfig
def __init__(self, *args: DataSource | VariableSpec, data: DataSource = None, **variables: VariableSpec) -> None: ...
def __add__(self, other) -> NoReturn: ...
def on(self, target: Axes | SubFigure | Figure) -> Plot: ...
def add(
self,
mark: Mark,
*transforms: Stat | Move,
orient: str | None = None,
legend: bool = True,
label: str | None = None,
data: DataSource = None,
**variables: VariableSpec,
) -> Plot: ...
def pair(
self, x: VariableSpecList = None, y: VariableSpecList = None, wrap: int | None = None, cross: bool = True
) -> Plot: ...
def facet(
self,
col: VariableSpec = None,
row: VariableSpec = None,
order: OrderSpec | dict[str, OrderSpec] = None,
wrap: int | None = None,
) -> Plot: ...
def scale(self, **scales: Scale) -> Plot: ...
def share(self, **shares: bool | str) -> Plot: ...
def limit(self, **limits: tuple[Any, Any]) -> Plot: ...
def label(self, *, title: str | None = None, legend: str | None = None, **variables: str | Callable[[str], str]) -> Plot: ...
def layout(self, *, size: tuple[float, float] | Default = ..., engine: str | None | Default = ...) -> Plot: ...
def theme(self, *args: dict[str, Any]) -> Plot: ...
def save(self, loc: str | os.PathLike[Any] | IO[Any], **kwargs) -> Plot: ...
def show(self, **kwargs) -> None: ...
def plot(self, pyplot: bool = False) -> Plotter: ...

class Plotter:
def __init__(self, pyplot: bool, theme: dict[str, Any]) -> None: ...
def save(self, loc: str | os.PathLike[Any] | IO[Any], **kwargs) -> Plotter: ...
def show(self, **kwargs) -> None: ...
98 changes: 98 additions & 0 deletions stubs/seaborn/seaborn/_core/properties.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from _typeshed import Incomplete
from collections.abc import Callable
from typing import Any
from typing_extensions import TypeAlias

from matplotlib.markers import MarkerStyle
from matplotlib.path import Path
from numpy.typing import ArrayLike
from pandas import Series
from seaborn._core.scales import Scale

RGBTuple: TypeAlias = tuple[float, float, float]
RGBATuple: TypeAlias = tuple[float, float, float, float]
ColorSpec: TypeAlias = RGBTuple | RGBATuple | str
DashPattern: TypeAlias = tuple[float, ...]
DashPatternWithOffset: TypeAlias = tuple[float, DashPattern | None]
MarkerPattern: TypeAlias = float | str | tuple[int, int, float] | list[tuple[float, float]] | Path | MarkerStyle
Mapping: TypeAlias = Callable[[ArrayLike], ArrayLike]

class Property:
legend: bool
normed: bool
variable: Incomplete
def __init__(self, variable: str | None = None) -> None: ...
def default_scale(self, data: Series[Any]) -> Scale: ...
def infer_scale(self, arg: Any, data: Series[Any]) -> Scale: ...
def get_mapping(self, scale: Scale, data: Series[Any]) -> Mapping: ...
def standardize(self, val: Any) -> Any: ...

class Coordinate(Property):
legend: bool
normed: bool

class IntervalProperty(Property):
legend: bool
normed: bool
@property
def default_range(self) -> tuple[float, float]: ...
def infer_scale(self, arg: Any, data: Series[Any]) -> Scale: ...
def get_mapping(self, scale: Scale, data: Series[Any]) -> Mapping: ...

class PointSize(IntervalProperty): ...

class LineWidth(IntervalProperty):
@property
def default_range(self) -> tuple[float, float]: ...

class EdgeWidth(IntervalProperty):
@property
def default_range(self) -> tuple[float, float]: ...

class Stroke(IntervalProperty): ...
class Alpha(IntervalProperty): ...
class Offset(IntervalProperty): ...

class FontSize(IntervalProperty):
@property
def default_range(self) -> tuple[float, float]: ...

class ObjectProperty(Property):
legend: bool
normed: bool
null_value: Any
def default_scale(self, data: Series[Any]) -> Scale: ...
def infer_scale(self, arg: Any, data: Series[Any]) -> Scale: ...
def get_mapping(self, scale: Scale, data: Series[Any]) -> Mapping: ...

class Marker(ObjectProperty):
null_value: Incomplete
def standardize(self, val: MarkerPattern) -> MarkerStyle: ...

class LineStyle(ObjectProperty):
null_value: str
def standardize(self, val: str | DashPattern) -> DashPatternWithOffset: ...

class TextAlignment(ObjectProperty):
legend: bool

class HorizontalAlignment(TextAlignment): ...
class VerticalAlignment(TextAlignment): ...

class Color(Property):
legend: bool
normed: bool
def standardize(self, val: ColorSpec) -> RGBTuple | RGBATuple: ...
def infer_scale(self, arg: Any, data: Series[Any]) -> Scale: ...
def get_mapping(self, scale: Scale, data: Series[Any]) -> Mapping: ...

class Fill(Property):
legend: bool
normed: bool
def default_scale(self, data: Series[Any]) -> Scale: ...
def infer_scale(self, arg: Any, data: Series[Any]) -> Scale: ...
def standardize(self, val: Any) -> bool: ...
def get_mapping(self, scale: Scale, data: Series[Any]) -> Mapping: ...

PROPERTY_CLASSES: dict[str, type[Property]]
PROPERTIES: dict[str, Property]
15 changes: 15 additions & 0 deletions stubs/seaborn/seaborn/_core/rules.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from collections import UserString
from typing import Any
from typing_extensions import Literal

from pandas import Series

class VarType(UserString):
allowed: tuple[str, ...]
def __init__(self, data: str) -> None: ...
def __eq__(self, other: str) -> bool: ... # type: ignore[override]

def variable_type(
vector: Series[Any], boolean_type: Literal["numeric", "categorical", "boolean"] = "numeric", strict_boolean: bool = False
) -> VarType: ...
def categorical_order(vector: Series[Any], order: list[Any] | None = None) -> list[Any]: ...
Loading