diff --git a/stubs/openpyxl/@tests/stubtest_allowlist.txt b/stubs/openpyxl/@tests/stubtest_allowlist.txt index b5bd2f3b069f..2de1741319e5 100644 --- a/stubs/openpyxl/@tests/stubtest_allowlist.txt +++ b/stubs/openpyxl/@tests/stubtest_allowlist.txt @@ -3,3 +3,7 @@ openpyxl.descriptors.slots.AutoSlotProperties.__new__ # Requires numpy to be installed openpyxl.utils.dataframe + +# Element can be imported from lxml or xml.etree, so the attributes can +# differ at runtime. +openpyxl.xml.functions.Element.* diff --git a/stubs/openpyxl/openpyxl/cell/cell.pyi b/stubs/openpyxl/openpyxl/cell/cell.pyi index ce7c7df30a53..9991c46dd4e8 100644 --- a/stubs/openpyxl/openpyxl/cell/cell.pyi +++ b/stubs/openpyxl/openpyxl/cell/cell.pyi @@ -1,12 +1,21 @@ from _typeshed import Incomplete -from datetime import datetime +from datetime import date, datetime, time, timedelta +from decimal import Decimal +from typing import overload +from typing_extensions import TypeAlias +from openpyxl.cell.rich_text import CellRichText from openpyxl.comments.comments import Comment from openpyxl.styles.cell_style import StyleArray from openpyxl.styles.styleable import StyleableObject +from openpyxl.worksheet.formula import ArrayFormula, DataTableFormula from openpyxl.worksheet.hyperlink import Hyperlink from openpyxl.worksheet.worksheet import Worksheet +_CellValue: TypeAlias = ( # if numpy is installed also numpy bool and number types + bool | float | Decimal | str | CellRichText | date | time | timedelta | DataTableFormula | ArrayFormula +) + __docformat__: str TIME_TYPES: Incomplete TIME_FORMATS: Incomplete @@ -49,14 +58,17 @@ class Cell(StyleableObject): def encoding(self) -> str: ... @property def base_date(self) -> datetime: ... - def check_string(self, value: str): ... + @overload + def check_string(self, value: None) -> None: ... + @overload + def check_string(self, value: str | bytes) -> str: ... def check_error(self, value: object) -> str: ... @property - def value(self) -> str | float | datetime | None: ... + def value(self) -> _CellValue: ... @value.setter - def value(self, value: str | float | datetime | None) -> None: ... + def value(self, value: _CellValue | bytes | None) -> None: ... @property - def internal_value(self) -> str | float | datetime | None: ... + def internal_value(self) -> _CellValue: ... @property def hyperlink(self) -> Hyperlink | None: ... @hyperlink.setter diff --git a/stubs/openpyxl/openpyxl/cell/rich_text.pyi b/stubs/openpyxl/openpyxl/cell/rich_text.pyi new file mode 100644 index 000000000000..e084bdec8532 --- /dev/null +++ b/stubs/openpyxl/openpyxl/cell/rich_text.pyi @@ -0,0 +1,24 @@ +from collections.abc import Iterable +from typing import overload +from typing_extensions import Self + +from openpyxl.descriptors import Strict, String, Typed + +class TextBlock(Strict): + font: Typed + text: String + + def __init__(self, font: Typed, text: String) -> None: ... + def __eq__(self, other: TextBlock) -> bool: ... # type: ignore[override] + +class CellRichText(list[str | TextBlock]): + @overload + def __init__(self, __args: list[str] | list[TextBlock] | list[str | TextBlock] | tuple[str | TextBlock, ...]) -> None: ... + @overload + def __init__(self, *args: str | TextBlock) -> None: ... + @classmethod + def from_tree(cls, node) -> Self: ... + def __add__(self, arg: Iterable[str | TextBlock]) -> CellRichText: ... # type: ignore[override] + def append(self, arg: str | TextBlock) -> None: ... + def extend(self, arg: Iterable[str | TextBlock]) -> None: ... + def as_list(self) -> list[str]: ... diff --git a/stubs/openpyxl/openpyxl/utils/bound_dictionary.pyi b/stubs/openpyxl/openpyxl/utils/bound_dictionary.pyi index 71292228afaf..c4556fa4bb90 100644 --- a/stubs/openpyxl/openpyxl/utils/bound_dictionary.pyi +++ b/stubs/openpyxl/openpyxl/utils/bound_dictionary.pyi @@ -1,7 +1,9 @@ -from _typeshed import Incomplete from collections import defaultdict +from typing import TypeVar -class BoundDictionary(defaultdict[Incomplete, Incomplete]): - reference: Incomplete - def __init__(self, reference: Incomplete | None = ..., *args, **kw) -> None: ... - def __getitem__(self, key): ... +_KT = TypeVar("_KT") +_VT = TypeVar("_VT") + +class BoundDictionary(defaultdict[_KT, _VT]): + reference: str | None + def __init__(self, reference: str | None = None, *args, **kw) -> None: ... diff --git a/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi b/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi index 8193a77bdc32..eda43be324f2 100644 --- a/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi @@ -1,95 +1,115 @@ -from _typeshed import Incomplete +from _typeshed import Incomplete, Unused +from collections.abc import Callable, Iterator +from typing import ClassVar, Generic, TypeVar +from typing_extensions import Self from openpyxl.descriptors import Strict +from openpyxl.descriptors.base import Alias, Bool, Float, Integer, String from openpyxl.descriptors.serialisable import Serialisable from openpyxl.styles.styleable import StyleableObject from openpyxl.utils.bound_dictionary import BoundDictionary +from openpyxl.worksheet.worksheet import Worksheet +from openpyxl.xml.functions import Element + +_DimT = TypeVar("_DimT", bound=Dimension) class Dimension(Strict, StyleableObject): - __fields__: Incomplete - index: Incomplete - hidden: Incomplete - outlineLevel: Incomplete - outline_level: Incomplete - collapsed: Incomplete - style: Incomplete + __fields__: ClassVar[tuple[str, ...]] + + index: Integer + hidden: Bool + outlineLevel: Integer + outline_level: Alias + collapsed: Bool + style: Alias + def __init__( - self, index, hidden, outlineLevel, collapsed, worksheet, visible: bool = ..., style: Incomplete | None = ... + self, + index: int, + hidden: bool, + outlineLevel: int | None, + collapsed: bool, + worksheet: Worksheet, + visible: bool = True, + style: Incomplete | None = None, ) -> None: ... - def __iter__(self): ... - def __copy__(self): ... + def __iter__(self) -> Iterator[tuple[str, str]]: ... + def __copy__(self) -> Self: ... class RowDimension(Dimension): - __fields__: Incomplete - r: Incomplete - s: Incomplete - ht: Incomplete - height: Incomplete - thickBot: Incomplete - thickTop: Incomplete + r: Alias + s: Alias + ht: Float + height: Alias + thickBot: Bool + thickTop: Bool + def __init__( self, - worksheet, - index: int = ..., - ht: Incomplete | None = ..., - customHeight: Incomplete | None = ..., - s: Incomplete | None = ..., - customFormat: Incomplete | None = ..., - hidden: bool = ..., - outlineLevel: int = ..., - outline_level: Incomplete | None = ..., - collapsed: bool = ..., - visible: Incomplete | None = ..., - height: Incomplete | None = ..., - r: Incomplete | None = ..., - spans: Incomplete | None = ..., - thickBot: Incomplete | None = ..., - thickTop: Incomplete | None = ..., - **kw, + worksheet: Worksheet, + index: int = 0, + ht: Incomplete | None = None, + customHeight: Incomplete | None = None, + s: Incomplete | None = None, + customFormat: Incomplete | None = None, + hidden: bool = False, + outlineLevel: int = 0, + outline_level: Incomplete | None = None, + collapsed: bool = False, + visible: Incomplete | None = None, + height: Incomplete | None = None, + r: Incomplete | None = None, + spans: Incomplete | None = None, + thickBot: Incomplete | None = None, + thickTop: Incomplete | None = None, + **kw: Unused, ) -> None: ... @property - def customFormat(self): ... + def customFormat(self) -> bool: ... @property - def customHeight(self): ... + def customHeight(self) -> bool: ... class ColumnDimension(Dimension): - width: Incomplete - bestFit: Incomplete - auto_size: Incomplete - index: Incomplete - min: Incomplete - max: Incomplete - collapsed: Incomplete - __fields__: Incomplete + width: Float + bestFit: Bool + auto_size: Alias + index: String # type: ignore[assignment] + min: Integer + max: Integer + collapsed: Bool + def __init__( self, - worksheet, - index: str = ..., - width=..., - bestFit: bool = ..., - hidden: bool = ..., - outlineLevel: int = ..., - outline_level: Incomplete | None = ..., - collapsed: bool = ..., - style: Incomplete | None = ..., - min: Incomplete | None = ..., - max: Incomplete | None = ..., - customWidth: bool = ..., - visible: Incomplete | None = ..., - auto_size: Incomplete | None = ..., + worksheet: Worksheet, + index: str = "A", + width: int = ..., + bestFit: bool = False, + hidden: bool = False, + outlineLevel: int = 0, + outline_level: int | None = None, + collapsed: bool = False, + style: Incomplete | None = None, + min: int | None = None, + max: int | None = None, + customWidth: bool = False, + visible: bool | None = None, + auto_size: bool | None = None, ) -> None: ... @property - def customWidth(self): ... + def customWidth(self) -> bool: ... def reindex(self) -> None: ... - def to_tree(self): ... + def to_tree(self) -> Element | None: ... -class DimensionHolder(BoundDictionary): - worksheet: Incomplete - max_outline: Incomplete - default_factory: Incomplete - def __init__(self, worksheet, reference: str = ..., default_factory: Incomplete | None = ...) -> None: ... - def group(self, start, end: Incomplete | None = ..., outline_level: int = ..., hidden: bool = ...) -> None: ... - def to_tree(self): ... +class DimensionHolder(BoundDictionary[str, _DimT], Generic[_DimT]): + worksheet: Worksheet + max_outline: int | None + default_factory: Callable[[], _DimT] | None + + def __init__( + self, worksheet: Worksheet, reference: str = "index", default_factory: Callable[[], _DimT] | None = None + ) -> None: ... + def group(self, start: str, end: str | None = None, outline_level: int = 1, hidden: bool = False) -> None: ... + def to_tree(self) -> Element | None: ... class SheetFormatProperties(Serialisable): tagname: str diff --git a/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi b/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi index f3402b772132..7879d5b19ef2 100644 --- a/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi @@ -1,25 +1,34 @@ from _typeshed import Incomplete from collections.abc import Generator, Iterable, Iterator from datetime import datetime -from typing import overload -from typing_extensions import Literal +from typing import Any, overload +from typing_extensions import Final, Literal -from openpyxl.cell.cell import Cell +from openpyxl.cell.cell import Cell, _CellValue +from openpyxl.formatting.formatting import ConditionalFormattingList from openpyxl.workbook.child import _WorkbookChild +from openpyxl.workbook.defined_name import DefinedNameDict from openpyxl.workbook.workbook import Workbook -from openpyxl.worksheet.cell_range import CellRange -from openpyxl.worksheet.datavalidation import DataValidation +from openpyxl.worksheet.cell_range import CellRange, MultiCellRange +from openpyxl.worksheet.datavalidation import DataValidation, DataValidationList +from openpyxl.worksheet.dimensions import ColumnDimension, DimensionHolder, RowDimension, SheetFormatProperties +from openpyxl.worksheet.filters import AutoFilter +from openpyxl.worksheet.page import PageMargins, PrintOptions, PrintPageSetup +from openpyxl.worksheet.pagebreak import ColBreak, RowBreak +from openpyxl.worksheet.properties import WorksheetProperties +from openpyxl.worksheet.protection import SheetProtection +from openpyxl.worksheet.scenario import ScenarioList from openpyxl.worksheet.table import Table, TableList -from openpyxl.worksheet.views import SheetView +from openpyxl.worksheet.views import SheetView, SheetViewList class Worksheet(_WorkbookChild): mime_type: str BREAK_NONE: int BREAK_ROW: int BREAK_COLUMN: int - SHEETSTATE_VISIBLE: str - SHEETSTATE_HIDDEN: str - SHEETSTATE_VERYHIDDEN: str + SHEETSTATE_VISIBLE: Final = "visible" + SHEETSTATE_HIDDEN: Final = "hidden" + SHEETSTATE_VERYHIDDEN: Final = "veryHidden" PAPERSIZE_LETTER: str PAPERSIZE_LETTER_SMALL: str PAPERSIZE_TABLOID: str @@ -33,6 +42,27 @@ class Worksheet(_WorkbookChild): PAPERSIZE_A5: str ORIENTATION_PORTRAIT: str ORIENTATION_LANDSCAPE: str + + row_dimensions: DimensionHolder[RowDimension] + column_dimensions: DimensionHolder[ColumnDimension] + row_breaks: RowBreak + col_breaks: ColBreak + merged_cells: MultiCellRange + data_validations: DataValidationList + sheet_state: Literal["visible", "hidden", "veryHidden"] + page_setup: PrintPageSetup + print_options: PrintOptions + page_margins: PageMargins + views: SheetViewList + protection: SheetProtection + defined_names: DefinedNameDict + auto_filter: AutoFilter + conditional_formatting: ConditionalFormattingList + legacy_drawing: Incomplete | None + sheet_properties: WorksheetProperties + sheet_format: SheetFormatProperties + scenarios: ScenarioList + def __init__(self, parent: Workbook, title: str | None = ...) -> None: ... @property def sheet_view(self) -> SheetView: ... @@ -49,7 +79,10 @@ class Worksheet(_WorkbookChild): @freeze_panes.setter def freeze_panes(self, topLeftCell: Incomplete | None = ...) -> None: ... def cell(self, row: int, column: int, value: str | None = ...) -> Cell: ... - def __getitem__(self, key: str | int | slice) -> Cell | tuple[Cell, ...]: ... + @overload + def __getitem__(self, key: int | slice) -> tuple[Cell, ...]: ... + @overload + def __getitem__(self, key: str) -> Any: ... # Cell | tuple[Cell, ...] def __setitem__(self, key: str, value: str) -> None: ... def __iter__(self) -> Iterator[Cell]: ... def __delitem__(self, key: str) -> None: ... @@ -102,9 +135,9 @@ class Worksheet(_WorkbookChild): values_only: bool, ) -> Generator[tuple[Cell | str | float | datetime | None, ...], None, None]: ... @property - def rows(self) -> Generator[Cell, None, None]: ... + def rows(self) -> Generator[tuple[Cell, ...], None, None]: ... @property - def values(self) -> Generator[str | float | datetime | None, None, None]: ... + def values(self) -> Generator[tuple[_CellValue, ...], None, None]: ... @overload def iter_cols( self, min_col: int | None, max_col: int | None, min_row: int | None, max_row: int | None, values_only: Literal[True] diff --git a/stubs/openpyxl/openpyxl/xml/functions.pyi b/stubs/openpyxl/openpyxl/xml/functions.pyi index 2a6bab56885b..c9438a9e7a9f 100644 --- a/stubs/openpyxl/openpyxl/xml/functions.pyi +++ b/stubs/openpyxl/openpyxl/xml/functions.pyi @@ -1,4 +1,5 @@ from _typeshed import Incomplete +from xml.etree.ElementTree import Element as Element # possibly also imported from lxml NS_REGEX: Incomplete