Source code for pdfnaut.cos.objects.containers
from __future__ import annotations
from collections import UserDict, UserList
from typing import SupportsIndex, cast, overload
from typing_extensions import TypeVar
from ...exceptions import PdfResolutionError
from .base import PdfObject, PdfReference
DictKey = TypeVar("DictKey", default=str, infer_variance=True)
DictVal = TypeVar("DictVal", default=PdfObject, infer_variance=True)
[docs]
class PdfDictionary(UserDict[DictKey, DictVal]):
"""An associative table containing pairs of objects or entries where each entry is
composed of a key which is a name object and a value which is any PDF object
(see ISO 32000-2:2020 § 7.3.7 "Dictionary objects").
:class:`PdfDictionary` is effectively a Python dictionary. Its keys are strings and
its values are any PDF object. The main difference from a typical dictionary is that
PdfDictionary automatically resolves references on key access.
The underlying data in unresolved form is stored in :attr:`.PdfDictionary.data`.
"""
def __getitem__(self, key: DictKey) -> DictVal:
item = self.data[key]
if isinstance(item, PdfReference):
try:
return cast(DictVal, item.get())
except PdfResolutionError:
pass
return cast(DictVal, item)
def __setitem__(self, key: DictKey, value: DictVal | PdfReference[DictVal]) -> None:
self.data[key] = cast(DictVal, value)
def __hash__(self) -> int:
return hash((self.__class__, tuple(hash(v) for v in self.data.items())))
ArrVal = TypeVar("ArrVal", default=PdfObject)
[docs]
class PdfArray(UserList[ArrVal]):
"""A heterogeneous collection of sequentially arranged items (see ISO 32000-2:2020
§ 7.3.6 "Array objects").
:class:`PdfArray` is effectively a Python list. The main difference from a typical list
is that PdfArray automatically resolves references when indexing.
The underlying data in unresolved form is stored in :attr:`.PdfArray.data`.
"""
@overload
def __getitem__(self, i: SupportsIndex) -> ArrVal: ...
@overload
def __getitem__(self, i: slice) -> PdfArray[ArrVal]: ...
def __getitem__(self, i: SupportsIndex | slice) -> ArrVal | PdfArray[ArrVal]:
item = self.data[i]
if isinstance(i, slice):
return PdfArray(cast(list[ArrVal], item))
if isinstance(item, PdfReference):
try:
return cast(ArrVal, item.get())
except PdfResolutionError:
pass
return cast(ArrVal, item)
def __hash__(self) -> int: # type: ignore -- our arrays are hashable!
return hash((self.__class__, tuple(hash(v) for v in self.data)))