From 5521da8e927c3a489ae0db2532637131598404ae Mon Sep 17 00:00:00 2001 From: Avasam Date: Mon, 4 Dec 2023 15:54:45 -0500 Subject: [PATCH] Openpyxl: Various improvements (#11092) --- stubs/openpyxl/@tests/stubtest_allowlist.txt | 2 + stubs/openpyxl/openpyxl/cell/cell.pyi | 5 +- .../openpyxl/chartsheet/chartsheet.pyi | 2 +- stubs/openpyxl/openpyxl/reader/workbook.pyi | 16 +++--- .../openpyxl/openpyxl/styles/differential.pyi | 12 ++-- stubs/openpyxl/openpyxl/styles/fills.pyi | 4 +- .../openpyxl/openpyxl/styles/named_styles.pyi | 16 +++--- stubs/openpyxl/openpyxl/styles/numbers.pyi | 6 +- stubs/openpyxl/openpyxl/utils/cell.pyi | 18 +++--- stubs/openpyxl/openpyxl/utils/escape.pyi | 4 +- stubs/openpyxl/openpyxl/workbook/child.pyi | 8 +-- stubs/openpyxl/openpyxl/workbook/workbook.pyi | 14 ++--- .../openpyxl/worksheet/_read_only.pyi | 3 +- stubs/openpyxl/openpyxl/worksheet/_reader.pyi | 55 ++++++++++--------- stubs/openpyxl/openpyxl/worksheet/_writer.pyi | 8 +-- .../openpyxl/worksheet/cell_range.pyi | 23 ++++++-- stubs/openpyxl/openpyxl/worksheet/copier.pyi | 8 +-- .../openpyxl/worksheet/dimensions.pyi | 5 +- .../openpyxl/openpyxl/worksheet/worksheet.pyi | 48 ++++++++++++---- .../openpyxl/xml/_functions_overloads.pyi | 9 +-- 20 files changed, 162 insertions(+), 104 deletions(-) diff --git a/stubs/openpyxl/@tests/stubtest_allowlist.txt b/stubs/openpyxl/@tests/stubtest_allowlist.txt index 366ecf61c..a416f36f7 100644 --- a/stubs/openpyxl/@tests/stubtest_allowlist.txt +++ b/stubs/openpyxl/@tests/stubtest_allowlist.txt @@ -44,6 +44,8 @@ openpyxl\.descriptors\.(base\.)?Typed\.allow_none # Inconsistent methods because # - using the default value results in an error because of the runtime type-guards # - or, keyword arguments are explicitly specified +openpyxl.cell.Cell.__init__ +openpyxl.cell.cell.Cell.__init__ openpyxl.cell.text.PhoneticProperties.__init__ openpyxl.cell.text.PhoneticText.__init__ openpyxl.chart.axis._BaseAxis.__init__ diff --git a/stubs/openpyxl/openpyxl/cell/cell.pyi b/stubs/openpyxl/openpyxl/cell/cell.pyi index e92a5b5ee..5c961240b 100644 --- a/stubs/openpyxl/openpyxl/cell/cell.pyi +++ b/stubs/openpyxl/openpyxl/cell/cell.pyi @@ -39,11 +39,12 @@ class Cell(StyleableObject): row: int column: int data_type: str + # row and column are never meant to be None and would lead to errors def __init__( self, worksheet: Worksheet, - row: int | None = None, - column: int | None = None, + row: int, + column: int, value: str | float | datetime | None = None, style_array: StyleArray | None = None, ) -> None: ... diff --git a/stubs/openpyxl/openpyxl/chartsheet/chartsheet.pyi b/stubs/openpyxl/openpyxl/chartsheet/chartsheet.pyi index b1b20ce32..51b307a96 100644 --- a/stubs/openpyxl/openpyxl/chartsheet/chartsheet.pyi +++ b/stubs/openpyxl/openpyxl/chartsheet/chartsheet.pyi @@ -34,7 +34,7 @@ class Chartsheet(_WorkbookChild, Serialisable): extLst: Typed[ExtensionList, Literal[True]] sheet_state: Set[_VisibilityType] headerFooter: Typed[_HeaderFooter, Literal[False]] - HeaderFooter: Alias + HeaderFooter: Alias # type: ignore[assignment] # Different from parent class __elements__: ClassVar[tuple[str, ...]] __attrs__: ClassVar[tuple[str, ...]] def __init__( diff --git a/stubs/openpyxl/openpyxl/reader/workbook.pyi b/stubs/openpyxl/openpyxl/reader/workbook.pyi index 2b6e03d5b..d27a6deb9 100644 --- a/stubs/openpyxl/openpyxl/reader/workbook.pyi +++ b/stubs/openpyxl/openpyxl/reader/workbook.pyi @@ -2,22 +2,24 @@ from _typeshed import Incomplete from collections.abc import Generator from zipfile import ZipFile -from openpyxl.packaging.relationship import RelationshipList +from openpyxl.packaging.relationship import Relationship, RelationshipList +from openpyxl.packaging.workbook import PivotCache from openpyxl.pivot.cache import CacheDefinition from openpyxl.workbook import Workbook class WorkbookParser: archive: ZipFile - workbook_part_name: Incomplete + workbook_part_name: str wb: Workbook - keep_links: Incomplete - sheets: Incomplete - def __init__(self, archive: ZipFile, workbook_part_name, keep_links: bool = True) -> None: ... + keep_links: bool + sheets: list[Incomplete] + def __init__(self, archive: ZipFile, workbook_part_name: str, keep_links: bool = True) -> None: ... @property def rels(self) -> RelationshipList: ... - caches: Incomplete + # Errors if "parse" is never called. + caches: list[PivotCache] def parse(self) -> None: ... - def find_sheets(self) -> Generator[Incomplete, None, None]: ... + def find_sheets(self) -> Generator[tuple[Incomplete, Relationship], None, None]: ... def assign_names(self) -> None: ... @property def pivot_caches(self) -> dict[int, CacheDefinition]: ... diff --git a/stubs/openpyxl/openpyxl/styles/differential.pyi b/stubs/openpyxl/openpyxl/styles/differential.pyi index 7fac40e0f..3946cba22 100644 --- a/stubs/openpyxl/openpyxl/styles/differential.pyi +++ b/stubs/openpyxl/openpyxl/styles/differential.pyi @@ -1,6 +1,6 @@ -from _typeshed import Incomplete +from _typeshed import Incomplete, Unused from typing import ClassVar -from typing_extensions import Literal +from typing_extensions import Literal, SupportsIndex from openpyxl.descriptors.base import Alias, Typed from openpyxl.descriptors.excel import ExtensionList @@ -34,10 +34,10 @@ class DifferentialStyleList(Serialisable): dxf: Incomplete styles: Alias __attrs__: ClassVar[tuple[str, ...]] - def __init__(self, dxf=(), count: Incomplete | None = None) -> None: ... - def append(self, dxf) -> None: ... - def add(self, dxf): ... + def __init__(self, dxf=(), count: Unused = None) -> None: ... + def append(self, dxf: DifferentialStyle) -> None: ... + def add(self, dxf: DifferentialStyle) -> int: ... def __bool__(self) -> bool: ... - def __getitem__(self, idx): ... + def __getitem__(self, idx: SupportsIndex) -> DifferentialStyle: ... @property def count(self) -> int: ... diff --git a/stubs/openpyxl/openpyxl/styles/fills.pyi b/stubs/openpyxl/openpyxl/styles/fills.pyi index fd993ed8e..b56b9d956 100644 --- a/stubs/openpyxl/openpyxl/styles/fills.pyi +++ b/stubs/openpyxl/openpyxl/styles/fills.pyi @@ -113,4 +113,6 @@ class GradientFill(Fill): stop=(), ) -> None: ... def __iter__(self) -> Iterator[tuple[str, str]]: ... - def to_tree(self, tagname: Unused = None, namespace: Unused = None, idx: Unused = None): ... # type: ignore[override] + def to_tree( # type: ignore[override] + self, tagname: Unused = None, namespace: Unused = None, idx: Unused = None + ) -> Element: ... diff --git a/stubs/openpyxl/openpyxl/styles/named_styles.pyi b/stubs/openpyxl/openpyxl/styles/named_styles.pyi index 592675399..805034cff 100644 --- a/stubs/openpyxl/openpyxl/styles/named_styles.pyi +++ b/stubs/openpyxl/openpyxl/styles/named_styles.pyi @@ -8,9 +8,11 @@ from openpyxl.descriptors.excel import ExtensionList from openpyxl.descriptors.serialisable import Serialisable from openpyxl.styles.alignment import Alignment from openpyxl.styles.borders import Border +from openpyxl.styles.cell_style import CellStyle, StyleArray from openpyxl.styles.fills import Fill from openpyxl.styles.fonts import Font from openpyxl.styles.protection import Protection +from openpyxl.workbook.workbook import Workbook class NamedStyle(Serialisable): font: Typed[Font, Literal[False]] @@ -41,16 +43,16 @@ class NamedStyle(Serialisable): def __iter__(self) -> Iterator[tuple[str, str]]: ... @property def xfId(self) -> int | None: ... - def bind(self, wb) -> None: ... - def as_tuple(self): ... - def as_xf(self): ... - def as_name(self): ... + def bind(self, wb: Workbook) -> None: ... + def as_tuple(self) -> StyleArray: ... + def as_xf(self) -> CellStyle: ... + def as_name(self) -> _NamedCellStyle: ... -class NamedStyleList(list[Incomplete]): +class NamedStyleList(list[NamedStyle]): @property def names(self) -> list[str]: ... - def __getitem__(self, key): ... - def append(self, style) -> None: ... + def __getitem__(self, key: int | str) -> NamedStyle: ... # type: ignore[override] + def append(self, style: NamedStyle) -> None: ... class _NamedCellStyle(Serialisable): tagname: ClassVar[str] diff --git a/stubs/openpyxl/openpyxl/styles/numbers.pyi b/stubs/openpyxl/openpyxl/styles/numbers.pyi index b9856cc15..1fdf97202 100644 --- a/stubs/openpyxl/openpyxl/styles/numbers.pyi +++ b/stubs/openpyxl/openpyxl/styles/numbers.pyi @@ -1,7 +1,7 @@ from _typeshed import ConvertibleToInt, Incomplete, Unused from re import Pattern from typing import ClassVar, overload -from typing_extensions import Final, Literal, TypeGuard +from typing_extensions import Final, Literal, SupportsIndex, TypeGuard from openpyxl.descriptors import Strict, String from openpyxl.descriptors.base import Integer @@ -58,7 +58,7 @@ def is_datetime(fmt: None) -> None: ... @overload def is_datetime(fmt: str) -> Literal["datetime", "date", "time"] | None: ... def is_builtin(fmt: str | None) -> TypeGuard[str]: ... -def builtin_format_code(index): ... +def builtin_format_code(index: int) -> str | None: ... @overload def builtin_format_id(fmt: None) -> None: ... @overload @@ -81,4 +81,4 @@ class NumberFormatList(Serialisable): def __init__(self, count: Unused = None, numFmt=()) -> None: ... @property def count(self) -> int: ... - def __getitem__(self, idx): ... + def __getitem__(self, idx: SupportsIndex) -> NumberFormat: ... diff --git a/stubs/openpyxl/openpyxl/utils/cell.pyi b/stubs/openpyxl/openpyxl/utils/cell.pyi index 5b15e29f3..815c8c750 100644 --- a/stubs/openpyxl/openpyxl/utils/cell.pyi +++ b/stubs/openpyxl/openpyxl/utils/cell.pyi @@ -1,11 +1,13 @@ -from _typeshed import Incomplete from collections.abc import Generator from re import Pattern -from typing_extensions import Final +from typing_extensions import Final, TypeAlias + +# "1:1" | "A1:A1" | "A:A" +_RangeBoundariesTuple: TypeAlias = tuple[None, int, None, int] | tuple[int, int, int, int] | tuple[int, None, int, None] COORD_RE: Final[Pattern[str]] -COL_RANGE: Final = """[A-Z]{1,3}:[A-Z]{1,3}:""" -ROW_RANGE: Final = r"""\d+:\d+:""" +COL_RANGE: Final = "[A-Z]{1,3}:[A-Z]{1,3}:" +ROW_RANGE: Final = r"\d+:\d+:" RANGE_EXPR: Final[str] ABSOLUTE_RE: Final[Pattern[str]] SHEET_TITLE: Final[str] @@ -16,9 +18,9 @@ def coordinate_from_string(coord_string: str) -> tuple[str, int]: ... def absolute_coordinate(coord_string: str) -> str: ... def get_column_letter(idx: int) -> str: ... def column_index_from_string(str_col: str) -> int: ... -def range_boundaries(range_string: str) -> tuple[int, int, int, int]: ... -def rows_from_range(range_string) -> Generator[Incomplete, None, None]: ... -def cols_from_range(range_string) -> Generator[Incomplete, None, None]: ... +def range_boundaries(range_string: str) -> _RangeBoundariesTuple: ... +def rows_from_range(range_string: str) -> Generator[tuple[str, ...], None, None]: ... +def cols_from_range(range_string: str) -> Generator[tuple[str, ...], None, None]: ... def coordinate_to_tuple(coordinate: str) -> tuple[int, int]: ... -def range_to_tuple(range_string: str) -> tuple[str, tuple[int, int, int, int]]: ... +def range_to_tuple(range_string: str) -> tuple[str, _RangeBoundariesTuple]: ... def quote_sheetname(sheetname: str) -> str: ... diff --git a/stubs/openpyxl/openpyxl/utils/escape.pyi b/stubs/openpyxl/openpyxl/utils/escape.pyi index 3e182f450..0ad3a1008 100644 --- a/stubs/openpyxl/openpyxl/utils/escape.pyi +++ b/stubs/openpyxl/openpyxl/utils/escape.pyi @@ -1,2 +1,2 @@ -def escape(value): ... -def unescape(value): ... +def escape(value: str) -> str: ... +def unescape(value: str) -> str: ... diff --git a/stubs/openpyxl/openpyxl/workbook/child.pyi b/stubs/openpyxl/openpyxl/workbook/child.pyi index 678dcbb1a..c4e07c6e6 100644 --- a/stubs/openpyxl/openpyxl/workbook/child.pyi +++ b/stubs/openpyxl/openpyxl/workbook/child.pyi @@ -1,17 +1,17 @@ -from _typeshed import Incomplete +from collections.abc import Iterable from re import Pattern from typing_extensions import Final from openpyxl import _Decodable from openpyxl.workbook.workbook import Workbook -from openpyxl.worksheet.header_footer import HeaderFooterItem +from openpyxl.worksheet.header_footer import HeaderFooter, HeaderFooterItem INVALID_TITLE_REGEX: Final[Pattern[str]] -def avoid_duplicate_name(names, value): ... +def avoid_duplicate_name(names: Iterable[str], value: str) -> str: ... class _WorkbookChild: - HeaderFooter: Incomplete + HeaderFooter: HeaderFooter def __init__(self, parent: Workbook | None = None, title: str | _Decodable | None = None) -> None: ... @property def parent(self) -> Workbook | None: ... diff --git a/stubs/openpyxl/openpyxl/workbook/workbook.pyi b/stubs/openpyxl/openpyxl/workbook/workbook.pyi index d418f46a5..515010b24 100644 --- a/stubs/openpyxl/openpyxl/workbook/workbook.pyi +++ b/stubs/openpyxl/openpyxl/workbook/workbook.pyi @@ -1,6 +1,7 @@ -from _typeshed import Incomplete +from _typeshed import Incomplete, Unused from collections.abc import Iterator from datetime import datetime +from typing import Any from typing_extensions import Final from zipfile import ZipFile @@ -46,7 +47,10 @@ class Workbook: def active(self) -> _WorkbookChild | None: ... @active.setter def active(self, value: _WorkbookChild | int) -> None: ... - def create_sheet(self, title: str | _Decodable | None = None, index: int | None = None): ... + # Could be generic based on write_only + def create_sheet( + self, title: str | _Decodable | None = None, index: int | None = None + ) -> Any: ... # AnyOf[WriteOnlyWorksheet, Worksheet] def move_sheet(self, sheet: Worksheet | str, offset: int = 0) -> None: ... def remove(self, worksheet: Worksheet) -> None: ... def remove_sheet(self, worksheet: Worksheet) -> None: ... @@ -66,11 +70,7 @@ class Workbook: @property def sheetnames(self) -> list[str]: ... def create_named_range( - self, - name: str, - worksheet: Worksheet | None = None, - value: str | Incomplete | None = None, - scope: Incomplete | None = None, + self, name: str, worksheet: Worksheet | None = None, value: str | Incomplete | None = None, scope: Unused = None ) -> None: ... def add_named_style(self, style: NamedStyle) -> None: ... @property diff --git a/stubs/openpyxl/openpyxl/worksheet/_read_only.pyi b/stubs/openpyxl/openpyxl/worksheet/_read_only.pyi index 8eba59e18..224bc864e 100644 --- a/stubs/openpyxl/openpyxl/worksheet/_read_only.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/_read_only.pyi @@ -4,9 +4,10 @@ from collections.abc import Generator from openpyxl import _VisibilityType from openpyxl.cell import _CellValue from openpyxl.cell.cell import Cell +from openpyxl.utils.cell import _RangeBoundariesTuple from openpyxl.worksheet.worksheet import Worksheet -def read_dimension(source): ... +def read_dimension(source) -> _RangeBoundariesTuple | None: ... class ReadOnlyWorksheet: cell = Worksheet.cell diff --git a/stubs/openpyxl/openpyxl/worksheet/_reader.pyi b/stubs/openpyxl/openpyxl/worksheet/_reader.pyi index d5e0d4169..c5568abfd 100644 --- a/stubs/openpyxl/openpyxl/worksheet/_reader.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/_reader.pyi @@ -1,11 +1,14 @@ -from _typeshed import Incomplete +from _typeshed import Incomplete, SupportsGetItem, Unused from collections.abc import Container, Generator from datetime import datetime from typing_extensions import Final +from xml.etree.ElementTree import _FileRead from openpyxl.cell.rich_text import CellRichText -from openpyxl.descriptors.serialisable import _ChildSerialisableTreeElement +from openpyxl.descriptors.serialisable import _ChildSerialisableTreeElement, _SerialisableTreeElement +from openpyxl.utils.cell import _RangeBoundariesTuple +from ..xml._functions_overloads import _HasAttrib, _SupportsIterAndAttrib from .hyperlink import HyperlinkList from .pagebreak import ColBreak, RowBreak from .protection import SheetProtection @@ -46,15 +49,15 @@ class WorkSheetParser: min_row: Incomplete | None min_col: Incomplete | None epoch: datetime - source: Incomplete - shared_strings: Incomplete + source: _FileRead + shared_strings: SupportsGetItem[int, Incomplete] data_only: bool shared_formulae: dict[Incomplete, Incomplete] row_counter: int col_counter: int tables: TablePartList - date_formats: Container[Incomplete] - timedelta_formats: Container[Incomplete] + date_formats: Container[int] + timedelta_formats: Container[int] row_dimensions: dict[Incomplete, Incomplete] column_dimensions: dict[Incomplete, Incomplete] number_formats: list[Incomplete] @@ -70,39 +73,41 @@ class WorkSheetParser: def __init__( self, - src, - shared_strings, + src: _FileRead, + shared_strings: SupportsGetItem[int, Incomplete], data_only: bool = False, epoch: datetime = ..., - date_formats: Container[Incomplete] = ..., - timedelta_formats: Container[Incomplete] = ..., + date_formats: Container[int] = ..., + timedelta_formats: Container[int] = ..., rich_text: bool = False, ) -> None: ... def parse(self) -> Generator[Incomplete, None, None]: ... - def parse_dimensions(self): ... - def parse_cell(self, element): ... + def parse_dimensions(self) -> _RangeBoundariesTuple | None: ... + def parse_cell(self, element) -> dict[str, Incomplete]: ... def parse_formula(self, element): ... - def parse_column_dimensions(self, col) -> None: ... - def parse_row(self, row): ... - def parse_formatting(self, element) -> None: ... - def parse_sheet_protection(self, element) -> None: ... - def parse_extensions(self, element) -> None: ... - def parse_legacy(self, element) -> None: ... - def parse_row_breaks(self, element) -> None: ... - def parse_col_breaks(self, element) -> None: ... - def parse_custom_views(self, element) -> None: ... + def parse_column_dimensions(self, col: _HasAttrib) -> None: ... + def parse_row(self, row: _SupportsIterAndAttrib) -> tuple[int, list[dict[str, Incomplete]]]: ... + def parse_formatting(self, element: _ChildSerialisableTreeElement) -> None: ... + def parse_sheet_protection(self, element: _SerialisableTreeElement) -> None: ... + def parse_extensions(self, element: _ChildSerialisableTreeElement) -> None: ... + def parse_legacy(self, element: _ChildSerialisableTreeElement) -> None: ... + def parse_row_breaks(self, element: _ChildSerialisableTreeElement) -> None: ... + def parse_col_breaks(self, element: _ChildSerialisableTreeElement) -> None: ... + def parse_custom_views(self, element: Unused) -> None: ... class WorksheetReader: ws: Incomplete - parser: Incomplete - tables: Incomplete - def __init__(self, ws, xml_source, shared_strings, data_only, rich_text: bool) -> None: ... + parser: WorkSheetParser + tables: list[Incomplete] + def __init__( + self, ws, xml_source: _FileRead, shared_strings: SupportsGetItem[int, Incomplete], data_only: bool, rich_text: bool + ) -> None: ... def bind_cells(self) -> None: ... def bind_formatting(self) -> None: ... def bind_tables(self) -> None: ... def bind_merged_cells(self) -> None: ... def bind_hyperlinks(self) -> None: ... - def normalize_merged_cell_link(self, coord): ... + def normalize_merged_cell_link(self, coord: str) -> Incomplete | None: ... def bind_col_dimensions(self) -> None: ... def bind_row_dimensions(self) -> None: ... def bind_properties(self) -> None: ... diff --git a/stubs/openpyxl/openpyxl/worksheet/_writer.pyi b/stubs/openpyxl/openpyxl/worksheet/_writer.pyi index 841132661..151511935 100644 --- a/stubs/openpyxl/openpyxl/worksheet/_writer.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/_writer.pyi @@ -14,12 +14,12 @@ _OutType: TypeAlias = _SupportsCloseAndWrite | StrPath ALL_TEMP_FILES: list[str] -def create_temporary_file(suffix: str = ""): ... +def create_temporary_file(suffix: str = "") -> str: ... class WorksheetWriter: ws: Incomplete out: _OutType - xf: Incomplete + xf: Generator[Incomplete | None, Incomplete, None] def __init__(self, ws, out: _OutType | None = None) -> None: ... def write_properties(self) -> None: ... def write_dimensions(self) -> None: ... @@ -27,7 +27,7 @@ class WorksheetWriter: def write_views(self) -> None: ... def write_cols(self) -> None: ... def write_top(self) -> None: ... - def rows(self): ... + def rows(self) -> list[tuple[int, list[Incomplete]]]: ... def write_rows(self) -> None: ... def write_row(self, xf, row, row_idx) -> None: ... def write_protection(self) -> None: ... @@ -50,5 +50,5 @@ class WorksheetWriter: def write_tail(self) -> None: ... def write(self) -> None: ... def close(self) -> None: ... - def read(self): ... + def read(self) -> bytes: ... def cleanup(self) -> None: ... diff --git a/stubs/openpyxl/openpyxl/worksheet/cell_range.pyi b/stubs/openpyxl/openpyxl/worksheet/cell_range.pyi index b970a970a..edea01770 100644 --- a/stubs/openpyxl/openpyxl/worksheet/cell_range.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/cell_range.pyi @@ -1,4 +1,4 @@ -from _typeshed import ConvertibleToInt, Incomplete, Unused +from _typeshed import ConvertibleToInt, Incomplete from collections.abc import Generator, Iterator from itertools import product from typing import Any, overload @@ -15,14 +15,17 @@ class CellRange(Serialisable): max_row: MinMax[int, Literal[False]] title: str | None + # With `range_string`, min/max parameters go unused. + # Enforcing `None` to avoid confusion upon which params get used + # if the user still tries to pass a `ConvertibleToInt`. @overload def __init__( self, range_string: str, - min_col: Unused = None, - min_row: Unused = None, - max_col: Unused = None, - max_row: Unused = None, + min_col: None = None, + min_row: None = None, + max_col: None = None, + max_row: None = None, title: str | None = None, ) -> None: ... @overload @@ -36,6 +39,16 @@ class CellRange(Serialisable): max_row: ConvertibleToInt, title: str | None = None, ) -> None: ... + @overload + def __init__( + self, + range_string: None, + min_col: ConvertibleToInt, + min_row: ConvertibleToInt, + max_col: ConvertibleToInt, + max_row: ConvertibleToInt, + title: str | None = None, + ) -> None: ... @property def bounds(self) -> tuple[int, int, int, int]: ... @property diff --git a/stubs/openpyxl/openpyxl/worksheet/copier.pyi b/stubs/openpyxl/openpyxl/worksheet/copier.pyi index 5e8886fd7..e32d38c57 100644 --- a/stubs/openpyxl/openpyxl/worksheet/copier.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/copier.pyi @@ -1,7 +1,7 @@ -from _typeshed import Incomplete +from openpyxl.worksheet.worksheet import Worksheet class WorksheetCopy: - source: Incomplete - target: Incomplete - def __init__(self, source_worksheet, target_worksheet) -> None: ... + source: Worksheet + target: Worksheet + def __init__(self, source_worksheet: Worksheet, target_worksheet: Worksheet) -> None: ... def copy_worksheet(self) -> None: ... diff --git a/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi b/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi index 230a41d72..442d8415d 100644 --- a/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/dimensions.pyi @@ -8,6 +8,7 @@ from openpyxl.descriptors.base import Alias, Bool, Float, Integer, String, _Conv from openpyxl.descriptors.serialisable import Serialisable from openpyxl.styles.styleable import StyleableObject from openpyxl.utils.bound_dictionary import BoundDictionary +from openpyxl.utils.cell import _RangeBoundariesTuple from openpyxl.worksheet.worksheet import Worksheet from openpyxl.xml.functions import Element @@ -21,7 +22,7 @@ class Dimension(Strict, StyleableObject): outlineLevel: Integer[Literal[True]] outline_level: Alias collapsed: Bool[Literal[False]] - style: Alias + style: Alias # type: ignore[assignment] def __init__( self, @@ -139,4 +140,4 @@ class SheetDimension(Serialisable): ref: String[Literal[False]] def __init__(self, ref: str) -> None: ... @property - def boundaries(self) -> tuple[int, int, int, int]: ... + def boundaries(self) -> _RangeBoundariesTuple: ... diff --git a/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi b/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi index 3ce24862b..6964d6018 100644 --- a/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi +++ b/stubs/openpyxl/openpyxl/worksheet/worksheet.pyi @@ -1,12 +1,15 @@ -from _typeshed import Incomplete +from _typeshed import ConvertibleToInt, Incomplete from collections.abc import Generator, Iterable, Iterator from datetime import datetime +from types import GeneratorType from typing import Any, NoReturn, overload from typing_extensions import Final, Literal from openpyxl import _Decodable, _VisibilityType from openpyxl.cell import _CellValue from openpyxl.cell.cell import Cell +from openpyxl.chart._chart import ChartBase +from openpyxl.drawing.image import Image from openpyxl.formatting.formatting import ConditionalFormattingList from openpyxl.workbook.child import _WorkbookChild from openpyxl.workbook.defined_name import DefinedNameDict @@ -68,7 +71,7 @@ class Worksheet(_WorkbookChild): sheet_format: SheetFormatProperties scenarios: ScenarioList - def __init__(self, parent: Workbook, title: str | _Decodable | None = None) -> None: ... + def __init__(self, parent: Workbook | None, title: str | _Decodable | None = None) -> None: ... @property def sheet_view(self) -> SheetView: ... @property @@ -183,22 +186,38 @@ class Worksheet(_WorkbookChild): @property def columns(self) -> Generator[tuple[Cell, ...], None, None]: ... def set_printer_settings( - self, paper_size: int | None, orientation: None | Literal["default", "portrait", "landscape"] + self, paper_size: int | None, orientation: Literal["default", "portrait", "landscape"] | None ) -> None: ... def add_data_validation(self, data_validation: DataValidation) -> None: ... - def add_chart(self, chart, anchor: Incomplete | None = None) -> None: ... - def add_image(self, img, anchor: Incomplete | None = None) -> None: ... + def add_chart(self, chart: ChartBase, anchor: str | None = None) -> None: ... + def add_image(self, img: Image, anchor: str | None = None) -> None: ... def add_table(self, table: Table) -> None: ... @property def tables(self) -> TableList: ... def add_pivot(self, pivot) -> None: ... + # Same overload as CellRange.__init__ + @overload + def merge_cells( + self, range_string: str, start_row: None = None, start_column: None = None, end_row: None = None, end_column: None = None + ) -> None: ... + @overload def merge_cells( self, - range_string: str | None = None, - start_row: int | None = None, - start_column: int | None = None, - end_row: int | None = None, - end_column: int | None = None, + range_string: None = None, + *, + start_row: ConvertibleToInt, + start_column: ConvertibleToInt, + end_row: ConvertibleToInt, + end_column: ConvertibleToInt, + ) -> None: ... + @overload + def merge_cells( + self, + range_string: None, + start_row: ConvertibleToInt, + start_column: ConvertibleToInt, + end_row: ConvertibleToInt, + end_column: ConvertibleToInt, ) -> None: ... # deprecated: Will always raise: TypeError: 'set' object is not subscriptable @property @@ -211,7 +230,14 @@ class Worksheet(_WorkbookChild): end_row: int | None = None, end_column: int | None = None, ) -> None: ... - def append(self, iterable: Iterable[Incomplete]) -> None: ... + def append( + self, + iterable: list[Incomplete] + | tuple[Incomplete, ...] + | range + | GeneratorType[Incomplete, object, object] + | dict[int | str, Incomplete], + ) -> None: ... def insert_rows(self, idx: int, amount: int = 1) -> None: ... def insert_cols(self, idx: int, amount: int = 1) -> None: ... def delete_rows(self, idx: int, amount: int = 1) -> None: ... diff --git a/stubs/openpyxl/openpyxl/xml/_functions_overloads.pyi b/stubs/openpyxl/openpyxl/xml/_functions_overloads.pyi index e99694d1a..4583f01a8 100644 --- a/stubs/openpyxl/openpyxl/xml/_functions_overloads.pyi +++ b/stubs/openpyxl/openpyxl/xml/_functions_overloads.pyi @@ -1,7 +1,7 @@ # This file does not exist at runtime. It is a helper file to overload imported functions in openpyxl.xml.functions import sys -from _typeshed import Incomplete, ReadableBuffer, SupportsIter +from _typeshed import Incomplete, ReadableBuffer from collections.abc import Iterable, Iterator, Mapping, Sequence from typing import Any, Protocol, TypeVar, overload from typing_extensions import TypeAlias @@ -38,11 +38,12 @@ class _SupportsFindChartLines(Protocol): def find(self, __path: str) -> ChartLines | None: ... class _SupportsFindAndIterAndAttribAndText( # noqa: Y046 - _SupportsFindChartLines, SupportsIter[Incomplete], _HasAttrib, _HasText, Protocol + _SupportsFindChartLines, Iterable[Incomplete], _HasAttrib, _HasText, Protocol ): ... -class _SupportsIterAndAttribAndTextAndTag(SupportsIter[Incomplete], _HasAttrib, _HasText, _HasTag, Protocol): ... # noqa: Y046 +class _SupportsIterAndAttrib(Iterable[Incomplete], _HasAttrib, Protocol): ... # noqa: Y046 +class _SupportsIterAndAttribAndTextAndTag(Iterable[Incomplete], _HasAttrib, _HasText, _HasTag, Protocol): ... # noqa: Y046 class _SupportsIterAndAttribAndTextAndGet( # noqa: Y046 - SupportsIter[Incomplete], _HasAttrib, _HasText, _HasGet[Incomplete], Protocol + Iterable[Incomplete], _HasAttrib, _HasText, _HasGet[Incomplete], Protocol ): ... class _ParentElement(Protocol[_T]):