From c5821ef1016ae78451ab86ded6f4f07f75a16353 Mon Sep 17 00:00:00 2001 From: "James R. Barlow" Date: Thu, 16 Aug 2018 00:37:30 -0700 Subject: Support syntax: "Name.Foo in dictionary" --- src/qpdf/object.cpp | 24 +++++++++++++++++------- tests/test_object.py | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/qpdf/object.cpp b/src/qpdf/object.cpp index 16778cb..4f99f4c 100644 --- a/src/qpdf/object.cpp +++ b/src/qpdf/object.cpp @@ -273,6 +273,15 @@ bool operator==(const QPDFObjectHandle& self, const QPDFObjectHandle& other) } +bool object_has_key(QPDFObjectHandle& h, std::string const& key) +{ + if (!h.isDictionary() && !h.isStream()) + throw py::value_error("object is not a dictionary or a stream"); + QPDFObjectHandle dict = h.isStream() ? h.getDict() : h; + return dict.hasKey(key); +} + + QPDFObjectHandle object_get_key(QPDFObjectHandle& h, std::string const& key) { if (!h.isDictionary() && !h.isStream()) @@ -516,15 +525,16 @@ void init_object(py::module& m) py::arg("default_") = py::none() ) .def("keys", &QPDFObjectHandle::getKeys) + .def("__contains__", + [](QPDFObjectHandle &h, QPDFObjectHandle &key) { + if (!key.isName()) + throw py::type_error("Dictionaries can only contain Names"); + return object_has_key(h, key.getName()); + } + ) .def("__contains__", [](QPDFObjectHandle &h, std::string const& key) { - if (h.isDictionary()) { - return h.hasKey(key); - } - if (h.isStream()) { - return h.getDict().hasKey(key); - } - throw py::value_error("__contains__ not defined for object type"); + return object_has_key(h, key); } ) .def("as_list", &QPDFObjectHandle::getArrayAsVector) diff --git a/tests/test_object.py b/tests/test_object.py index 601fa07..67d21af 100644 --- a/tests/test_object.py +++ b/tests/test_object.py @@ -160,6 +160,20 @@ def test_name_equality(): assert Name.Foo == Name('/Foo') +def test_dictionary_contains(): + d = Dictionary({ + '/Monty': 'Python', + '/Flying': 'Circus' + }) + assert Name.Flying in d + assert Name('/Monty') in d + assert Name.Brian not in d + + +def test_unslashed_name(): + with pytest.raises(ValueError, match='must begin with'): + Name('Monty') not in d + class TestHashViolation: def check(self, a, b): -- cgit v1.2.3