Files
DeDRM_tools/DeDRM_plugin/utilities.py
T
JMR-devandClaude Opus 4.8 ae2231727f Fix Python 3 correctness bugs found in code review
Fix str/bytes and leftover-py2 defects across the plugin, several on live
decryption paths:

  - erdr2pml.py: getText() footnote/sidebar handling mixed a bytes
    accumulator with str literals and called ord() on a bytes element,
    crashing on eReader/.pdb books that contain footnotes or sidebars.
  - ion.py: readdecimal() did `[ord(x) for x in self.read(...)]` over
    bytes (ord(int)), crashing KFX decryption on Ion DECIMAL values;
    printlob() had the same ord()-over-bytes in its debug path.
  - zipfilerugged.py: `isinstance(file, unicode)` raised NameError when a
    file-like object (not a path string) was passed to the ZipFile.
  - utilities.py: SafeUnbuffered.write referenced the undefined `unicode`
    (same fix already applied to the obok copy).
  - ineptpdf.py: ord(bookkey[0]) over an int in an error-diagnostic print.
  - epubfontdecrypt.py: removed a dead py2 itertools.izip fallback.
  - convert2xml.py: escapestr did bytes.replace(str, ...).
  - kgenpids.py: decode() built a str result then += bytes.

Cleanups from the earlier shim removal: drop now-unused `import sys`
(alfcrypto, utilities, kgenpids); unicode_argv returns list(sys.argv) so
callers can't mutate the process-global sys.argv.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 20:35:11 -05:00

42 lines
1.3 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#@@CALIBRE_COMPAT_CODE@@
__license__ = 'GPL v3'
def uStrCmp (s1, s2, caseless=False):
import unicodedata as ud
str1 = s1 if isinstance(s1, str) else str(s1)
str2 = s2 if isinstance(s2, str) else str(s2)
if caseless:
return ud.normalize('NFC', str1.lower()) == ud.normalize('NFC', str2.lower())
else:
return ud.normalize('NFC', str1) == ud.normalize('NFC', str2)
# Wrap a stream so that output gets flushed immediately
# and also make sure that any unicode strings get safely
# encoded using "replace" before writing them.
class SafeUnbuffered:
def __init__(self, stream):
self.stream = stream
self.encoding = stream.encoding
if self.encoding == None:
self.encoding = "utf-8"
def write(self, data):
if isinstance(data,str):
data = data.encode(self.encoding,"replace")
try:
buffer = getattr(self.stream, 'buffer', self.stream)
# self.stream.buffer for Python3, self.stream for Python2
buffer.write(data)
buffer.flush()
except:
# We can do nothing if a write fails
raise
def __getattr__(self, attr):
return getattr(self.stream, attr)