diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index f0bc1df..492f174 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: python-version: [3.7, 3.8] - poppler-version: [ubuntu, poppler-20.08.0, master] + poppler-version: [ubuntu, poppler-0.26.0, poppler-20.08.0, master] steps: - uses: actions/checkout@v2 @@ -28,9 +28,13 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - sudo apt-get install libpoppler-cpp-dev libopenjp2-7-dev + sudo apt-get install libopenjp2-7-dev python -m pip install --upgrade pip pip install tox + - name: Install libpoppler-cpp-dev + if: matrix.poppler-version == 'ubuntu' + run: | + sudo apt-get install libpoppler-cpp-dev - name: clone poppler if: matrix.poppler-version != 'ubuntu' run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index bb132ee..936467d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ add_subdirectory(pybind11) find_package(PkgConfig REQUIRED) -pkg_check_modules(POPPLER REQUIRED IMPORTED_TARGET poppler-cpp>=0.62.0) +pkg_check_modules(POPPLER REQUIRED IMPORTED_TARGET poppler-cpp>=0.26.0) add_library(global_ MODULE src/cpp/global.cpp) target_link_libraries(global_ PRIVATE pybind11::module PkgConfig::POPPLER ) diff --git a/docs/installation.rst b/docs/installation.rst index 94dcaa7..73c4b6b 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -12,7 +12,7 @@ This package is currently distributed as source only, and is currently tested on Linux only (using Arch Linux on my personal machine, and Ubuntu 18.04 using GitHub actions. -It requires poppler version 0.62 or higher. +It requires poppler version 0.26 or higher. Current poppler version is 0.89. Because we need to compile and link cpp files, you need the headers files for poppler and for python. diff --git a/src/cpp/document.cpp b/src/cpp/document.cpp index b7f0b2a..811174e 100644 --- a/src/cpp/document.cpp +++ b/src/cpp/document.cpp @@ -107,16 +107,20 @@ PYBIND11_MODULE(document, m) .def("create_toc", &document::create_toc) .def("embedded_files", &document::embedded_files) .def("fonts", &document::fonts) +#if HAS_VERSION(0, 46) .def("get_author", &document::get_author) .def("get_creation_date", &document::get_creation_date) .def("get_creator", &document::get_creator) .def("get_keywords", &document::get_keywords) .def("get_modification_date", &document::get_modification_date) +#endif .def("get_pdf_id", &binding::pdf_id) .def("get_pdf_version", &binding::pdf_version) +#if HAS_VERSION(0, 46) .def("get_producer", &document::get_producer) .def("get_subject", &document::get_subject) .def("get_title", &document::get_title) +#endif .def("has_embedded_files", &document::has_embedded_files) .def("has_permission", &document::has_permission, py::arg("which")) .def("info_date", &document::info_date, py::arg("key")) @@ -129,6 +133,7 @@ PYBIND11_MODULE(document, m) .def("page_layout", &document::page_layout) .def("page_mode", &document::page_mode) .def("pages", &document::pages) +#if HAS_VERSION(0, 46) .def("remove_info", &document::remove_info) .def("save", &document::save, py::arg("file_name")) .def("save_a_copy", &document::save_a_copy, py::arg("file_name")) @@ -142,6 +147,7 @@ PYBIND11_MODULE(document, m) .def("set_producer", &document::set_producer, py::arg("producer")) .def("set_subject", &document::set_subject, py::arg("subject")) .def("set_title", &document::set_title, py::arg("title")) +#endif .def("unlock", &document::unlock, py::arg("owner_password"), py::arg("user_password")); m.def("load_from_data", &binding::load_from_data, py::arg("file_data"), py::arg("owner_password") = "", py::arg("user_password") = ""); diff --git a/src/poppler/document.py b/src/poppler/document.py index 7d6f497..5c671cb 100644 --- a/src/poppler/document.py +++ b/src/poppler/document.py @@ -72,43 +72,46 @@ def create_page(self, index): @property @ensure_unlocked def author(self): - return str(self._document.get_author()) + return self.info_key("Author") @author.setter + @since(0, 46) @ensure_unlocked def author(self, author): - self._document.set_author(ustring(author)) + self.set_info_key("Author", author) @property @ensure_unlocked def creation_date(self): - timestamp = self._document.get_creation_date() - return from_time_type(timestamp) + return self.info_date("CreationDate") @creation_date.setter + @since(0, 46) @ensure_unlocked def creation_date(self, creation_date): - self._document.set_creation_date(to_time_type(creation_date)) + self.set_info_date("CreationDate", creation_date) @property @ensure_unlocked def creator(self): - return str(self._document.get_creator()) + return self.info_key("Creator") @creator.setter + @since(0, 46) @ensure_unlocked def creator(self, creator): - self._document.set_creator(ustring(creator)) + self.set_info_key("Creator", creator) @property @ensure_unlocked def keywords(self): - return str(self._document.get_keywords()) + return self.info_key("Keywords") @keywords.setter + @since(0, 46) @ensure_unlocked def keywords(self, keywords): - self._document.set_keywords(ustring(keywords)) + self.set_info_key("Keywords", keywords) @property @ensure_unlocked @@ -119,13 +122,13 @@ def metadata(self): @property @ensure_unlocked def modification_date(self): - timestamp = self._document.get_modification_date() - return from_time_type(timestamp) + return self.info_date("ModDate") @modification_date.setter + @since(0, 46) @ensure_unlocked def modification_date(self, modification_date): - self._document.set_modification_date(to_time_type(modification_date)) + self.set_info_date("ModDate", modification_date) @property def pdf_id(self): @@ -138,32 +141,35 @@ def pdf_version(self): @property @ensure_unlocked def producer(self): - return str(self._document.get_producer()) + return self.info_key("Producer") @producer.setter + @since(0, 46) @ensure_unlocked def producer(self, producer): - self._document.set_producer(ustring(producer)) + self.set_info_key("Producer", producer) @property @ensure_unlocked def subject(self): - return str(self._document.get_subject()) + return self.info_key("Subject") @subject.setter + @since(0, 46) @ensure_unlocked def subject(self, subject): - self._document.set_subject(ustring(subject)) + self.set_info_key("Subject", subject) @property @ensure_unlocked def title(self): - return str(self._document.get_title()) + return self.info_key("Title") @title.setter + @since(0, 46) @ensure_unlocked def title(self, title): - self._document.set_title(ustring(title)) + self.set_info_key("Title", title) @property @ensure_unlocked @@ -198,6 +204,7 @@ def info_date(self, key): timestamp = self._document.info_date(key) return from_time_type(timestamp) + @since(0, 46) @ensure_unlocked def set_info_date(self, key, val): return self._document.set_info_date(key, to_time_type(val)) @@ -218,6 +225,7 @@ def infos(self): info_dict[key] = self.info_key(key) return info_dict + @since(0, 46) @ensure_unlocked def set_info_key(self, key, val): return self._document.set_info_key(key, ustring(val)) @@ -245,14 +253,17 @@ def page_layout(self): def page_mode(self): return self._document.page_mode() + @since(0, 46) @ensure_unlocked def remove_info(self): return self._document.remove_info() + @since(0, 46) @ensure_unlocked def save(self, file_name): return self._document.save(str(file_name)) + @since(0, 46) @ensure_unlocked def save_a_copy(self, file_name): return self._document.save_a_copy(str(file_name)) diff --git a/tests/test_document.py b/tests/test_document.py index c38f4a5..5e833d7 100644 --- a/tests/test_document.py +++ b/tests/test_document.py @@ -33,29 +33,44 @@ def locked_document(data_path): def test_load_from_data(data_path): file_data = (data_path / "document.pdf").read_bytes() pdf_document = document.load_from_data(file_data, "owner", "user") - assert pdf_document.author == "Charles Brunet" + if version() < (0, 46, 0): + assert pdf_document.author == "Charles" + else: + assert pdf_document.author == "Charles Brunet" def test_load_with_path(data_path): pdf_document = document.load(data_path / "document.pdf", "owner", "user") - assert pdf_document.author == "Charles Brunet" + if version() < (0, 46, 0): + assert pdf_document.author == "Charles" + else: + assert pdf_document.author == "Charles Brunet" def test_load_with_filename(data_path): pdf_document = document.load(str(data_path / "document.pdf"), "owner", "user") - assert pdf_document.author == "Charles Brunet" + if version() < (0, 46, 0): + assert pdf_document.author == "Charles" + else: + assert pdf_document.author == "Charles Brunet" def test_load_with_bytes(data_path): data = (data_path / "document.pdf").read_bytes() pdf_document = document.load(data, "owner", "user") - assert pdf_document.author == "Charles Brunet" + if version() < (0, 46, 0): + assert pdf_document.author == "Charles" + else: + assert pdf_document.author == "Charles Brunet" def test_load_with_file(data_path): with (data_path / "document.pdf").open("rb") as f: pdf_document = document.load(f, "owner", "user") - assert pdf_document.author == "Charles Brunet" + if version() < (0, 46, 0): + assert pdf_document.author == "Charles" + else: + assert pdf_document.author == "Charles Brunet" def test_load_with_file_not_bytes(data_path): @@ -69,6 +84,7 @@ def test_load_with_invalid_type(): document.load(42) +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_save(pdf_document, tmp_path): copy_document = tmp_path / "copy.pdf" pdf_document.author = "Valérie Tremblay" @@ -78,6 +94,7 @@ def test_save(pdf_document, tmp_path): assert pdf_copy.author == "Valérie Tremblay" +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_save_a_copy(pdf_document, tmp_path): copy_document = tmp_path / "copy.pdf" pdf_document.author = "Valérie Tremblay" @@ -96,17 +113,30 @@ def test_embedded_file(pdf_document): def test_get_author(pdf_document): - assert pdf_document.author == "Charles Brunet" + if version() < (0, 46, 0): + assert pdf_document.author == "Charles" + else: + assert pdf_document.author == "Charles Brunet" def test_get_creation_date(pdf_document): - assert pdf_document.creation_date.astimezone(timezone.utc) == datetime( - 2020, 3, 26, 1, 19, 50, tzinfo=timezone.utc - ) + date = pdf_document.creation_date + + if version() < (0, 46, 0): + assert date.astimezone(timezone.utc) == datetime( + 2020, 3, 25, 21, 19, 50, tzinfo=timezone.utc + ) + else: + assert date.astimezone(timezone.utc) == datetime( + 2020, 3, 26, 1, 19, 50, tzinfo=timezone.utc + ) def test_get_creator(pdf_document): - assert pdf_document.creator == "Writer" + if version() < (0, 46, 0): + assert pdf_document.creator == "Wri" + else: + assert pdf_document.creator == "Writer" def test_get_keywords(pdf_document): @@ -129,7 +159,10 @@ def test_get_pdf_version(pdf_document): def test_get_producer(pdf_document): - assert pdf_document.producer == "LibreOffice 6.4" + if version() < (0, 46, 0): + assert pdf_document.producer == "LibreOf" + else: + assert pdf_document.producer == "LibreOffice 6.4" def test_get_subject(pdf_document): @@ -158,14 +191,22 @@ def test_has_permission(pdf_document): def test_info_date(pdf_document): date = pdf_document.info_date("CreationDate") - assert date.astimezone(timezone.utc) == datetime( - 2020, 3, 26, 1, 19, 50, tzinfo=timezone.utc - ) + if version() < (0, 46, 0): + assert date.astimezone(timezone.utc) == datetime( + 2020, 3, 25, 21, 19, 50, tzinfo=timezone.utc + ) + else: + assert date.astimezone(timezone.utc) == datetime( + 2020, 3, 26, 1, 19, 50, tzinfo=timezone.utc + ) def test_info_key(pdf_document): info = pdf_document.info_key("Author") - assert info == "Charles Brunet" + if version() < (0, 46, 0): + assert info == "Charles" + else: + assert info == "Charles Brunet" def test_info_keys(pdf_document): @@ -190,65 +231,76 @@ def test_metadata(pdf_document): assert meta == "" +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_author(pdf_document): author = "Valérie Tremblay" pdf_document.author = author assert pdf_document.author == author +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_creation_date(pdf_document): d = datetime(1980, 7, 19, 10, 30, 50) pdf_document.creation_date = d assert pdf_document.creation_date == d +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_empty_creation_date(pdf_document): pdf_document.creation_date = None assert "CreationDate" not in pdf_document.info_keys() +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_creator(pdf_document): creator = "Me" pdf_document.creator = creator assert pdf_document.creator == creator +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_keywords(pdf_document): keywords = "one, two, three" pdf_document.keywords = keywords assert pdf_document.keywords == keywords +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_modification_date(pdf_document): d = datetime(1980, 7, 19, 10, 30, 50) pdf_document.modification_date = d assert pdf_document.modification_date == d +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_producer(pdf_document): producer = "Me" pdf_document.producer = producer assert pdf_document.producer == producer +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_subject(pdf_document): subject = "Me" pdf_document.subject = subject assert pdf_document.subject == subject +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_title(pdf_document): title = "The document title" pdf_document.title = title assert pdf_document.title == title +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_info_date(pdf_document): d = datetime(1980, 7, 19, 10, 30, 50) assert pdf_document.set_info_date("CreationDate", d) is True assert pdf_document.creation_date == d +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_set_info_key(pdf_document): author = "Valérie Tremblay" assert pdf_document.set_info_key("Author", author) is True @@ -257,9 +309,13 @@ def test_set_info_key(pdf_document): def test_infos(pdf_document): infos = pdf_document.infos() - assert infos["Author"] == "Charles Brunet" + if version() < (0, 46, 0): + assert infos['Author'] == 'Charles' + else: + assert infos["Author"] == "Charles Brunet" +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_remove_info(pdf_document): pdf_document.remove_info() assert not pdf_document.infos() diff --git a/tests/test_page.py b/tests/test_page.py index b698f34..64320cb 100644 --- a/tests/test_page.py +++ b/tests/test_page.py @@ -27,6 +27,7 @@ def test_page_duration(pdf_page): assert pdf_page.duration == -1.0 +@pytest.mark.skipif(version() < (0, 46, 0), reason="Requires at least Poppler 0.46.0") def test_page_label(pdf_page): assert pdf_page.label == "1" @@ -57,7 +58,12 @@ def test_page_rect_box(pdf_page, box): def test_text(pdf_page): text = pdf_page.text() - expected = "Page 1" if version() < (0, 88, 0) else "Page 1\n\x0c" + if version() < (0, 46, 0): + expected = "Page " + elif version() < (0, 88, 0): + expected = "Page 1" + else: + expected = "Page 1\n\x0c" assert text == expected