summaryrefslogtreecommitdiff
path: root/pdfrw/objects/pdfdict.py
diff options
context:
space:
mode:
Diffstat (limited to 'pdfrw/objects/pdfdict.py')
-rw-r--r--pdfrw/objects/pdfdict.py84
1 files changed, 56 insertions, 28 deletions
diff --git a/pdfrw/objects/pdfdict.py b/pdfrw/objects/pdfdict.py
index 1b3f6a0..fc28492 100644
--- a/pdfrw/objects/pdfdict.py
+++ b/pdfrw/objects/pdfdict.py
@@ -1,18 +1,24 @@
-# A part of pdfrw (pdfrw.googlecode.com)
-# Copyright (C) 2006-2012 Patrick Maupin, Austin, Texas
+# A part of pdfrw (https://github.com/pmaupin/pdfrw)
+# Copyright (C) 2006-2015 Patrick Maupin, Austin, Texas
# MIT license -- See LICENSE.txt for details
-from pdfrw.objects.pdfname import PdfName
-from pdfrw.objects.pdfindirect import PdfIndirect
-from pdfrw.objects.pdfobject import PdfObject
+from .pdfname import PdfName, BasePdfName
+from .pdfindirect import PdfIndirect
+from .pdfobject import PdfObject
+from ..py23_diffs import iteritems
+from ..errors import PdfParseError
+
class _DictSearch(object):
''' Used to search for inheritable attributes.
'''
+
def __init__(self, basedict):
self.basedict = basedict
+
def __getattr__(self, name, PdfName=PdfName):
return self[PdfName(name)]
+
def __getitem__(self, name, set=set, getattr=getattr, id=id):
visited = set()
mydict = self.basedict
@@ -27,28 +33,35 @@ class _DictSearch(object):
if mydict is None:
return
+
class _Private(object):
''' Used to store private attributes (not output to PDF files)
on PdfDict classes
'''
+
def __init__(self, pdfdict):
vars(self)['pdfdict'] = pdfdict
+
def __setattr__(self, name, value):
vars(self.pdfdict)[name] = value
+
class PdfDict(dict):
- ''' PdfDict objects are subclassed dictionaries with the following features:
+ ''' PdfDict objects are subclassed dictionaries
+ with the following features:
- Every key in the dictionary starts with "/"
- A dictionary item can be deleted by assigning it to None
- - Keys that (after the initial "/") conform to Python naming conventions
- can also be accessed (set and retrieved) as attributes of the dictionary.
- E.g. mydict.Page is the same thing as mydict['/Page']
+ - Keys that (after the initial "/") conform to Python
+ naming conventions can also be accessed (set and retrieved)
+ as attributes of the dictionary. E.g. mydict.Page is the
+ same thing as mydict['/Page']
- - Private attributes (not in the PDF space) can be set on the dictionary
- object attribute dictionary by using the private attribute:
+ - Private attributes (not in the PDF space) can be set
+ on the dictionary object attribute dictionary by using
+ the private attribute:
mydict.private.foo = 3
mydict.foo = 5
@@ -61,11 +74,11 @@ class PdfDict(dict):
- PdfDicts have the following read-only properties:
- - private -- as discussed above, provides write access to dictionary's
- attributes
- - inheritable -- this creates and returns a "view" attribute that
- will search through the object hierarchy for any desired
- attribute, such as /Rotate or /MediaBox
+ - private -- as discussed above, provides write access to
+ dictionary's attributes
+ - inheritable -- this creates and returns a "view" attribute
+ that will search through the object hierarchy for
+ any desired attribute, such as /Rotate or /MediaBox
- PdfDicts also have the following special attributes:
- indirect is not stored in the PDF dictionary, but in the object's
@@ -84,13 +97,15 @@ class PdfDict(dict):
indirect = False
stream = None
- _special = dict(indirect = ('indirect', False),
- stream = ('stream', True),
- _stream = ('stream', False),
- )
+ _special = dict(indirect=('indirect', False),
+ stream=('stream', True),
+ _stream=('stream', False),
+ )
- def __setitem__(self, name, value, setter=dict.__setitem__):
- assert name.startswith('/'), name
+ def __setitem__(self, name, value, setter=dict.__setitem__,
+ BasePdfName=BasePdfName, isinstance=isinstance):
+ if not isinstance(name, BasePdfName):
+ raise PdfParseError('Dict key %s is not a PdfName' % repr(name))
if value is not None:
setter(self, name, value)
elif name in self:
@@ -104,7 +119,7 @@ class PdfDict(dict):
if isinstance(args, PdfDict):
self.indirect = args.indirect
self._stream = args.stream
- for key, value in kw.iteritems():
+ for key, value in iteritems(kw):
setattr(self, key, value)
def __getattr__(self, name, PdfName=PdfName):
@@ -114,8 +129,10 @@ class PdfDict(dict):
'''
return self.get(PdfName(name))
- def get(self, key, dictget=dict.get, isinstance=isinstance, PdfIndirect=PdfIndirect):
- ''' Get a value out of the dictionary, after resolving any indirect objects.
+ def get(self, key, dictget=dict.get, isinstance=isinstance,
+ PdfIndirect=PdfIndirect):
+ ''' Get a value out of the dictionary,
+ after resolving any indirect objects.
'''
value = dictget(self, key)
if isinstance(value, PdfIndirect):
@@ -125,7 +142,8 @@ class PdfDict(dict):
def __getitem__(self, key):
return self.get(key)
- def __setattr__(self, name, value, special=_special.get, PdfName=PdfName, vars=vars):
+ def __setattr__(self, name, value, special=_special.get,
+ PdfName=PdfName, vars=vars):
''' Set an attribute on the dictionary. Handle the keywords
indirect, stream, and _stream specially (for content objects)
'''
@@ -139,28 +157,37 @@ class PdfDict(dict):
notnone = value is not None
self.Length = notnone and PdfObject(len(value)) or None
- def iteritems(self, dictiter=dict.iteritems, isinstance=isinstance, PdfIndirect=PdfIndirect):
+ def iteritems(self, dictiter=iteritems,
+ isinstance=isinstance, PdfIndirect=PdfIndirect,
+ BasePdfName=BasePdfName):
''' Iterate over the dictionary, resolving any unresolved objects
'''
for key, value in list(dictiter(self)):
if isinstance(value, PdfIndirect):
self[key] = value = value.real_value()
if value is not None:
- assert key.startswith('/'), (key, value)
+ if not isinstance(key, BasePdfName):
+ raise PdfParseError('Dict key %s is not a PdfName' %
+ repr(key))
yield key, value
def items(self):
return list(self.iteritems())
+
def itervalues(self):
for key, value in self.iteritems():
yield value
+
def values(self):
return list((value for key, value in self.iteritems()))
+
def keys(self):
return list((key for key, value in self.iteritems()))
+
def __iter__(self):
for key, value in self.iteritems():
yield key
+
def iterkeys(self):
return iter(self)
@@ -197,6 +224,7 @@ class PdfDict(dict):
return _Private(self)
private = property(private)
+
class IndirectPdfDict(PdfDict):
''' IndirectPdfDict is a convenience class. You could
create a direct PdfDict and then set indirect = True on it,