diff --git a/.coveragerc b/.coveragerc index e7dfb5f..9fdbdf2 100644 --- a/.coveragerc +++ b/.coveragerc @@ -4,5 +4,3 @@ branch = true [report] show_missing = true exclude_lines = # no coverage - -# vim:ft=dosini diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 90e05c4..5ace460 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,6 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - version: 2 updates: - - package-ecosystem: "github-actions" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: "github-actions" + directory: "/" schedule: interval: "weekly" diff --git a/.github/workflows/check-for-updates.yml b/.github/workflows/check-for-updates.yml index 05ba75b..f743e31 100644 --- a/.github/workflows/check-for-updates.yml +++ b/.github/workflows/check-for-updates.yml @@ -24,5 +24,3 @@ jobs: - name: check for Boost updates run: ./private/check-new-boost-release - -# vim:ts=2 sts=2 sw=2 et diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a64433..02e35b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,5 +192,3 @@ jobs: run: | cd / man 1 didjvu | grep -A 10 -w DIDJVU - -# vim:ts=2 sts=2 sw=2 et diff --git a/.pylintrc b/.pylintrc index c167ba3..4e81665 100644 --- a/.pylintrc +++ b/.pylintrc @@ -28,5 +28,3 @@ min-similarity-lines = 8 max-line-length = 140 expected-line-ending-format = LF -# vim:ft=dosini ts=4 sts=4 sw=4 et - diff --git a/Makefile b/Makefile index 635831f..4415650 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ # Copyright © 2012-2019 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -45,5 +46,3 @@ clean: rm -f *.tmp .error = GNU make is required - -# vim:ts=4 sts=4 sw=4 noet diff --git a/didjvu/__init__.py b/didjvu/__init__.py index 5fef26f..d994947 100644 --- a/didjvu/__init__.py +++ b/didjvu/__init__.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2009-2021 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -16,5 +15,3 @@ """ didjvu's private modules """ - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/__main__.py b/didjvu/__main__.py index db563a6..900ce03 100644 --- a/didjvu/__main__.py +++ b/didjvu/__main__.py @@ -1,8 +1,20 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- +# Copyright © 2022-2024 FriedrichFroebel +# +# This file is part of didjvu. +# +# didjvu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# didjvu is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +from typing import Optional -def main(prog=None): + +def main(prog: Optional[str] = None) -> None: from didjvu.didjvu import Main Main(prog=prog) diff --git a/didjvu/cli.py b/didjvu/cli.py index 2eff09b..ec71040 100644 --- a/didjvu/cli.py +++ b/didjvu/cli.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2009-2021 Jakub Wilk +# Copyright © 2009-2023 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -363,6 +362,7 @@ def dump_options(options, multi_page=False): yield f'{layer_name}-subsample', layer.subsample -__all__ = ['ArgumentParser', 'dump_options'] - -# vim:ts=4 sts=4 sw=4 et +__all__ = [ + 'ArgumentParser', + 'dump_options' +] diff --git a/didjvu/didjvu.py b/didjvu/didjvu.py index 88152fd..33a889f 100644 --- a/didjvu/didjvu.py +++ b/didjvu/didjvu.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2009-2021 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -21,6 +20,7 @@ import logging import os import sys +from typing import Any, Dict, Tuple from didjvu import cli from didjvu import djvu_support @@ -34,18 +34,18 @@ from didjvu import xmp -def setup_logging(): +def setup_logging() -> Tuple[logging.Logger, logging.Logger]: logger = logging.getLogger('didjvu.main') ipc_logger = logging.getLogger('didjvu.ipc') - logging.NOSY = (logging.INFO + logging.DEBUG) // 2 + logging.NOSY = (logging.INFO + logging.DEBUG) // 2 # type: ignore[attr-defined] # noinspection PyUnresolvedReferences - assert logging.INFO > logging.NOSY > logging.DEBUG + assert logging.INFO > logging.NOSY > logging.DEBUG # type: ignore[attr-defined] - def nosy(msg, *args, **kwargs): + def nosy(msg: str, *args: Any, **kwargs: Any): # noinspection PyUnresolvedReferences - logger.log(logging.NOSY, msg, *args, **kwargs) + logger.log(logging.NOSY, msg, *args, **kwargs) # type: ignore[attr-defined] - logger.nosy = nosy + logger.nosy = nosy # type: ignore[attr-defined] # Main handler: handler = logging.StreamHandler() formatter = logging.Formatter('%(message)s') @@ -63,7 +63,7 @@ def nosy(msg, *args, **kwargs): LOGGER, IPC_LOGGER = setup_logging() -def error(message, *args, **kwargs): +def error(message: str, *args: Any, **kwargs: Any) -> None: if args or kwargs: message = message.format(*args, **kwargs) print(f'didjvu: error: {message}', file=sys.stderr) @@ -452,14 +452,14 @@ def bundle_complex(self, options): bytes_in = 0 pixels = [0] page_info = [] - page_id_memo = {} + page_id_memo: Dict[str, int] = {} for page_number, (image_filename, mask_filename) in enumerate(zip(options.input, options.masks)): page = utils.Namespace() page_info += [page] bytes_in += os.path.getsize(image_filename) page.page_id = templates.expand(options.page_id_template, image_filename, page_number, page_id_memo) try: - djvu_support.validate_page_id(page.page_id) + djvu_support.validate_page_id(page.page_id) # type: ignore[attr-defined] except ValueError as exception: error(exception) del page # quieten pyflakes @@ -472,11 +472,11 @@ def bundle_complex(self, options): options.masks, itertools.repeat(pixels) ) - [pixels] = pixels + [pixel_count] = pixels with temporary.directory() as minidjvu_out_dir: LOGGER.info('creating shared dictionaries') - def chdir(): + def chdir() -> None: os.chdir(minidjvu_out_dir) arguments = [ @@ -487,7 +487,7 @@ def chdir(): if options.loss_level > 0: arguments += ['--aggression', str(options.loss_level)] assert len(page_info) > 1 # minidjvu won't create single-page indirect documents - arguments += [page.sjbz_symlink for page in page_info] + arguments += [page.sjbz_symlink for page in page_info] # type: ignore[attr-defined] index_filename = temporary.name(prefix='__index__.', suffix='.djvu', dir=minidjvu_out_dir) index_filename = os.path.basename(index_filename) # FIXME: Name conflicts are still possible! arguments += [index_filename] @@ -496,29 +496,27 @@ def chdir(): component_filenames = [] for page_number, page in enumerate(page_info): if page_number % options.pages_per_dict == 0: - iff_name = fs.replace_ext(page_info[page_number].page_id, 'iff') + iff_name = fs.replace_ext(page_info[page_number].page_id, 'iff') # type: ignore[attr-defined] iff_name = os.path.join(minidjvu_out_dir, iff_name) component_filenames += [iff_name] - sjbz_name = os.path.join(minidjvu_out_dir, page.page_id) + sjbz_name = os.path.join(minidjvu_out_dir, page.page_id) # type: ignore[attr-defined] component_filenames += [sjbz_name] - page.djvu['sjbz'] = sjbz_name - page.djvu['incl'] = iff_name - page.djvu = page.djvu.save() - page.djvu_symlink = os.path.join(minidjvu_out_dir, page.page_id) - os.unlink(page.djvu_symlink) - os.symlink(page.djvu.name, page.djvu_symlink) + page.djvu['sjbz'] = sjbz_name # type: ignore[attr-defined] + page.djvu['incl'] = iff_name # type: ignore[attr-defined] + page.djvu = page.djvu.save() # type: ignore[attr-defined] + page.djvu_symlink = os.path.join(minidjvu_out_dir, page.page_id) # type: ignore[attr-defined] + os.unlink(page.djvu_symlink) # type: ignore[attr-defined] + os.symlink(page.djvu.name, page.djvu_symlink) # type: ignore[attr-defined] LOGGER.info('bundling') djvu_file = djvu_support.bundle_djvu(*component_filenames) try: bytes_out = fs.copy_file(djvu_file, output) finally: djvu_file.close() - bits_per_pixel = 8.0 * bytes_out / pixels + bits_per_pixel = 8.0 * bytes_out / pixel_count compression_info = format_compression_info(bytes_in, bytes_out, bits_per_pixel) # noinspection PyUnresolvedReferences LOGGER.nosy(compression_info) __all__ = ['Main'] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/djvu_support.py b/didjvu/djvu_support.py index 7a9c8b0..73d53f4 100644 --- a/didjvu/djvu_support.py +++ b/didjvu/djvu_support.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2009-2021 Jakub Wilk +# Copyright © 2009-2022 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -367,5 +366,3 @@ def validate_page_id(page_id): 'IW44_SLICES_DEFAULT', 'CRCB', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/filetype.py b/didjvu/filetype.py index b458754..ea73bda 100644 --- a/didjvu/filetype.py +++ b/didjvu/filetype.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2010-2018 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -51,5 +50,3 @@ def check(filename): 'Djvu', 'DjvuSingle', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/fs.py b/didjvu/fs.py index 4695a8c..f6224c3 100644 --- a/didjvu/fs.py +++ b/didjvu/fs.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2009-2018 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -41,5 +40,3 @@ def replace_ext(filename, ext): 'copy_file', 'replace_ext', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/gamera_support.py b/didjvu/gamera_support.py index e3bcbaa..b5f3880 100644 --- a/didjvu/gamera_support.py +++ b/didjvu/gamera_support.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2009-2021 Jakub Wilk +# Copyright © 2009-2022 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -250,5 +249,3 @@ def init(): 'to_pil_1bpp', 'to_pil_rgb', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/ipc.py b/didjvu/ipc.py index d7bb09a..828aef1 100644 --- a/didjvu/ipc.py +++ b/didjvu/ipc.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2008-2021 Jakub Wilk +# Copyright © 2008-2022 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -162,5 +161,3 @@ def require(*commands): 'CalledProcessError', 'CalledProcessInterrupted', 'Subprocess', 'PIPE', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/templates.py b/didjvu/templates.py index f54acc0..f359921 100644 --- a/didjvu/templates.py +++ b/didjvu/templates.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2010-2018 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -72,5 +71,3 @@ def expand(template, name, page, memo): __all__ = ['expand'] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/temporary.py b/didjvu/temporary.py index 4d34f27..0b9b966 100644 --- a/didjvu/temporary.py +++ b/didjvu/temporary.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2009-2015 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -55,5 +54,3 @@ def directory(*args, **kwargs): 'hardlink', 'name', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/timestamp.py b/didjvu/timestamp.py index 7f716a2..4cd5916 100644 --- a/didjvu/timestamp.py +++ b/didjvu/timestamp.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2012-2019 Jakub Wilk +# Copyright © 2012-2024 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -17,8 +16,8 @@ Timestamps. """ -import time import datetime +import time class Timestamp: @@ -69,6 +68,7 @@ def now(): return Timestamp(time.time()) -__all__ = ['Timestamp', 'now'] - -# vim:ts=4 sts=4 sw=4 et +__all__ = [ + 'Timestamp', + 'now' +] diff --git a/didjvu/utils.py b/didjvu/utils.py index 3647dc4..775097a 100644 --- a/didjvu/utils.py +++ b/didjvu/utils.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2011-2019 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -63,5 +62,3 @@ def __setattr__(self, name, value): 'Proxy', 'enhance_import_error', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/version.py b/didjvu/version.py index 81ef3d1..d17634e 100644 --- a/didjvu/version.py +++ b/didjvu/version.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2011-2019 Jakub Wilk +# Copyright © 2011-2024 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -63,6 +62,15 @@ def __call__(self, parser, namespace, values, option_string=None): # noinspection PyUnresolvedReferences pil_version = gamera_support.PILImage.VERSION print(f'+ {pil_name} {pil_version}') + + from didjvu import xmp + if xmp.backend: + for version in xmp.backend.versions: + prefix = '+' + if version[0] == '+': + prefix = ' ' + print(prefix, version) + parser.exit() @@ -71,5 +79,3 @@ def __call__(self, parser, namespace, values, option_string=None): '__version__', 'get_software_agent', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/xmp/__init__.py b/didjvu/xmp/__init__.py index e35cd55..4b4b07d 100644 --- a/didjvu/xmp/__init__.py +++ b/didjvu/xmp/__init__.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2012-2016 Jakub Wilk +# Copyright © 2012-2023 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -146,5 +145,3 @@ def write(self, fp): 'import_error', 'metadata', ] - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/xmp/gexiv2_backend.py b/didjvu/xmp/gexiv2_backend.py index a2a5c02..533aa48 100644 --- a/didjvu/xmp/gexiv2_backend.py +++ b/didjvu/xmp/gexiv2_backend.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2012-2016 Jakub Wilk +# Copyright © 2012-2024 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -45,6 +44,17 @@ GExiv2.Metadata.register_xmp_namespace(namespaces.didjvu, 'didjvu') +def _get_versions(): + yield f'PyGI {gi.__version__}' + version_int = GExiv2.get_version() + major_minor, patch = divmod(version_int, 100) + major, minor = divmod(major_minor, 100) + yield f'GExiv2 {major}.{minor}.{patch}' + + +versions = list(_get_versions()) + + class XmpError(RuntimeError): pass @@ -120,6 +130,7 @@ def read(self, fp): self._read_data(data) -__all__ = ['MetadataBase'] - -# vim:ts=4 sts=4 sw=4 et +__all__ = [ + 'MetadataBase', + 'versions', +] diff --git a/didjvu/xmp/libxmp_backend.py b/didjvu/xmp/libxmp_backend.py index c89648c..bc03a9a 100644 --- a/didjvu/xmp/libxmp_backend.py +++ b/didjvu/xmp/libxmp_backend.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2012-2019 Jakub Wilk +# Copyright © 2012-2024 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -24,6 +23,18 @@ from didjvu.xmp import namespaces +def _get_versions(): + library = 'python-xmp-toolkit' + try: + version = libxmp.__version__ + except AttributeError: + return library + return f'{library} {version}' + + +versions = [_get_versions()] + + class XmpError(RuntimeError): pass @@ -108,6 +119,7 @@ def read(self, fp): backend.parse_from_str(xmp) -__all__ = ['MetadataBase'] - -# vim:ts=4 sts=4 sw=4 et +__all__ = [ + 'MetadataBase', + 'versions', +] diff --git a/didjvu/xmp/namespaces.py b/didjvu/xmp/namespaces.py index f928dbc..06b4023 100644 --- a/didjvu/xmp/namespaces.py +++ b/didjvu/xmp/namespaces.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2012-2018 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -24,5 +23,3 @@ tiff = 'http://ns.adobe.com/tiff/1.0/' xmp = 'http://ns.adobe.com/xap/1.0/' xmpmm = 'http://ns.adobe.com/xap/1.0/mm/' - -# vim:ts=4 sts=4 sw=4 et diff --git a/didjvu/xmp/pyexiv2_backend.py b/didjvu/xmp/pyexiv2_backend.py index d568d14..32c28cc 100644 --- a/didjvu/xmp/pyexiv2_backend.py +++ b/didjvu/xmp/pyexiv2_backend.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2012-2021 Jakub Wilk +# Copyright © 2012-2024 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -30,8 +29,19 @@ from didjvu.xmp import namespaces +def _get_versions(): + version = pyexiv2.__version__ + yield f'pyexiv2 {version}' + version = pyexiv2.__exiv2_version__ + yield f'+ Exiv2 {version}' + + +versions = list(_get_versions()) + + def xmp_register_namespace(prefix, uri): # Work-around for + # ("pyexiv2.xmp.register_namespace() requires URI ending with /") class Namespace(str): def endswith(self, suffix, *args, **kwargs): @@ -195,6 +205,7 @@ def read(self, file): self._reload() -__all__ = ['MetadataBase'] - -# vim:ts=4 sts=4 sw=4 et +__all__ = [ + 'MetadataBase', + 'versions', +] diff --git a/doc/Makefile b/doc/Makefile index af6a6cc..2d9d716 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,4 +1,5 @@ -# Copyright © 2018-2019 Jakub Wilk +# Copyright © 2018-2022 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -47,5 +48,3 @@ check-xml: manpage.xml .PHONY: clean clean: rm -f *.1 - -# vim:ts=4 sts=4 sw=4 noet diff --git a/doc/README b/doc/README index fc99c38..a42df70 100644 --- a/doc/README +++ b/doc/README @@ -98,5 +98,3 @@ Differences from upstream https://github.com/rmast .. _Issue #13: https://github.com/jwilk/didjvu/issues/13 - -.. vim:ft=rst ts=3 sts=3 sw=3 et tw=72 diff --git a/doc/manpage.xml b/doc/manpage.xml index e341a5f..c8496bd 100644 --- a/doc/manpage.xml +++ b/doc/manpage.xml @@ -2,7 +2,8 @@ diff --git a/doc/todo b/doc/todo index 93c59b5..c182779 100644 --- a/doc/todo +++ b/doc/todo @@ -24,5 +24,3 @@ not ``\(aq``. Automatically check Python code with pylint. Should ``xmp::ModifyDate`` be updated? - -.. vim:ft=rst ts=3 sts=4 sw=3 et tw=72 diff --git a/private/check-new-boost-release b/private/check-new-boost-release index fdc1ab5..089fdb5 100755 --- a/private/check-new-boost-release +++ b/private/check-new-boost-release @@ -1,5 +1,20 @@ #!/usr/bin/env python +# Copyright © 2023-2024 FriedrichFroebel +# +# This file is part of didjvu. +# +# didjvu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as published by +# the Free Software Foundation. If you like, you might use the +# `check-new-boost-release` script under the terms of the MIT license as well, id +# est this file can be considered "GPL-2.0-only OR MIT". +# +# didjvu is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. + import sys from dataclasses import dataclass from pathlib import Path diff --git a/private/update-version b/private/update-version index 27668b1..b2fab04 100755 --- a/private/update-version +++ b/private/update-version @@ -1,4 +1,19 @@ #!/bin/sh + +# Copyright © 2010-2018 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel +# +# This file is part of didjvu +# +# didjvu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# didjvu is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. + set -e -u version=${1:?"no version number provided"} date="$(date -u --rfc-3339=date)" diff --git a/setup.py b/setup.py index 943a059..8ef5689 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,17 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- +# Copyright © 2010-2018 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel +# +# This file is part of didjvu. +# +# didjvu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# didjvu is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. + from setuptools import setup, find_packages from pathlib import Path diff --git a/tests/test_cli.py b/tests/test_cli.py index ac35391..940ea54 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2015-2021 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -290,5 +289,3 @@ def test_help(self): for action in actions: with self.subTest(action=action): self._test_help(action=action) - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_didjvu.py b/tests/test_didjvu.py index e3b34fd..55d4419 100644 --- a/tests/test_didjvu.py +++ b/tests/test_didjvu.py @@ -1,6 +1,4 @@ -# encoding=UTF-8 - -# Copyright © 2015-2021 Jakub Wilk +# Copyright © 2023-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -48,5 +46,3 @@ def test_generates_output_file(self): target_file.seek(0) first_bytes = target_file.read(340) self.assertEqual(340, len(first_bytes), first_bytes) - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_djvu.py b/tests/test_djvu.py index 94a9ca3..1edec31 100644 --- a/tests/test_djvu.py +++ b/tests/test_djvu.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2015 Jakub Wilk +# Copyright © 2015-2024 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -57,22 +56,24 @@ def ddjvu(djvu_file, fmt='ppm'): class BitonalToDjvuTestCase(TestCase): def test_bitonal_to_djvu(self): path = self.get_data_file('onebit.bmp') - in_image = Image.open(path) - djvu_file = djvu.bitonal_to_djvu(in_image) - out_image = ddjvu(djvu_file, fmt='pbm') - self.assert_images_equal(in_image, out_image) + with Image.open(path) as in_image: + djvu_file = djvu.bitonal_to_djvu(in_image) + out_image = ddjvu(djvu_file, fmt='pbm') + self.addCleanup(out_image.close) + self.assert_images_equal(in_image, out_image) class PhotoToDjvuTestCase(TestCase): def test_photo_to_djvu(self): path = self.get_data_file('ycbcr-jpeg.tiff') with silence_truncated_file_read_warnings(): - in_image = Image.open(path) - in_image = in_image.convert('RGB') - mask_image = in_image.convert('1') - djvu_file = djvu.photo_to_djvu(in_image, mask_image=mask_image) - out_image = ddjvu(djvu_file, fmt='ppm') - self.assert_image_sizes_equal(in_image, out_image) + with Image.open(path) as in_image: + in_image = in_image.convert('RGB') + mask_image = in_image.convert('1') + djvu_file = djvu.photo_to_djvu(in_image, mask_image=mask_image) + out_image = ddjvu(djvu_file, fmt='ppm') + self.addCleanup(out_image.close) + self.assert_image_sizes_equal(in_image, out_image) class DjvuToIw44TestCase(TestCase): @@ -81,7 +82,9 @@ def test_djvu_to_iw44(self): with open(path, mode='rb') as in_djvu: out_djvu = djvu.djvu_to_iw44(in_djvu) in_image = ddjvu(in_djvu, fmt='ppm') + self.addCleanup(in_image.close) out_image = ddjvu(out_djvu, fmt='ppm') + self.addCleanup(out_image.close) self.assert_image_sizes_equal(in_image, out_image) in_djvu.seek(0) in_data = in_djvu.read() @@ -93,29 +96,31 @@ def test_djvu_to_iw44(self): class MultichunkTestCase(TestCase): def test_sjbz(self): path = self.get_data_file('onebit.bmp') - in_image = Image.open(path) - width, height = in_image.size - sjbz_path = self.get_data_file('onebit.djvu') - multichunk = djvu.Multichunk(width, height, 100, sjbz=sjbz_path) - djvu_file = multichunk.save() - out_image = ddjvu(djvu_file, fmt='pbm') - self.assert_images_equal(in_image, out_image) + with Image.open(path) as in_image: + width, height = in_image.size + sjbz_path = self.get_data_file('onebit.djvu') + multichunk = djvu.Multichunk(width, height, 100, sjbz=sjbz_path) + djvu_file = multichunk.save() + out_image = ddjvu(djvu_file, fmt='pbm') + self.addCleanup(out_image.close) + self.assert_images_equal(in_image, out_image) def test_incl(self): path = self.get_data_file('onebit.bmp') - in_image = Image.open(path) - width, height = in_image.size - sjbz_path = self.get_data_file('onebit.djvu') - incl_path = self.get_data_file('shared_anno.iff') - multichunk = djvu.Multichunk(width, height, 100, sjbz=sjbz_path, incl=incl_path) - djvu_file = multichunk.save() - with temporary.directory() as tmpdir: - tmp_djvu_path = os.path.join(tmpdir, 'index.djvu') - tmp_incl_path = os.path.join(tmpdir, 'shared_anno.iff') - os.link(djvu_file.name, tmp_djvu_path) - shutil.copyfile(incl_path, tmp_incl_path) - out_image = ddjvu(tmp_djvu_path, fmt='pbm') - self.assert_images_equal(in_image, out_image) + with Image.open(path) as in_image: + width, height = in_image.size + sjbz_path = self.get_data_file('onebit.djvu') + incl_path = self.get_data_file('shared_anno.iff') + multichunk = djvu.Multichunk(width, height, 100, sjbz=sjbz_path, incl=incl_path) + djvu_file = multichunk.save() + with temporary.directory() as tmpdir: + tmp_djvu_path = os.path.join(tmpdir, 'index.djvu') + tmp_incl_path = os.path.join(tmpdir, 'shared_anno.iff') + os.link(djvu_file.name, tmp_djvu_path) + shutil.copyfile(incl_path, tmp_incl_path) + out_image = ddjvu(tmp_djvu_path, fmt='pbm') + self.addCleanup(out_image.close) + self.assert_images_equal(in_image, out_image) class ValidatePageIdTestCase(TestCase): @@ -189,6 +194,3 @@ def wait(self, timeout=None): ) self.assertTrue(os.path.exists(djvu_path.name)) self.assertEqual(2, len(self._wait_called)) - - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_filetype.py b/tests/test_filetype.py index 28bfd7b..d28771b 100644 --- a/tests/test_filetype.py +++ b/tests/test_filetype.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2015 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -32,5 +31,3 @@ def test_bad(self): file_type = filetype.check(path) self.assertFalse(file_type.like(filetype.Djvu)) self.assertFalse(file_type.like(filetype.DjvuSingle)) - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_fs.py b/tests/test_fs.py index c9e5619..e0061db 100644 --- a/tests/test_fs.py +++ b/tests/test_fs.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2015 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -49,5 +48,3 @@ def test_replace_ext(self): self.assertEqual(result, 'eggs.spam') result = fs.replace_ext('eggs.ham', 'spam') self.assertEqual(result, 'eggs.spam') - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_gamera.py b/tests/test_gamera.py index e1dbdf4..af7bd57 100644 --- a/tests/test_gamera.py +++ b/tests/test_gamera.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2015 Jakub Wilk +# Copyright © 2015-2024 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -85,15 +84,14 @@ class ToPilRgbTestCase(TestCase): def _test(self, filename): path = self.get_data_file(filename) self.assertTrue(os.path.exists(path)) - in_image = Image.open(path) - self.addCleanup(in_image.close) - if in_image.mode != 'RGB': - in_image = in_image.convert('RGB') - self.assertEqual(in_image.mode, 'RGB') - gamera_support.init() - gamera_image = gamera_support.load_image(path) - out_image = gamera_support.to_pil_rgb(gamera_image) - self.assert_images_equal(in_image, out_image) + with Image.open(path) as in_image: + if in_image.mode != 'RGB': + in_image = in_image.convert('RGB') + self.assertEqual(in_image.mode, 'RGB') + gamera_support.init() + gamera_image = gamera_support.load_image(path) + out_image = gamera_support.to_pil_rgb(gamera_image) + self.assert_images_equal(in_image, out_image) def test_color(self): with silence_truncated_file_read_warnings(): @@ -106,21 +104,18 @@ def test_grey(self): class ToPil1bppTestCase(TestCase): def _test(self, filename): path = self.get_data_file(filename) - in_image = Image.open(path) - self.addCleanup(in_image.close) - if in_image.mode != '1': - in_image = in_image.convert('1') - self.assertEqual(in_image.mode, '1') - gamera_support.init() - gamera_image = gamera_support.load_image(path) - out_image = gamera_support.to_pil_1bpp(gamera_image) - out_image = out_image.convert('1') # FIXME? - self.assert_images_equal(in_image, out_image) + with Image.open(path) as in_image: + if in_image.mode != '1': + in_image = in_image.convert('1') + self.assertEqual(in_image.mode, '1') + gamera_support.init() + gamera_image = gamera_support.load_image(path) + out_image = gamera_support.to_pil_1bpp(gamera_image) + out_image = out_image.convert('1') # FIXME? + self.assert_images_equal(in_image, out_image) def test_grey(self): self._test('greyscale-packbits.tiff') def test_mono(self): self._test('onebit.png') - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_ipc.py b/tests/test_ipc.py index 7632ba7..5ddbdb3 100644 --- a/tests/test_ipc.py +++ b/tests/test_ipc.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2010-2017 Jakub Wilk +# Copyright © 2010-2022 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -235,5 +234,3 @@ def test_fail(self): ipc.require(NON_EXISTENT_COMMAND) exception_message = f"[Errno {errno.ENOENT}] command not found: {NON_EXISTENT_COMMAND!r}" self.assertEqual(str(exception_manager.exception), exception_message) - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_templates.py b/tests/test_templates.py index 25d5e86..af2f848 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2010-2015 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -85,5 +84,3 @@ def test_duplicates(self): self.assertEqual(result, 'eggs.2.1.djvu') result = templates.expand('{base-ext}.2.djvu', path, 0, memo) self.assertEqual(result, 'eggs.2.2.djvu') - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_timestamp.py b/tests/test_timestamp.py index d20f4d7..74bcdb1 100644 --- a/tests/test_timestamp.py +++ b/tests/test_timestamp.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2012-2015 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -64,6 +63,3 @@ def test_timezones(self): timezone=timezone, expected=expected ) - - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_utils.py b/tests/test_utils.py index c9ba93b..f11f01d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2010-2019 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -125,5 +124,3 @@ def __del__(self): del proxy gc.collect() self.assertFalse(Del.ok) - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_version.py b/tests/test_version.py index 168dbc6..d81e971 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2015-2018 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -54,5 +53,3 @@ def test_get_software_agent(self): self.assertIsInstance(result, str) match = re.match(r'^didjvu [\d.]+ [(]Gamera [\d.]+(pre)?[)]$', result) self.assertIsNotNone(match) - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/test_xmp.py b/tests/test_xmp.py index 3bc9a22..4f02e85 100644 --- a/tests/test_xmp.py +++ b/tests/test_xmp.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - # Copyright © 2012-2021 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -481,5 +480,3 @@ def test_io_error(self): for backend in XMP_BACKENDS: with self.subTest(backend=backend): self._test_io_error(backend) - -# vim:ts=4 sts=4 sw=4 et diff --git a/tests/tools.py b/tests/tools.py index 25754eb..f422122 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -1,6 +1,5 @@ -# encoding=UTF-8 - -# Copyright © 2010-2021 Jakub Wilk +# Copyright © 2010-2022 Jakub Wilk +# Copyright © 2022-2024 FriedrichFroebel # # This file is part of didjvu. # @@ -94,5 +93,3 @@ def silence_truncated_file_read_warnings(): 'interim_environ', 'silence_truncated_file_read_warnings', ] - -# vim:ts=4 sts=4 sw=4 et