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

openpyxl: Add _WorkbookChild / ReadOnlyWorksheet / Workbook annotations #11677

Merged
merged 3 commits into from
Apr 1, 2024
Merged
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
2 changes: 2 additions & 0 deletions stubs/openpyxl/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ openpyxl\.descriptors\.(base\.)?Typed\.allow_none
# - or, keyword arguments are explicitly specified
openpyxl.cell.Cell.__init__
openpyxl.cell.cell.Cell.__init__
openpyxl.cell.cell.WriteOnlyCell
openpyxl.cell.WriteOnlyCell
openpyxl.cell.text.PhoneticProperties.__init__
openpyxl.cell.text.PhoneticText.__init__
openpyxl.chart.axis._BaseAxis.__init__
Expand Down
6 changes: 3 additions & 3 deletions stubs/openpyxl/openpyxl/cell/_writer.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from _typeshed import Incomplete
from _typeshed import Incomplete, Unused

def etree_write_cell(xf, worksheet, cell, styled: Incomplete | None = None) -> None: ...
def lxml_write_cell(xf, worksheet, cell, styled: bool = False) -> None: ...
def etree_write_cell(xf, worksheet: Unused, cell, styled: Incomplete | None = None) -> None: ...
def lxml_write_cell(xf, worksheet: Unused, cell, styled: bool = False) -> None: ...

write_cell = lxml_write_cell
write_cell = etree_write_cell
12 changes: 8 additions & 4 deletions stubs/openpyxl/openpyxl/cell/cell.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ from openpyxl.comments.comments import Comment
from openpyxl.compat.numbers import NUMERIC_TYPES as NUMERIC_TYPES # cell numeric types
from openpyxl.styles.cell_style import StyleArray
from openpyxl.styles.styleable import StyleableObject
from openpyxl.workbook.child import _WorkbookChild
from openpyxl.worksheet._read_only import ReadOnlyWorksheet
from openpyxl.worksheet.hyperlink import Hyperlink
from openpyxl.worksheet.worksheet import Worksheet

__docformat__: Final = "restructuredtext en"
TIME_TYPES: Final[tuple[type, ...]]
Expand Down Expand Up @@ -41,7 +42,7 @@ class Cell(StyleableObject):
# row and column are never meant to be None and would lead to errors
def __init__(
self,
worksheet: Worksheet,
worksheet: _WorkbookChild | ReadOnlyWorksheet,
row: int,
column: int,
value: str | float | datetime | None = None,
Expand Down Expand Up @@ -86,10 +87,13 @@ class MergedCell(StyleableObject):
hyperlink: Hyperlink | None
row: int | None
column: int | None
def __init__(self, worksheet: Worksheet, row: int | None = None, column: int | None = None) -> None: ...
def __init__(
self, worksheet: _WorkbookChild | ReadOnlyWorksheet, row: int | None = None, column: int | None = None
) -> None: ...
# Same as Cell.coordinate
# https://github.com/python/mypy/issues/6700
@property
def coordinate(self) -> str: ...
value: str | float | int | datetime | None

def WriteOnlyCell(ws: Worksheet | None = None, value: str | float | datetime | None = None) -> Cell: ...
def WriteOnlyCell(ws: _WorkbookChild | ReadOnlyWorksheet, value: str | float | datetime | None = None) -> Cell: ...
11 changes: 9 additions & 2 deletions stubs/openpyxl/openpyxl/cell/read_only.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,26 @@ from openpyxl.styles.cell_style import StyleArray
from openpyxl.styles.fills import Fill
from openpyxl.styles.fonts import Font
from openpyxl.styles.protection import Protection
from openpyxl.workbook.child import _WorkbookChild
from openpyxl.worksheet._read_only import ReadOnlyWorksheet

class ReadOnlyCell:
parent: Incomplete
parent: _WorkbookChild | ReadOnlyWorksheet
row: Incomplete
column: Incomplete
data_type: Incomplete
def __init__(self, sheet, row, column, value, data_type: str = "n", style_id: int = 0) -> None: ...
def __init__(
self, sheet: _WorkbookChild | ReadOnlyWorksheet, row, column, value, data_type: str = "n", style_id: int = 0
) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...
# Same as Cell.coordinate
# https://github.com/python/mypy/issues/6700
# Defined twice in the implementation
@property
def coordinate(self) -> str: ...
# Same as Cell.column_letter
# https://github.com/python/mypy/issues/6700
@property
def column_letter(self) -> str: ...
@property
Expand All @@ -41,6 +47,7 @@ class ReadOnlyCell:
@property
def protection(self) -> Protection: ...
# Same as Cell.is_date
# https://github.com/python/mypy/issues/6700
@property
def is_date(self) -> bool: ...
@property
Expand Down
1 change: 1 addition & 0 deletions stubs/openpyxl/openpyxl/chart/chartspace.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ChartContainer(Serialisable):
pivotFmts: Incomplete

# Same as _3DBase
# https://github.com/python/mypy/issues/6700
view3D: Typed[View3D, Literal[True]]
floor: Typed[Surface, Literal[True]]
sideWall: Typed[Surface, Literal[True]]
Expand Down
10 changes: 6 additions & 4 deletions stubs/openpyxl/openpyxl/chart/reference.pyi
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from _typeshed import ConvertibleToInt, Incomplete, Unused
from _typeshed import ConvertibleToInt, Unused
from collections.abc import Generator
from typing import Literal, overload

from openpyxl.descriptors import Strict
from openpyxl.descriptors.base import MinMax, String
from openpyxl.workbook.child import _WorkbookChild
from openpyxl.worksheet._read_only import ReadOnlyWorksheet

class DummyWorksheet:
title: str
Expand All @@ -15,12 +17,12 @@ class Reference(Strict):
min_col: MinMax[int, Literal[False]]
max_col: MinMax[int, Literal[False]]
range_string: String[Literal[True]]
worksheet: Incomplete | None
worksheet: _WorkbookChild | ReadOnlyWorksheet | DummyWorksheet
@overload
def __init__(
self,
*,
worksheet: Unused = None,
worksheet: _WorkbookChild | ReadOnlyWorksheet | DummyWorksheet | None = None,
min_col: Unused = None,
min_row: Unused = None,
max_col: Unused = None,
Expand All @@ -30,7 +32,7 @@ class Reference(Strict):
@overload
def __init__(
self,
worksheet: Incomplete | None,
worksheet: _WorkbookChild | ReadOnlyWorksheet,
min_col: ConvertibleToInt,
min_row: ConvertibleToInt,
max_col: ConvertibleToInt | None = None,
Expand Down
5 changes: 3 additions & 2 deletions stubs/openpyxl/openpyxl/chartsheet/chartsheet.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from _typeshed import Incomplete, Unused
from _typeshed import Unused
from typing import ClassVar, Literal

from openpyxl import _Decodable, _VisibilityType
Expand All @@ -12,6 +12,7 @@ from openpyxl.descriptors.base import Alias, Set, Typed
from openpyxl.descriptors.excel import ExtensionList
from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.workbook.child import _WorkbookChild
from openpyxl.workbook.workbook import Workbook
from openpyxl.worksheet.drawing import Drawing
from openpyxl.worksheet.header_footer import HeaderFooter as _HeaderFooter
from openpyxl.worksheet.page import PageMargins, PrintPageSetup
Expand Down Expand Up @@ -50,7 +51,7 @@ class Chartsheet(_WorkbookChild, Serialisable):
picture: SheetBackgroundPicture | None = None,
webPublishItems: WebPublishItems | None = None,
extLst: Unused = None,
parent: Incomplete | None = None,
parent: Workbook | None = None,
title: str | _Decodable | None = "",
sheet_state: _VisibilityType = "visible",
) -> None: ...
Expand Down
2 changes: 1 addition & 1 deletion stubs/openpyxl/openpyxl/packaging/workbook.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class WorkbookPackage(Serialisable):
properties: Alias
workbookProtection: Typed[WorkbookProtection, Literal[True]]
bookViews: Incomplete
sheets: Incomplete
sheets: Incomplete # NestedSequence[ChildSheet]
functionGroups: Typed[FunctionGroupList, Literal[True]]
externalReferences: Incomplete
definedNames: Typed[DefinedNameList, Literal[True]]
Expand Down
7 changes: 3 additions & 4 deletions stubs/openpyxl/openpyxl/reader/workbook.pyi
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from _typeshed import Incomplete
from collections.abc import Generator
from zipfile import ZipFile

from openpyxl.packaging.relationship import Relationship, RelationshipList
from openpyxl.packaging.workbook import PivotCache
from openpyxl.packaging.workbook import ChildSheet, PivotCache
from openpyxl.pivot.cache import CacheDefinition
from openpyxl.workbook import Workbook

Expand All @@ -12,14 +11,14 @@ class WorkbookParser:
workbook_part_name: str
wb: Workbook
keep_links: bool
sheets: list[Incomplete]
sheets: list[ChildSheet]
def __init__(self, archive: ZipFile, workbook_part_name: str, keep_links: bool = True) -> None: ...
@property
def rels(self) -> RelationshipList: ...
# Errors if "parse" is never called.
caches: list[PivotCache]
def parse(self) -> None: ...
def find_sheets(self) -> Generator[tuple[Incomplete, Relationship], None, None]: ...
def find_sheets(self) -> Generator[tuple[ChildSheet, Relationship], None, None]: ...
def assign_names(self) -> None: ...
@property
def pivot_caches(self) -> dict[int, CacheDefinition]: ...
10 changes: 7 additions & 3 deletions stubs/openpyxl/openpyxl/styles/styleable.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from _typeshed import Incomplete, Unused
from _typeshed import Unused
from collections.abc import Iterable

from openpyxl.descriptors.serialisable import Serialisable
from openpyxl.workbook.child import _WorkbookChild
from openpyxl.worksheet._read_only import ReadOnlyWorksheet

from .named_styles import NamedStyle
from .proxy import StyleProxy
Expand Down Expand Up @@ -41,8 +43,10 @@ class StyleableObject:
style: NamedStyleDescriptor
quotePrefix: StyleArrayDescriptor
pivotButton: StyleArrayDescriptor
parent: Incomplete
def __init__(self, sheet, style_array: bytes | bytearray | Iterable[int] | None = None) -> None: ...
parent: _WorkbookChild | ReadOnlyWorksheet
def __init__(
self, sheet: _WorkbookChild | ReadOnlyWorksheet, style_array: bytes | bytearray | Iterable[int] | None = None
) -> None: ...
@property
def style_id(self) -> int: ...
@property
Expand Down
2 changes: 1 addition & 1 deletion stubs/openpyxl/openpyxl/styles/stylesheet.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ class Stylesheet(Serialisable):
def to_tree(self, tagname: str | None = None, idx: Unused = None, namespace: str | None = None) -> Element: ...

def apply_stylesheet(archive: ZipFile, wb: _WorkbookT) -> _WorkbookT | None: ...
def write_stylesheet(wb): ...
def write_stylesheet(wb: Workbook): ...
8 changes: 5 additions & 3 deletions stubs/openpyxl/openpyxl/workbook/_writer.pyi
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from _typeshed import Incomplete

def get_active_sheet(wb): ...
from openpyxl.workbook.workbook import Workbook

def get_active_sheet(wb: Workbook) -> int | None: ...

class WorkbookWriter:
wb: Incomplete
wb: Workbook
rels: Incomplete
package: Incomplete
def __init__(self, wb) -> None: ...
def __init__(self, wb: Workbook) -> None: ...
def write_properties(self) -> None: ...
def write_worksheets(self) -> None: ...
def write_refs(self) -> None: ...
Expand Down
43 changes: 27 additions & 16 deletions stubs/openpyxl/openpyxl/workbook/workbook.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from _typeshed import Incomplete, Unused
from collections.abc import Iterator
from datetime import datetime
from typing import Any, Final
from typing_extensions import deprecated
from typing_extensions import TypeAlias, deprecated
from zipfile import ZipFile

from openpyxl import _Decodable, _ZipFileFileProtocol
Expand All @@ -14,6 +14,9 @@ from openpyxl.worksheet._read_only import ReadOnlyWorksheet
from openpyxl.worksheet._write_only import WriteOnlyWorksheet
from openpyxl.worksheet.worksheet import Worksheet

_WorkbookWorksheet: TypeAlias = Worksheet | WriteOnlyWorksheet | ReadOnlyWorksheet
_WorkbookSheet: TypeAlias = _WorkbookWorksheet | Chartsheet

INTEGER_TYPES: Final[tuple[type[int]]]

class Workbook:
Expand All @@ -32,9 +35,9 @@ class Workbook:
rels: Incomplete
calculation: Incomplete
views: Incomplete
# Private, but useful as a reference of what "sheets" can be for other types
# Useful as a reference of what "sheets" can be for other types
# ExcelReader can add ReadOnlyWorksheet in read_only mode.
_sheets: list[Worksheet | WriteOnlyWorksheet | Chartsheet | ReadOnlyWorksheet]
# _sheets: list[_WorkbookSheet]
def __init__(self, write_only: bool = False, iso_dates: bool = False) -> None: ...
@property
def epoch(self) -> datetime: ...
Expand All @@ -49,38 +52,43 @@ class Workbook:
@property
def excel_base_date(self) -> datetime: ...
@property
def active(self) -> _WorkbookChild | None: ...
def active(self) -> _WorkbookSheet | None: ...
@active.setter
def active(self, value: _WorkbookChild | int) -> None: ...
def active(self, value: Worksheet | Chartsheet | int) -> None: ...
# read_only workbook cannot call this method
# 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(self, worksheet: _WorkbookSheet) -> None: ...
@deprecated("Use wb.remove(worksheet) or del wb[sheetname]")
def remove_sheet(self, worksheet: Worksheet) -> None: ...
def remove_sheet(self, worksheet: _WorkbookSheet) -> None: ...
def create_chartsheet(self, title: str | _Decodable | None = None, index: int | None = None) -> Chartsheet: ...
@deprecated("Use wb[sheetname]")
def get_sheet_by_name(self, name: str) -> Worksheet: ...
def get_sheet_by_name(self, name: str) -> _WorkbookSheet: ...
def __contains__(self, key: str) -> bool: ...
def index(self, worksheet: Worksheet) -> int: ...
def index(self, worksheet: _WorkbookWorksheet) -> int: ...
@deprecated("Use wb.index(worksheet)")
def get_index(self, worksheet: Worksheet) -> int: ...
def __getitem__(self, key: str) -> Worksheet: ...
def get_index(self, worksheet: _WorkbookWorksheet) -> int: ...
def __getitem__(self, key: str) -> _WorkbookSheet: ...
def __delitem__(self, key: str) -> None: ...
def __iter__(self) -> Iterator[Worksheet]: ...
def __iter__(self) -> Iterator[_WorkbookWorksheet]: ...
@deprecated("Use wb.sheetnames")
def get_sheet_names(self) -> list[Worksheet]: ...
def get_sheet_names(self) -> list[str]: ...
@property
def worksheets(self) -> list[Worksheet]: ...
def worksheets(self) -> list[_WorkbookWorksheet]: ...
@property
def chartsheets(self) -> list[Chartsheet]: ...
@property
def sheetnames(self) -> list[str]: ...
@deprecated("Assign scoped named ranges directly to worksheets or global ones to the workbook. Deprecated in 3.1")
def create_named_range(
self, name: str, worksheet: Worksheet | None = None, value: str | Incomplete | None = None, scope: Unused = None
self,
name: str,
worksheet: _WorkbookChild | ReadOnlyWorksheet | None = None,
value: str | Incomplete | None = None,
scope: Unused = None,
) -> None: ...
def add_named_style(self, style: NamedStyle) -> None: ...
@property
Expand All @@ -90,5 +98,8 @@ class Workbook:
def save(self, filename: _ZipFileFileProtocol) -> None: ...
@property
def style_names(self) -> list[str]: ...
def copy_worksheet(self, from_worksheet: Worksheet) -> Worksheet | WriteOnlyWorksheet: ...
# A write_only and read_only workbooks can't use this method as it requires both reading and writing.
# On an implementation level, a WorksheetCopy is created from the call to self.create_sheet,
# but WorksheetCopy only works with Worksheet.
def copy_worksheet(self, from_worksheet: Worksheet) -> Worksheet: ...
def close(self) -> None: ...
11 changes: 8 additions & 3 deletions stubs/openpyxl/openpyxl/worksheet/_read_only.pyi
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from _typeshed import Incomplete, SupportsGetItem
from _typeshed import SupportsGetItem
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.workbook.workbook import Workbook
from openpyxl.worksheet.worksheet import Worksheet

def read_dimension(source) -> _RangeBoundariesTuple | None: ...
Expand All @@ -13,17 +14,21 @@ class ReadOnlyWorksheet:
cell = Worksheet.cell
iter_rows = Worksheet.iter_rows
# Same as Worksheet.values
# https://github.com/python/mypy/issues/6700
@property
def values(self) -> Generator[tuple[_CellValue, ...], None, None]: ...
# Same as Worksheet.rows
# https://github.com/python/mypy/issues/6700
@property
def rows(self) -> Generator[tuple[Cell, ...], None, None]: ...
__getitem__ = Worksheet.__getitem__
__iter__ = Worksheet.__iter__
parent: Incomplete
parent: Workbook
title: str
sheet_state: _VisibilityType
def __init__(self, parent_workbook, title: str, worksheet_path, shared_strings: SupportsGetItem[int, str]) -> None: ...
def __init__(
self, parent_workbook: Workbook, title: str, worksheet_path, shared_strings: SupportsGetItem[int, str]
) -> None: ...
def calculate_dimension(self, force: bool = False): ...
def reset_dimensions(self) -> None: ...
@property
Expand Down
Loading
Loading