summaryrefslogtreecommitdiff
path: root/src/pikepdf/objects.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/pikepdf/objects.py')
-rw-r--r--src/pikepdf/objects.py49
1 files changed, 33 insertions, 16 deletions
diff --git a/src/pikepdf/objects.py b/src/pikepdf/objects.py
index a888b97..2e42eb9 100644
--- a/src/pikepdf/objects.py
+++ b/src/pikepdf/objects.py
@@ -8,24 +8,33 @@
The purpose of these is to provide nice-looking classes to allow explicit
construction of PDF objects and more pythonic idioms and facilitate discovery
-by documentation generators.
+by documentation generators and linters.
It's also a place to narrow the scope of input types to those more easily
converted to C++.
-In reality all of these return objects of class pikepdf.Object or rather
-QPDFObjectHandle which is a generic type.
-
+There is some deliberate "smoke and mirrors" here: all of the objects are truly
+instances of ``pikepdf.Object``, which is a variant container object. The
+``__new__`` constructs a ``pikepdf.Object`` in each case, and the rest of the
+class definition is present as an aide for code introspection.
"""
from . import _qpdf
-from ._qpdf import Object, ObjectType
-# pylint: disable=unused-import
-from ._qpdf import Operator
+# pylint: disable=unused-import, abstract-method
+from ._qpdf import Object, ObjectType, Operator
+
+# By default pikepdf.Object will identify itself as pikepdf._qpdf.Object
+# Here we change the module to discourage people from using that internal name
+# Instead it will become pikepdf.objects.Object
+Object.__module__ = __name__
+ObjectType.__module__ = __name__
+Operator.__module__ = __name__
-class _ObjectMeta(type):
+
+# type(Object) is the metaclass that pybind11 defines; we wish to extend that
+class _ObjectMeta(type(Object)):
"""Supports instance checking"""
def __instancecheck__(cls, instance):
@@ -38,9 +47,13 @@ class _NameObjectMeta(_ObjectMeta):
"""Supports usage pikepdf.Name.Whatever -> Name('/Whatever')"""
def __getattr__(self, attr):
+ if attr.startswith('_'):
+ return _ObjectMeta.__getattr__(attr)
return Name('/' + attr)
- def __setattr__(self, name, value):
+ def __setattr__(self, attr, value):
+ if attr.startswith('_'):
+ return _ObjectMeta.__setattr__(attr, value)
raise TypeError("Attributes may not be set on pikepdf.Name")
def __getitem__(self, item):
@@ -56,7 +69,7 @@ class _NameObjectMeta(_ObjectMeta):
)
-class Name(metaclass=_NameObjectMeta):
+class Name(Object, metaclass=_NameObjectMeta):
"""Constructs a PDF Name object
Names can be constructed with two notations:
@@ -69,6 +82,7 @@ class Name(metaclass=_NameObjectMeta):
that are normally expected to be in a PDF. The latter is preferred for
dynamic names and attributes.
"""
+
object_type = ObjectType.name
def __new__(cls, name):
@@ -79,8 +93,9 @@ class Name(metaclass=_NameObjectMeta):
return _qpdf._new_name(name)
-class String(metaclass=_ObjectMeta):
+class String(Object, metaclass=_ObjectMeta):
"""Constructs a PDF String object"""
+
object_type = ObjectType.string
def __new__(cls, s):
@@ -97,8 +112,9 @@ class String(metaclass=_ObjectMeta):
return _qpdf._new_string_utf8(s)
-class Array(metaclass=_ObjectMeta):
+class Array(Object, metaclass=_ObjectMeta):
"""Constructs a PDF Array object"""
+
object_type = ObjectType.array
def __new__(cls, a=None):
@@ -118,8 +134,9 @@ class Array(metaclass=_ObjectMeta):
return _qpdf._new_array(a)
-class Dictionary(metaclass=_ObjectMeta):
+class Dictionary(Object, metaclass=_ObjectMeta):
"""Constructs a PDF Dictionary object"""
+
object_type = ObjectType.dictionary
def __new__(cls, d=None, **kwargs):
@@ -147,15 +164,15 @@ class Dictionary(metaclass=_ObjectMeta):
if kwargs:
# Add leading slash
# Allows Dictionary(MediaBox=(0,0,1,1), Type=Name('/Page')...
- return _qpdf._new_dictionary(
- {('/' + k) : v for k, v in kwargs.items()})
+ return _qpdf._new_dictionary({('/' + k): v for k, v in kwargs.items()})
if not d:
d = {}
return _qpdf._new_dictionary(d)
-class Stream(metaclass=_ObjectMeta):
+class Stream(Object, metaclass=_ObjectMeta):
"""Constructs a PDF Stream object"""
+
object_type = ObjectType.stream
def __new__(cls, owner, obj):