Skip to content

Commit

Permalink
feat(typing): add py.typed, improve public types
Browse files Browse the repository at this point in the history
  • Loading branch information
scanny committed Apr 29, 2024
1 parent f4a48b5 commit 89b399b
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 18 deletions.
10 changes: 7 additions & 3 deletions src/docx/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,25 @@
from __future__ import annotations

import os
from typing import IO
from typing import IO, TYPE_CHECKING, cast

from docx.opc.constants import CONTENT_TYPE as CT
from docx.package import Package

if TYPE_CHECKING:
from docx.document import Document as DocumentObject
from docx.parts.document import DocumentPart

def Document(docx: str | IO[bytes] | None = None):

def Document(docx: str | IO[bytes] | None = None) -> DocumentObject:
"""Return a |Document| object loaded from `docx`, where `docx` can be either a path
to a ``.docx`` file (a string) or a file-like object.
If `docx` is missing or ``None``, the built-in default document "template" is
loaded.
"""
docx = _default_docx_path() if docx is None else docx
document_part = Package.open(docx).main_document_part
document_part = cast("DocumentPart", Package.open(docx).main_document_part)
if document_part.content_type != CT.WML_DOCUMENT_MAIN:
tmpl = "file '%s' is not a Word file, content type is '%s'"
raise ValueError(tmpl % (docx, document_part.content_type))
Expand Down
45 changes: 31 additions & 14 deletions src/docx/oxml/text/parfmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,18 @@
class CT_Ind(BaseOxmlElement):
"""``<w:ind>`` element, specifying paragraph indentation."""

left = OptionalAttribute("w:left", ST_SignedTwipsMeasure)
right = OptionalAttribute("w:right", ST_SignedTwipsMeasure)
firstLine = OptionalAttribute("w:firstLine", ST_TwipsMeasure)
hanging = OptionalAttribute("w:hanging", ST_TwipsMeasure)
left: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
"w:left", ST_SignedTwipsMeasure
)
right: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
"w:right", ST_SignedTwipsMeasure
)
firstLine: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
"w:firstLine", ST_TwipsMeasure
)
hanging: Length | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
"w:hanging", ST_TwipsMeasure
)


class CT_Jc(BaseOxmlElement):
Expand All @@ -45,6 +53,7 @@ class CT_Jc(BaseOxmlElement):
class CT_PPr(BaseOxmlElement):
"""``<w:pPr>`` element, containing the properties for a paragraph."""

get_or_add_ind: Callable[[], CT_Ind]
get_or_add_pStyle: Callable[[], CT_String]
_insert_sectPr: Callable[[CT_SectPr], None]
_remove_pStyle: Callable[[], None]
Expand Down Expand Up @@ -98,13 +107,15 @@ class CT_PPr(BaseOxmlElement):
numPr = ZeroOrOne("w:numPr", successors=_tag_seq[7:])
tabs = ZeroOrOne("w:tabs", successors=_tag_seq[11:])
spacing = ZeroOrOne("w:spacing", successors=_tag_seq[22:])
ind = ZeroOrOne("w:ind", successors=_tag_seq[23:])
ind: CT_Ind | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
"w:ind", successors=_tag_seq[23:]
)
jc = ZeroOrOne("w:jc", successors=_tag_seq[27:])
sectPr = ZeroOrOne("w:sectPr", successors=_tag_seq[35:])
del _tag_seq

@property
def first_line_indent(self):
def first_line_indent(self) -> Length | None:
"""A |Length| value calculated from the values of `w:ind/@w:firstLine` and
`w:ind/@w:hanging`.
Expand All @@ -122,7 +133,7 @@ def first_line_indent(self):
return firstLine

@first_line_indent.setter
def first_line_indent(self, value):
def first_line_indent(self, value: Length | None):
if self.ind is None and value is None:
return
ind = self.get_or_add_ind()
Expand All @@ -135,30 +146,30 @@ def first_line_indent(self, value):
ind.firstLine = value

@property
def ind_left(self):
def ind_left(self) -> Length | None:
"""The value of `w:ind/@w:left` or |None| if not present."""
ind = self.ind
if ind is None:
return None
return ind.left

@ind_left.setter
def ind_left(self, value):
def ind_left(self, value: Length | None):
if value is None and self.ind is None:
return
ind = self.get_or_add_ind()
ind.left = value

@property
def ind_right(self):
def ind_right(self) -> Length | None:
"""The value of `w:ind/@w:right` or |None| if not present."""
ind = self.ind
if ind is None:
return None
return ind.right

@ind_right.setter
def ind_right(self, value):
def ind_right(self, value: Length | None):
if value is None and self.ind is None:
return
ind = self.get_or_add_ind()
Expand Down Expand Up @@ -340,9 +351,15 @@ class CT_TabStop(BaseOxmlElement):
only needs a __str__ method.
"""

val = RequiredAttribute("w:val", WD_TAB_ALIGNMENT)
leader = OptionalAttribute("w:leader", WD_TAB_LEADER, default=WD_TAB_LEADER.SPACES)
pos = RequiredAttribute("w:pos", ST_SignedTwipsMeasure)
val: WD_TAB_ALIGNMENT = RequiredAttribute( # pyright: ignore[reportAssignmentType]
"w:val", WD_TAB_ALIGNMENT
)
leader: WD_TAB_LEADER | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
"w:leader", WD_TAB_LEADER, default=WD_TAB_LEADER.SPACES
)
pos: Length = RequiredAttribute( # pyright: ignore[reportAssignmentType]
"w:pos", ST_SignedTwipsMeasure
)

def __str__(self) -> str:
"""Text equivalent of a `w:tab` element appearing in a run.
Expand Down
3 changes: 2 additions & 1 deletion src/docx/parts/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from docx.shared import lazyproperty

if TYPE_CHECKING:
from docx.opc.coreprops import CoreProperties
from docx.styles.style import BaseStyle


Expand All @@ -41,7 +42,7 @@ def add_header_part(self):
return header_part, rId

@property
def core_properties(self):
def core_properties(self) -> CoreProperties:
"""A |CoreProperties| object providing read/write access to the core properties
of this document."""
return self.package.core_properties
Expand Down
Empty file added src/docx/py.typed
Empty file.

0 comments on commit 89b399b

Please sign in to comment.