Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 20 additions & 0 deletions stubs/openpyxl/@tests/test_cases/check_read_only.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from collections.abc import Generator
from typing_extensions import assert_type

from openpyxl.cell import _CellGetValue
from openpyxl.cell.read_only import EmptyCell, ReadOnlyCell
from openpyxl.worksheet._read_only import ReadOnlyWorksheet


def check_read_only_methods(sheet: ReadOnlyWorksheet, values_only: bool) -> None:
# These methods alias Worksheet methods at runtime; their self and cell types differ.
assert_type(sheet.cell(1, 1), ReadOnlyCell | EmptyCell)
assert_type(next(sheet.iter_rows()), tuple[ReadOnlyCell | EmptyCell, ...])
assert_type(next(sheet.iter_rows(values_only=True)), tuple[_CellGetValue, ...])
assert_type(next(sheet.iter_rows(1, 2, 1, 3, True)), tuple[_CellGetValue, ...])
assert_type(
sheet.iter_rows(values_only=values_only),
Generator[tuple[ReadOnlyCell | EmptyCell, ...]] | Generator[tuple[_CellGetValue, ...]],
)
assert_type(next(iter(sheet)), tuple[ReadOnlyCell | EmptyCell, ...])
assert_type(sheet[1], tuple[ReadOnlyCell | EmptyCell, ...])
74 changes: 62 additions & 12 deletions stubs/openpyxl/openpyxl/worksheet/_read_only.pyi
Original file line number Diff line number Diff line change
@@ -1,27 +1,77 @@
from _typeshed import SupportsGetItem
from collections.abc import Generator
from collections.abc import Generator, Iterator
from typing import Any, Literal, TypeAlias, overload

from openpyxl import _VisibilityType
from openpyxl.cell import _CellGetValue, _CellOrMergedCell
from openpyxl.cell import _CellGetValue
from openpyxl.cell.read_only import EmptyCell, ReadOnlyCell
from openpyxl.utils.cell import _RangeBoundariesTuple
from openpyxl.workbook.workbook import Workbook
from openpyxl.worksheet.worksheet import Worksheet

_ReadOnlyCell: TypeAlias = ReadOnlyCell | EmptyCell

def read_dimension(source) -> _RangeBoundariesTuple | None: ...

class ReadOnlyWorksheet:
cell = Worksheet.cell
iter_rows = Worksheet.iter_rows
# Same as Worksheet.values
# https://github.com/python/mypy/issues/6700
# Worksheet methods are reused at runtime, but create read-only or empty cells here.
def cell(self, row: int, column: int, value: None = None) -> _ReadOnlyCell: ...

@overload
def iter_rows(
self, min_row: int | None, max_row: int | None, min_col: int | None, max_col: int | None, values_only: Literal[True]
) -> Generator[tuple[_CellGetValue, ...]]: ...
@overload
def iter_rows(
self,
min_row: int | None = None,
max_row: int | None = None,
min_col: int | None = None,
max_col: int | None = None,
*,
values_only: Literal[True],
) -> Generator[tuple[_CellGetValue, ...]]: ...
@overload
def iter_rows(
self,
min_row: int | None = None,
max_row: int | None = None,
min_col: int | None = None,
max_col: int | None = None,
values_only: Literal[False] = False,
) -> Generator[tuple[_ReadOnlyCell, ...]]: ...
@overload
def iter_rows(
self, min_row: int | None, max_row: int | None, min_col: int | None, max_col: int | None, values_only: bool
) -> Generator[tuple[_ReadOnlyCell, ...]] | Generator[tuple[_CellGetValue, ...]]: ...
@overload
def iter_rows(
self,
min_row: int | None = None,
max_row: int | None = None,
min_col: int | None = None,
max_col: int | None = None,
*,
values_only: bool,
) -> Generator[tuple[_ReadOnlyCell, ...]] | Generator[tuple[_CellGetValue, ...]]: ...

@property
def values(self) -> Generator[tuple[_CellGetValue, ...]]: ...
# Same as Worksheet.rows
# https://github.com/python/mypy/issues/6700
@property
def rows(self) -> Generator[tuple[_CellOrMergedCell, ...]]: ...
__getitem__ = Worksheet.__getitem__
__iter__ = Worksheet.__iter__
def rows(self) -> Generator[tuple[_ReadOnlyCell, ...]]: ...

# An int is necessarily a row selection
@overload
def __getitem__(self, key: int) -> tuple[_ReadOnlyCell, ...]: ...
# A slice is necessarily a row or rows, even if targetting a single cell
@overload
def __getitem__(self, key: slice) -> tuple[Any, ...]: ... # tuple[AnyOf[_ReadOnlyCell, tuple[_ReadOnlyCell, ...]]]
# A str could be an individual cell, row or full range
@overload
def __getitem__(
self, key: str
) -> Any: ... # AnyOf[_ReadOnlyCell, tuple[_ReadOnlyCell, ...], tuple[tuple[_ReadOnlyCell, ...], ...]]

def __iter__(self) -> Iterator[tuple[_ReadOnlyCell, ...]]: ...
parent: Workbook
title: str
sheet_state: _VisibilityType
Expand Down
Loading