aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/docx/parts
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/docx/parts')
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/__init__.py0
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/document.py149
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/hdrftr.py53
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/image.py80
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/numbering.py33
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/settings.py51
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/story.py95
-rw-r--r--.venv/lib/python3.12/site-packages/docx/parts/styles.py44
8 files changed, 505 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/__init__.py b/.venv/lib/python3.12/site-packages/docx/parts/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/__init__.py
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/document.py b/.venv/lib/python3.12/site-packages/docx/parts/document.py
new file mode 100644
index 00000000..416bb1a2
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/document.py
@@ -0,0 +1,149 @@
+"""|DocumentPart| and closely related objects."""
+
+from __future__ import annotations
+
+from typing import IO, TYPE_CHECKING, cast
+
+from docx.document import Document
+from docx.enum.style import WD_STYLE_TYPE
+from docx.opc.constants import RELATIONSHIP_TYPE as RT
+from docx.parts.hdrftr import FooterPart, HeaderPart
+from docx.parts.numbering import NumberingPart
+from docx.parts.settings import SettingsPart
+from docx.parts.story import StoryPart
+from docx.parts.styles import StylesPart
+from docx.shape import InlineShapes
+from docx.shared import lazyproperty
+
+if TYPE_CHECKING:
+ from docx.opc.coreprops import CoreProperties
+ from docx.settings import Settings
+ from docx.styles.style import BaseStyle
+
+
+class DocumentPart(StoryPart):
+ """Main document part of a WordprocessingML (WML) package, aka a .docx file.
+
+ Acts as broker to other parts such as image, core properties, and style parts. It
+ also acts as a convenient delegate when a mid-document object needs a service
+ involving a remote ancestor. The `Parented.part` property inherited by many content
+ objects provides access to this part object for that purpose.
+ """
+
+ def add_footer_part(self):
+ """Return (footer_part, rId) pair for newly-created footer part."""
+ footer_part = FooterPart.new(self.package)
+ rId = self.relate_to(footer_part, RT.FOOTER)
+ return footer_part, rId
+
+ def add_header_part(self):
+ """Return (header_part, rId) pair for newly-created header part."""
+ header_part = HeaderPart.new(self.package)
+ rId = self.relate_to(header_part, RT.HEADER)
+ return header_part, rId
+
+ @property
+ def core_properties(self) -> CoreProperties:
+ """A |CoreProperties| object providing read/write access to the core properties
+ of this document."""
+ return self.package.core_properties
+
+ @property
+ def document(self):
+ """A |Document| object providing access to the content of this document."""
+ return Document(self._element, self)
+
+ def drop_header_part(self, rId: str) -> None:
+ """Remove related header part identified by `rId`."""
+ self.drop_rel(rId)
+
+ def footer_part(self, rId: str):
+ """Return |FooterPart| related by `rId`."""
+ return self.related_parts[rId]
+
+ def get_style(self, style_id: str | None, style_type: WD_STYLE_TYPE) -> BaseStyle:
+ """Return the style in this document matching `style_id`.
+
+ Returns the default style for `style_type` if `style_id` is |None| or does not
+ match a defined style of `style_type`.
+ """
+ return self.styles.get_by_id(style_id, style_type)
+
+ def get_style_id(self, style_or_name, style_type):
+ """Return the style_id (|str|) of the style of `style_type` matching
+ `style_or_name`.
+
+ Returns |None| if the style resolves to the default style for `style_type` or if
+ `style_or_name` is itself |None|. Raises if `style_or_name` is a style of the
+ wrong type or names a style not present in the document.
+ """
+ return self.styles.get_style_id(style_or_name, style_type)
+
+ def header_part(self, rId: str):
+ """Return |HeaderPart| related by `rId`."""
+ return self.related_parts[rId]
+
+ @lazyproperty
+ def inline_shapes(self):
+ """The |InlineShapes| instance containing the inline shapes in the document."""
+ return InlineShapes(self._element.body, self)
+
+ @lazyproperty
+ def numbering_part(self):
+ """A |NumberingPart| object providing access to the numbering definitions for
+ this document.
+
+ Creates an empty numbering part if one is not present.
+ """
+ try:
+ return self.part_related_by(RT.NUMBERING)
+ except KeyError:
+ numbering_part = NumberingPart.new()
+ self.relate_to(numbering_part, RT.NUMBERING)
+ return numbering_part
+
+ def save(self, path_or_stream: str | IO[bytes]):
+ """Save this document to `path_or_stream`, which can be either a path to a
+ filesystem location (a string) or a file-like object."""
+ self.package.save(path_or_stream)
+
+ @property
+ def settings(self) -> Settings:
+ """A |Settings| object providing access to the settings in the settings part of
+ this document."""
+ return self._settings_part.settings
+
+ @property
+ def styles(self):
+ """A |Styles| object providing access to the styles in the styles part of this
+ document."""
+ return self._styles_part.styles
+
+ @property
+ def _settings_part(self) -> SettingsPart:
+ """A |SettingsPart| object providing access to the document-level settings for
+ this document.
+
+ Creates a default settings part if one is not present.
+ """
+ try:
+ return cast(SettingsPart, self.part_related_by(RT.SETTINGS))
+ except KeyError:
+ settings_part = SettingsPart.default(self.package)
+ self.relate_to(settings_part, RT.SETTINGS)
+ return settings_part
+
+ @property
+ def _styles_part(self) -> StylesPart:
+ """Instance of |StylesPart| for this document.
+
+ Creates an empty styles part if one is not present.
+ """
+ try:
+ return cast(StylesPart, self.part_related_by(RT.STYLES))
+ except KeyError:
+ package = self.package
+ assert package is not None
+ styles_part = StylesPart.default(package)
+ self.relate_to(styles_part, RT.STYLES)
+ return styles_part
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/hdrftr.py b/.venv/lib/python3.12/site-packages/docx/parts/hdrftr.py
new file mode 100644
index 00000000..35113801
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/hdrftr.py
@@ -0,0 +1,53 @@
+"""Header and footer part objects."""
+
+from __future__ import annotations
+
+import os
+from typing import TYPE_CHECKING
+
+from docx.opc.constants import CONTENT_TYPE as CT
+from docx.oxml.parser import parse_xml
+from docx.parts.story import StoryPart
+
+if TYPE_CHECKING:
+ from docx.package import Package
+
+
+class FooterPart(StoryPart):
+ """Definition of a section footer."""
+
+ @classmethod
+ def new(cls, package: Package):
+ """Return newly created footer part."""
+ partname = package.next_partname("/word/footer%d.xml")
+ content_type = CT.WML_FOOTER
+ element = parse_xml(cls._default_footer_xml())
+ return cls(partname, content_type, element, package)
+
+ @classmethod
+ def _default_footer_xml(cls):
+ """Return bytes containing XML for a default footer part."""
+ path = os.path.join(os.path.split(__file__)[0], "..", "templates", "default-footer.xml")
+ with open(path, "rb") as f:
+ xml_bytes = f.read()
+ return xml_bytes
+
+
+class HeaderPart(StoryPart):
+ """Definition of a section header."""
+
+ @classmethod
+ def new(cls, package: Package):
+ """Return newly created header part."""
+ partname = package.next_partname("/word/header%d.xml")
+ content_type = CT.WML_HEADER
+ element = parse_xml(cls._default_header_xml())
+ return cls(partname, content_type, element, package)
+
+ @classmethod
+ def _default_header_xml(cls):
+ """Return bytes containing XML for a default header part."""
+ path = os.path.join(os.path.split(__file__)[0], "..", "templates", "default-header.xml")
+ with open(path, "rb") as f:
+ xml_bytes = f.read()
+ return xml_bytes
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/image.py b/.venv/lib/python3.12/site-packages/docx/parts/image.py
new file mode 100644
index 00000000..5aec0707
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/image.py
@@ -0,0 +1,80 @@
+"""The proxy class for an image part, and related objects."""
+
+from __future__ import annotations
+
+import hashlib
+from typing import TYPE_CHECKING
+
+from docx.image.image import Image
+from docx.opc.part import Part
+from docx.shared import Emu, Inches
+
+if TYPE_CHECKING:
+ from docx.opc.package import OpcPackage
+ from docx.opc.packuri import PackURI
+
+
+class ImagePart(Part):
+ """An image part.
+
+ Corresponds to the target part of a relationship with type RELATIONSHIP_TYPE.IMAGE.
+ """
+
+ def __init__(
+ self, partname: PackURI, content_type: str, blob: bytes, image: Image | None = None
+ ):
+ super(ImagePart, self).__init__(partname, content_type, blob)
+ self._image = image
+
+ @property
+ def default_cx(self):
+ """Native width of this image, calculated from its width in pixels and
+ horizontal dots per inch (dpi)."""
+ px_width = self.image.px_width
+ horz_dpi = self.image.horz_dpi
+ width_in_inches = px_width / horz_dpi
+ return Inches(width_in_inches)
+
+ @property
+ def default_cy(self):
+ """Native height of this image, calculated from its height in pixels and
+ vertical dots per inch (dpi)."""
+ px_height = self.image.px_height
+ horz_dpi = self.image.horz_dpi
+ height_in_emu = int(round(914400 * px_height / horz_dpi))
+ return Emu(height_in_emu)
+
+ @property
+ def filename(self):
+ """Filename from which this image part was originally created.
+
+ A generic name, e.g. 'image.png', is substituted if no name is available, for
+ example when the image was loaded from an unnamed stream. In that case a default
+ extension is applied based on the detected MIME type of the image.
+ """
+ if self._image is not None:
+ return self._image.filename
+ return "image.%s" % self.partname.ext
+
+ @classmethod
+ def from_image(cls, image: Image, partname: PackURI):
+ """Return an |ImagePart| instance newly created from `image` and assigned
+ `partname`."""
+ return ImagePart(partname, image.content_type, image.blob, image)
+
+ @property
+ def image(self) -> Image:
+ if self._image is None:
+ self._image = Image.from_blob(self.blob)
+ return self._image
+
+ @classmethod
+ def load(cls, partname: PackURI, content_type: str, blob: bytes, package: OpcPackage):
+ """Called by ``docx.opc.package.PartFactory`` to load an image part from a
+ package being opened by ``Document(...)`` call."""
+ return cls(partname, content_type, blob)
+
+ @property
+ def sha1(self):
+ """SHA1 hash digest of the blob of this image part."""
+ return hashlib.sha1(self.blob).hexdigest()
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/numbering.py b/.venv/lib/python3.12/site-packages/docx/parts/numbering.py
new file mode 100644
index 00000000..54a430c1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/numbering.py
@@ -0,0 +1,33 @@
+"""|NumberingPart| and closely related objects."""
+
+from ..opc.part import XmlPart
+from ..shared import lazyproperty
+
+
+class NumberingPart(XmlPart):
+ """Proxy for the numbering.xml part containing numbering definitions for a document
+ or glossary."""
+
+ @classmethod
+ def new(cls):
+ """Return newly created empty numbering part, containing only the root
+ ``<w:numbering>`` element."""
+ raise NotImplementedError
+
+ @lazyproperty
+ def numbering_definitions(self):
+ """The |_NumberingDefinitions| instance containing the numbering definitions
+ (<w:num> element proxies) for this numbering part."""
+ return _NumberingDefinitions(self._element)
+
+
+class _NumberingDefinitions:
+ """Collection of |_NumberingDefinition| instances corresponding to the ``<w:num>``
+ elements in a numbering part."""
+
+ def __init__(self, numbering_elm):
+ super(_NumberingDefinitions, self).__init__()
+ self._numbering = numbering_elm
+
+ def __len__(self):
+ return len(self._numbering.num_lst)
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/settings.py b/.venv/lib/python3.12/site-packages/docx/parts/settings.py
new file mode 100644
index 00000000..116facca
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/settings.py
@@ -0,0 +1,51 @@
+"""|SettingsPart| and closely related objects."""
+
+from __future__ import annotations
+
+import os
+from typing import TYPE_CHECKING, cast
+
+from docx.opc.constants import CONTENT_TYPE as CT
+from docx.opc.packuri import PackURI
+from docx.opc.part import XmlPart
+from docx.oxml.parser import parse_xml
+from docx.settings import Settings
+
+if TYPE_CHECKING:
+ from docx.oxml.settings import CT_Settings
+ from docx.package import Package
+
+
+class SettingsPart(XmlPart):
+ """Document-level settings part of a WordprocessingML (WML) package."""
+
+ def __init__(
+ self, partname: PackURI, content_type: str, element: CT_Settings, package: Package
+ ):
+ super().__init__(partname, content_type, element, package)
+ self._settings = element
+
+ @classmethod
+ def default(cls, package: Package):
+ """Return a newly created settings part, containing a default `w:settings`
+ element tree."""
+ partname = PackURI("/word/settings.xml")
+ content_type = CT.WML_SETTINGS
+ element = cast("CT_Settings", parse_xml(cls._default_settings_xml()))
+ return cls(partname, content_type, element, package)
+
+ @property
+ def settings(self) -> Settings:
+ """A |Settings| proxy object for the `w:settings` element in this part.
+
+ Contains the document-level settings for this document.
+ """
+ return Settings(self._settings)
+
+ @classmethod
+ def _default_settings_xml(cls):
+ """Return a bytestream containing XML for a default settings part."""
+ path = os.path.join(os.path.split(__file__)[0], "..", "templates", "default-settings.xml")
+ with open(path, "rb") as f:
+ xml_bytes = f.read()
+ return xml_bytes
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/story.py b/.venv/lib/python3.12/site-packages/docx/parts/story.py
new file mode 100644
index 00000000..7482c91a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/story.py
@@ -0,0 +1,95 @@
+"""|StoryPart| and related objects."""
+
+from __future__ import annotations
+
+from typing import IO, TYPE_CHECKING, Tuple, cast
+
+from docx.opc.constants import RELATIONSHIP_TYPE as RT
+from docx.opc.part import XmlPart
+from docx.oxml.shape import CT_Inline
+from docx.shared import Length, lazyproperty
+
+if TYPE_CHECKING:
+ from docx.enum.style import WD_STYLE_TYPE
+ from docx.image.image import Image
+ from docx.parts.document import DocumentPart
+ from docx.styles.style import BaseStyle
+
+
+class StoryPart(XmlPart):
+ """Base class for story parts.
+
+ A story part is one that can contain textual content, such as the document-part and
+ header or footer parts. These all share content behaviors like `.paragraphs`,
+ `.add_paragraph()`, `.add_table()` etc.
+ """
+
+ def get_or_add_image(self, image_descriptor: str | IO[bytes]) -> Tuple[str, Image]:
+ """Return (rId, image) pair for image identified by `image_descriptor`.
+
+ `rId` is the str key (often like "rId7") for the relationship between this story
+ part and the image part, reused if already present, newly created if not.
+ `image` is an |Image| instance providing access to the properties of the image,
+ such as dimensions and image type.
+ """
+ package = self._package
+ assert package is not None
+ image_part = package.get_or_add_image_part(image_descriptor)
+ rId = self.relate_to(image_part, RT.IMAGE)
+ return rId, image_part.image
+
+ def get_style(self, style_id: str | None, style_type: WD_STYLE_TYPE) -> BaseStyle:
+ """Return the style in this document matching `style_id`.
+
+ Returns the default style for `style_type` if `style_id` is |None| or does not
+ match a defined style of `style_type`.
+ """
+ return self._document_part.get_style(style_id, style_type)
+
+ def get_style_id(
+ self, style_or_name: BaseStyle | str | None, style_type: WD_STYLE_TYPE
+ ) -> str | None:
+ """Return str style_id for `style_or_name` of `style_type`.
+
+ Returns |None| if the style resolves to the default style for `style_type` or if
+ `style_or_name` is itself |None|. Raises if `style_or_name` is a style of the
+ wrong type or names a style not present in the document.
+ """
+ return self._document_part.get_style_id(style_or_name, style_type)
+
+ def new_pic_inline(
+ self,
+ image_descriptor: str | IO[bytes],
+ width: int | Length | None = None,
+ height: int | Length | None = None,
+ ) -> CT_Inline:
+ """Return a newly-created `w:inline` element.
+
+ The element contains the image specified by `image_descriptor` and is scaled
+ based on the values of `width` and `height`.
+ """
+ rId, image = self.get_or_add_image(image_descriptor)
+ cx, cy = image.scaled_dimensions(width, height)
+ shape_id, filename = self.next_id, image.filename
+ return CT_Inline.new_pic_inline(shape_id, rId, filename, cx, cy)
+
+ @property
+ def next_id(self) -> int:
+ """Next available positive integer id value in this story XML document.
+
+ The value is determined by incrementing the maximum existing id value. Gaps in
+ the existing id sequence are not filled. The id attribute value is unique in the
+ document, without regard to the element type it appears on.
+ """
+ id_str_lst = self._element.xpath("//@id")
+ used_ids = [int(id_str) for id_str in id_str_lst if id_str.isdigit()]
+ if not used_ids:
+ return 1
+ return max(used_ids) + 1
+
+ @lazyproperty
+ def _document_part(self) -> DocumentPart:
+ """|DocumentPart| object for this package."""
+ package = self.package
+ assert package is not None
+ return cast("DocumentPart", package.main_document_part)
diff --git a/.venv/lib/python3.12/site-packages/docx/parts/styles.py b/.venv/lib/python3.12/site-packages/docx/parts/styles.py
new file mode 100644
index 00000000..dffa762e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/docx/parts/styles.py
@@ -0,0 +1,44 @@
+"""Provides StylesPart and related objects."""
+
+from __future__ import annotations
+
+import os
+from typing import TYPE_CHECKING
+
+from docx.opc.constants import CONTENT_TYPE as CT
+from docx.opc.packuri import PackURI
+from docx.opc.part import XmlPart
+from docx.oxml.parser import parse_xml
+from docx.styles.styles import Styles
+
+if TYPE_CHECKING:
+ from docx.opc.package import OpcPackage
+
+
+class StylesPart(XmlPart):
+ """Proxy for the styles.xml part containing style definitions for a document or
+ glossary."""
+
+ @classmethod
+ def default(cls, package: OpcPackage) -> StylesPart:
+ """Return a newly created styles part, containing a default set of elements."""
+ partname = PackURI("/word/styles.xml")
+ content_type = CT.WML_STYLES
+ element = parse_xml(cls._default_styles_xml())
+ return cls(partname, content_type, element, package)
+
+ @property
+ def styles(self):
+ """The |_Styles| instance containing the styles (<w:style> element proxies) for
+ this styles part."""
+ return Styles(self.element)
+
+ @classmethod
+ def _default_styles_xml(cls):
+ """Return a bytestream containing XML for a default styles part."""
+ path = os.path.join(
+ os.path.split(__file__)[0], "..", "templates", "default-styles.xml"
+ )
+ with open(path, "rb") as f:
+ xml_bytes = f.read()
+ return xml_bytes