# Copyright (c) 2010-2024 fastpyxl
from fastpyxl.typed_serialisable.base import Serialisable
from fastpyxl.typed_serialisable.fields import Field
from fastpyxl.xml.functions import Element
from fastpyxl.xml.constants import XPROPS_NS
from fastpyxl import __version__
def _invert_xml_bool(value):
if value is None:
return None
if isinstance(value, bool):
return value
if isinstance(value, str):
return value.lower() not in ("true", "1", "t")
return not bool(value)
def _invert_xml_bool_renderer(tagname, value, namespace=None):
if value is None:
return None
if namespace is not None:
tagname = "{%s}%s" % (namespace, tagname)
el = Element(tagname)
el.text = "false" if value else "true"
return el
[docs]
class DigSigBlob(Serialisable):
__elements__ = __attrs__ = ()
[docs]
class VectorLpstr(Serialisable):
__elements__ = __attrs__ = ()
[docs]
class VectorVariant(Serialisable):
__elements__ = __attrs__ = ()
[docs]
class ExtendedProperties(Serialisable):
"""
See 22.2
Most of this is irrelevant but Excel is very picky about the version number
It uses XX.YYYY (Version.Build) and expects everyone else to
We provide Major.Minor and the full version in the application name
"""
tagname = "Properties"
Template: str | None = Field.nested_text(expected_type=str, allow_none=True, default=None)
Manager: str | None = Field.nested_text(expected_type=str, allow_none=True, default=None)
Company: str | None = Field.nested_text(expected_type=str, allow_none=True, default=None)
Pages: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
Words: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
Characters: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
PresentationFormat: str | None = Field.nested_text(expected_type=str, allow_none=True, default=None)
Lines: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
Paragraphs: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
Slides: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
Notes: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
TotalTime: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
HiddenSlides: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
MMClips: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
ScaleCrop: bool | None = Field.nested_text(
expected_type=bool,
allow_none=True,
converter=_invert_xml_bool,
renderer=_invert_xml_bool_renderer, default=None,
)
HeadingPairs: VectorVariant | None = Field.element(expected_type=VectorVariant, allow_none=True, default=None)
TitlesOfParts: VectorLpstr | None = Field.element(expected_type=VectorLpstr, allow_none=True, default=None)
LinksUpToDate: bool | None = Field.nested_text(
expected_type=bool,
allow_none=True,
converter=_invert_xml_bool,
renderer=_invert_xml_bool_renderer, default=None,
)
CharactersWithSpaces: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
SharedDoc: bool | None = Field.nested_text(
expected_type=bool,
allow_none=True,
converter=_invert_xml_bool,
renderer=_invert_xml_bool_renderer, default=None,
)
HyperlinkBase: str | None = Field.nested_text(expected_type=str, allow_none=True, default=None)
HLinks: VectorVariant | None = Field.element(expected_type=VectorVariant, allow_none=True, default=None)
HyperlinksChanged: bool | None = Field.nested_text(
expected_type=bool,
allow_none=True,
converter=_invert_xml_bool,
renderer=_invert_xml_bool_renderer, default=None,
)
DigSig: DigSigBlob | None = Field.element(expected_type=DigSigBlob, allow_none=True, default=None)
Application: str | None = Field.nested_text(expected_type=str, allow_none=True, default=None)
AppVersion: str | None = Field.nested_text(expected_type=str, allow_none=True, default=None)
DocSecurity: int | None = Field.nested_text(expected_type=int, allow_none=True, default=None)
xml_order = ('Application', 'AppVersion', 'DocSecurity', 'ScaleCrop',
'LinksUpToDate', 'SharedDoc', 'HyperlinksChanged')
def __init__(self,
Template=None,
Manager=None,
Company=None,
Pages=None,
Words=None,
Characters=None,
PresentationFormat=None,
Lines=None,
Paragraphs=None,
Slides=None,
Notes=None,
TotalTime=None,
HiddenSlides=None,
MMClips=None,
ScaleCrop=None,
HeadingPairs=None,
TitlesOfParts=None,
LinksUpToDate=None,
CharactersWithSpaces=None,
SharedDoc=None,
HyperlinkBase=None,
HLinks=None,
HyperlinksChanged=None,
DigSig=None,
Application=None,
AppVersion=None,
DocSecurity=None,
):
self.Template = Template
self.Manager = Manager
self.Company = Company
self.Pages = Pages
self.Words = Words
self.Characters = Characters
self.PresentationFormat = PresentationFormat
self.Lines = Lines
self.Paragraphs = Paragraphs
self.Slides = Slides
self.Notes = Notes
self.TotalTime = TotalTime
self.HiddenSlides = HiddenSlides
self.MMClips = MMClips
self.ScaleCrop = ScaleCrop
self.HeadingPairs = HeadingPairs
self.TitlesOfParts = TitlesOfParts
self.LinksUpToDate = LinksUpToDate
self.CharactersWithSpaces = CharactersWithSpaces
self.SharedDoc = SharedDoc
self.HyperlinkBase = HyperlinkBase
self.HLinks = HLinks
self.HyperlinksChanged = HyperlinksChanged
self.DigSig = DigSig
if Application is None:
self.Application = f"Microsoft Excel Compatible / fastpyxl {__version__}"
else:
self.Application = Application
if AppVersion is None:
self.AppVersion = ".".join(__version__.split(".")[:-1])
else:
self.AppVersion = AppVersion
self.DocSecurity = DocSecurity
[docs]
def to_tree(self):
tree = super().to_tree()
tree.set("xmlns", XPROPS_NS)
return tree