Make code compatible with python 3.7, removed unused imports, change static methods.

This commit is contained in:
Vaso Peras-Likodric 2022-09-14 17:45:48 +02:00
parent 4a6d9d8b2b
commit ca45bcaaf5
10 changed files with 68 additions and 52 deletions

View File

@ -2,6 +2,8 @@ __license__ = 'GPL v3'
__copyright__ = '2011, John Schember <john at nachtimwald.com>, refactored: 2022, Vaso Peras-Likodric <vaso at vipl.in.rs>' __copyright__ = '2011, John Schember <john at nachtimwald.com>, refactored: 2022, Vaso Peras-Likodric <vaso at vipl.in.rs>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from typing import Optional, Dict
''' '''
Generates and writes an APNX page mapping file. Generates and writes an APNX page mapping file.
''' '''
@ -17,8 +19,6 @@ from polyglot.builtins import as_unicode, as_bytes
from calibre.devices.kindle.apnx_page_generator.generators.accurate_page_generator import AccuratePageGenerator from calibre.devices.kindle.apnx_page_generator.generators.accurate_page_generator import AccuratePageGenerator
from calibre.devices.kindle.apnx_page_generator.generators.pagebreak_page_generator import PagebreakPageGenerator from calibre.devices.kindle.apnx_page_generator.generators.pagebreak_page_generator import PagebreakPageGenerator
from calibre.devices.kindle.apnx_page_generator.generators.aria_pagebreak_page_generator import \
AriaPagebreakPageGenerator
from calibre.devices.kindle.apnx_page_generator.generators.exact_page_generator import ExactPageGenerator from calibre.devices.kindle.apnx_page_generator.generators.exact_page_generator import ExactPageGenerator
from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator
from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator
@ -30,14 +30,14 @@ class APNXBuilder:
Create an APNX file using a pseudo page mapping. Create an APNX file using a pseudo page mapping.
""" """
generators: dict[str, IPageGenerator] = { generators: Dict[str, IPageGenerator] = {
FastPageGenerator.instance.name(): FastPageGenerator.instance, FastPageGenerator.instance.name(): FastPageGenerator.instance,
AccuratePageGenerator.instance.name(): AccuratePageGenerator.instance, AccuratePageGenerator.instance.name(): AccuratePageGenerator.instance,
PagebreakPageGenerator.instance.name(): PagebreakPageGenerator.instance, PagebreakPageGenerator.instance.name(): PagebreakPageGenerator.instance,
# ExactPageGenerator.instance.name(): ExactPageGenerator.instance, # ExactPageGenerator.instance.name(): ExactPageGenerator.instance,
} }
def write_apnx(self, mobi_file_path: str, apnx_path: str, method: str | None = None, page_count: int = 0): def write_apnx(self, mobi_file_path: str, apnx_path: str, method: Optional[str] = None, page_count: int = 0):
""" """
If you want a fixed number of pages (such as from a custom column) then If you want a fixed number of pages (such as from a custom column) then
pass in a value to page_count, otherwise a count will be estimated pass in a value to page_count, otherwise a count will be estimated
@ -62,7 +62,7 @@ class APNXBuilder:
fsync(apnxf) fsync(apnxf)
@staticmethod @staticmethod
def get_apnx_meta(mobi_file_path) -> dict[str, str]: def get_apnx_meta(mobi_file_path) -> Dict[str, str]:
import uuid import uuid
apnx_meta = { apnx_meta = {
'guid': str(uuid.uuid4()).replace('-', '')[:8], 'guid': str(uuid.uuid4()).replace('-', '')[:8],

View File

@ -2,20 +2,24 @@ __license__ = 'GPL v3'
__copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>' __copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from typing import Optional
from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator
from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator, mobi_html
from calibre.devices.kindle.apnx_page_generator.pages import Pages from calibre.devices.kindle.apnx_page_generator.pages import Pages
class AccuratePageGenerator(IPageGenerator): class AccuratePageGenerator(IPageGenerator):
instance = None
def name(self) -> str: def name(self) -> str:
return "accurate" return "accurate"
def _generate_fallback(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate_fallback(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
return FastPageGenerator.instance.generate(mobi_file_path, real_count) return FastPageGenerator.instance.generate(mobi_file_path, real_count)
def _generate(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
""" """
A more accurate but much more resource intensive and slower A more accurate but much more resource intensive and slower
method to calculate the page length. method to calculate the page length.
@ -35,7 +39,7 @@ class AccuratePageGenerator(IPageGenerator):
""" """
pages = [] pages = []
html = self.mobi_html(mobi_file_path) html = mobi_html(mobi_file_path)
# States # States
in_tag = False in_tag = False
@ -54,7 +58,7 @@ class AccuratePageGenerator(IPageGenerator):
# and string functions will parse the text each # and string functions will parse the text each
# time they are called. # time they are called.
# #
# We can can use .lower() here because we are # We can use .lower() here because we are
# not modifying the text. In this case the case # not modifying the text. In this case the case
# doesn't matter just the absolute character and # doesn't matter just the absolute character and
# the position within the stream. # the position within the stream.

View File

@ -2,20 +2,24 @@ __license__ = 'GPL v3'
__copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>' __copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from typing import Optional
from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator
from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator, mobi_html_length
from calibre.devices.kindle.apnx_page_generator.pages import Pages from calibre.devices.kindle.apnx_page_generator.pages import Pages
class ExactPageGenerator(IPageGenerator): class ExactPageGenerator(IPageGenerator):
instance = None
def name(self) -> str: def name(self) -> str:
return "exact" return "exact"
def _generate_fallback(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate_fallback(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
return FastPageGenerator.instance.generate(mobi_file_path, real_count) return FastPageGenerator.instance.generate(mobi_file_path, real_count)
def _generate(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
""" """
Given a specified page count (such as from a custom column), Given a specified page count (such as from a custom column),
create our array of pages for the apnx file by dividing by create our array of pages for the apnx file by dividing by
@ -24,7 +28,7 @@ class ExactPageGenerator(IPageGenerator):
pages = [] pages = []
count = 0 count = 0
text_length = self.mobi_html_length(mobi_file_path) text_length = mobi_html_length(mobi_file_path)
chars_per_page = int(text_length // real_count) chars_per_page = int(text_length // real_count)
while count < text_length: while count < text_length:

View File

@ -2,7 +2,9 @@ __license__ = 'GPL v3'
__copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>' __copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator from typing import Optional
from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator, mobi_html_length
from calibre.devices.kindle.apnx_page_generator.pages import Pages from calibre.devices.kindle.apnx_page_generator.pages import Pages
@ -11,10 +13,10 @@ class FastPageGenerator(IPageGenerator):
def name(self) -> str: def name(self) -> str:
return "fast" return "fast"
def _generate_fallback(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate_fallback(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
raise Exception("Fast calculation impossible.") raise Exception("Fast calculation impossible.")
def _generate(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
""" """
2300 characters of uncompressed text per page. This is 2300 characters of uncompressed text per page. This is
not meant to map 1 to 1 to a print book but to be a not meant to map 1 to 1 to a print book but to be a
@ -34,7 +36,7 @@ class FastPageGenerator(IPageGenerator):
pages = [] pages = []
count = 0 count = 0
text_length = self.mobi_html_length(mobi_file_path) text_length = mobi_html_length(mobi_file_path)
while count < text_length: while count < text_length:
pages.append(count) pages.append(count)

View File

@ -2,8 +2,10 @@ __license__ = 'GPL v3'
__copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>' __copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from typing import Optional
from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator from calibre.devices.kindle.apnx_page_generator.generators.fast_page_generator import FastPageGenerator
from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator from calibre.devices.kindle.apnx_page_generator.i_page_generator import IPageGenerator, mobi_html
from calibre.devices.kindle.apnx_page_generator.pages import Pages from calibre.devices.kindle.apnx_page_generator.pages import Pages
import re import re
@ -13,12 +15,12 @@ class PagebreakPageGenerator(IPageGenerator):
def name(self) -> str: def name(self) -> str:
return "pagebreak" return "pagebreak"
def _generate_fallback(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate_fallback(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
return FastPageGenerator.instance.generate(mobi_file_path, real_count) return FastPageGenerator.instance.generate(mobi_file_path, real_count)
def _generate(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
""" Determine pages based on the presence of <*pagebreak*/>. """ """ Determine pages based on the presence of <*pagebreak*/>. """
html = self.mobi_html(mobi_file_path) html = mobi_html(mobi_file_path)
pages = [] pages = []
for m in re.finditer(b'<[^>]*pagebreak[^>]*>', html): for m in re.finditer(b'<[^>]*pagebreak[^>]*>', html):
pages.append(m.end()) pages.append(m.end())

View File

@ -4,6 +4,8 @@ __docformat__ = 'restructuredtext en'
import struct import struct
from abc import abstractmethod, ABCMeta from abc import abstractmethod, ABCMeta
from typing import Optional
from calibre.devices.kindle.apnx_page_generator.pages import Pages from calibre.devices.kindle.apnx_page_generator.pages import Pages
from calibre.ebooks.mobi.reader.mobi6 import MobiReader from calibre.ebooks.mobi.reader.mobi6 import MobiReader
from calibre.utils.logging import default_log from calibre.utils.logging import default_log
@ -14,14 +16,14 @@ from calibre.ebooks.pdb.header import PdbHeaderReader
class IPageGenerator(metaclass=ABCMeta): class IPageGenerator(metaclass=ABCMeta):
@abstractmethod @abstractmethod
def _generate(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
pass pass
@abstractmethod @abstractmethod
def _generate_fallback(self, mobi_file_path: str, real_count: int | None) -> Pages: def _generate_fallback(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
pass pass
def generate(self, mobi_file_path: str, real_count: int | None) -> Pages: def generate(self, mobi_file_path: str, real_count: Optional[int]) -> Pages:
try: try:
result = self._generate(mobi_file_path, real_count) result = self._generate(mobi_file_path, real_count)
if result.number_of_pages > 0: if result.number_of_pages > 0:
@ -36,18 +38,17 @@ class IPageGenerator(metaclass=ABCMeta):
def name(self) -> str: def name(self) -> str:
pass pass
@staticmethod
def mobi_html(mobi_file_path: str) -> bytes: def mobi_html(mobi_file_path: str) -> bytes:
mr = MobiReader(mobi_file_path, default_log) mr = MobiReader(mobi_file_path, default_log)
if mr.book_header.encryption_type != 0: if mr.book_header.encryption_type != 0:
raise Exception("DRMed book") raise Exception("DRMed book")
mr.extract_text() mr.extract_text()
return as_bytes(mr.mobi_html.lower()) return as_bytes(mr.mobi_html.lower())
@staticmethod
def mobi_html_length(mobi_file_path: str) -> int: def mobi_html_length(mobi_file_path: str) -> int:
with lopen(mobi_file_path, 'rb') as mf: with lopen(mobi_file_path, 'rb') as mf:
pdb_header = PdbHeaderReader(mf) pdb_header = PdbHeaderReader(mf)
r0 = pdb_header.section_data(0) r0 = pdb_header.section_data(0)
return struct.unpack('>I', r0[4:8])[0] return struct.unpack('>I', r0[4:8])[0]

View File

@ -2,30 +2,32 @@ __license__ = 'GPL v3'
__copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>' __copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
from typing import Union, List, Tuple
from calibre.devices.kindle.apnx_page_generator.page_number_type import PageNumberTypes from calibre.devices.kindle.apnx_page_generator.page_number_type import PageNumberTypes
class PageGroup: class PageGroup:
"""Simulate constructor overloading""" """Simulate constructor overloading"""
def __init__(self, page_locations: int | list[int], page_number_type: PageNumberTypes, first_value: int, def __init__(self, page_locations: Union[int, List[int]], page_number_type: PageNumberTypes, first_value: int,
page_labels: str | list[str] | None = None): page_labels: Union[str, List[str], None] = None):
if page_locations.__class__ == int: if page_locations.__class__ == int:
self.page_locations: list[int] = [page_locations] self.page_locations: List[int] = [page_locations]
else: else:
self.page_locations: list[int] = page_locations self.page_locations: List[int] = page_locations
self.__page_number_type: PageNumberTypes = page_number_type self.__page_number_type: PageNumberTypes = page_number_type
self.__first_value = first_value self.__first_value = first_value
if page_number_type == PageNumberTypes.Custom: if page_number_type == PageNumberTypes.Custom:
assert(page_labels is not None) assert(page_labels is not None)
if page_labels.__class__ == str: if page_labels.__class__ == str:
assert (1 == len(self.page_locations) and len(page_labels) > 0) assert (1 == len(self.page_locations) and len(page_labels) > 0)
self.__page_number_labels: list[str] = [page_labels] self.__page_number_labels: List[str] = [page_labels]
else: else:
assert (len(page_labels) == len(self.page_locations)) assert (len(page_labels) == len(self.page_locations))
assert(all(len(label) > 0 for label in page_labels)) assert(all(len(label) > 0 for label in page_labels))
self.__page_number_labels: list[str] = page_labels self.__page_number_labels: List[str] = page_labels
def append(self, page_location: int | tuple[int, str]) -> None: def append(self, page_location: Union[int, Tuple[int, str]]) -> None:
if page_location.__class__ == int: if page_location.__class__ == int:
assert (self.__page_number_type != PageNumberTypes.Custom) assert (self.__page_number_type != PageNumberTypes.Custom)
self.page_locations.append(page_location) self.page_locations.append(page_location)

View File

@ -5,7 +5,7 @@ __docformat__ = 'restructuredtext en'
import enum import enum
class PageNumberTypes(str, enum.Enum): class PageNumberTypes(enum.Enum):
Arabic = "a" Arabic = "a"
Roman = "r" Roman = "r"
Custom = 'c' Custom = "c"

View File

@ -3,17 +3,18 @@ __copyright__ = '2022, Vaso Peras-Likodric <vaso at vipl.in.rs>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import itertools import itertools
from typing import Optional, List
from calibre.devices.kindle.apnx_page_generator.page_group import PageGroup from calibre.devices.kindle.apnx_page_generator.page_group import PageGroup
from calibre.devices.kindle.apnx_page_generator.page_number_type import PageNumberTypes from calibre.devices.kindle.apnx_page_generator.page_number_type import PageNumberTypes
class Pages: class Pages:
def __init__(self, page_locations: list[int] | None = None): def __init__(self, page_locations: Optional[List[int]] = None):
if page_locations.__class__ == list: if page_locations.__class__ == list:
self.__pages_groups: list[PageGroup] = [PageGroup(page_locations, PageNumberTypes.Arabic, 1)] self.__pages_groups: List[PageGroup] = [PageGroup(page_locations, PageNumberTypes.Arabic, 1)]
else: else:
self.__pages_groups: list[PageGroup] = [] self.__pages_groups: List[PageGroup] = []
def append(self, page_location: PageGroup) -> None: def append(self, page_location: PageGroup) -> None:
self.__pages_groups.append(page_location) self.__pages_groups.append(page_location)
@ -33,7 +34,7 @@ class Pages:
return ",".join(result) return ",".join(result)
@property @property
def page_locations(self) -> list[int]: def page_locations(self) -> List[int]:
return list(itertools.chain.from_iterable(list(map(lambda pg: pg.page_locations, self.__pages_groups)))) return list(itertools.chain.from_iterable(list(map(lambda pg: pg.page_locations, self.__pages_groups))))
@property @property

View File

@ -411,7 +411,7 @@ class KINDLE2(KINDLE):
OPT_APNX_CUST_COL = 2 OPT_APNX_CUST_COL = 2
OPT_APNX_METHOD_COL = 3 OPT_APNX_METHOD_COL = 3
OPT_APNX_OVERWRITE = 4 OPT_APNX_OVERWRITE = 4
EXTRA_CUSTOMIZATION_CHOICES = {OPT_APNX_METHOD: APNXBuilder.generators.keys()} EXTRA_CUSTOMIZATION_CHOICES = {OPT_APNX_METHOD: set(APNXBuilder.generators.keys())}
# x330 on the PaperWhite # x330 on the PaperWhite
# x262 on the Touch. Doesn't choke on x330, though. # x262 on the Touch. Doesn't choke on x330, though.