Make PyICU optional
Update README.md
This commit is contained in:
parent
c1aba269a9
commit
e70c47d12a
@ -22,7 +22,6 @@ import shutil
|
||||
import sys
|
||||
from typing import cast
|
||||
|
||||
import natsort
|
||||
import wordninja
|
||||
|
||||
from comicapi import filenamelexer, filenameparser, utils
|
||||
@ -280,7 +279,7 @@ class ComicArchive:
|
||||
|
||||
# seems like some archive creators are on Windows, and don't know about case-sensitivity!
|
||||
if sort_list:
|
||||
files = cast(list[str], natsort.os_sorted(files))
|
||||
files = cast(list[str], utils.os_sorted(files))
|
||||
|
||||
# make a sub-list of image files
|
||||
self.page_list = []
|
||||
|
@ -18,22 +18,46 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import pathlib
|
||||
import platform
|
||||
import unicodedata
|
||||
from collections import defaultdict
|
||||
from collections.abc import Mapping
|
||||
from collections.abc import Iterable, Mapping
|
||||
from shutil import which # noqa: F401
|
||||
from typing import Any
|
||||
|
||||
import natsort
|
||||
import pycountry
|
||||
import rapidfuzz.fuzz
|
||||
|
||||
import comicapi.data
|
||||
|
||||
try:
|
||||
import icu
|
||||
|
||||
del icu
|
||||
icu_available = True
|
||||
except ImportError:
|
||||
icu_available = False
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UtilsVars:
|
||||
already_fixed_encoding = False
|
||||
def _custom_key(tup):
|
||||
lst = []
|
||||
for x in natsort.os_sort_keygen()(tup):
|
||||
ret = x
|
||||
if len(x) > 1 and isinstance(x[1], int) and isinstance(x[0], str) and x[0] == "":
|
||||
ret = ("a", *x[1:])
|
||||
|
||||
lst.append(ret)
|
||||
return tuple(lst)
|
||||
|
||||
|
||||
def os_sorted(lst: Iterable) -> Iterable:
|
||||
key = _custom_key
|
||||
if icu_available or platform.system() == "Windows":
|
||||
key = natsort.os_sort_keygen()
|
||||
return sorted(lst, key=key)
|
||||
|
||||
|
||||
def combine_notes(existing_notes: str | None, new_notes: str | None, split: str) -> str:
|
||||
|
@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import localefix
|
||||
from comictaggerlib.main import App
|
||||
|
||||
if __name__ == "__main__":
|
||||
localefix.configure_locale()
|
||||
|
||||
App().run()
|
@ -9,7 +9,7 @@ block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(
|
||||
["comictagger.py"],
|
||||
["comictaggerlib/__main__.py"],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
|
5
comictaggerlib/__main__.py
Normal file
5
comictaggerlib/__main__.py
Normal file
@ -0,0 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from comictaggerlib.main import main
|
||||
|
||||
main()
|
@ -73,12 +73,12 @@ try:
|
||||
return True
|
||||
return super().event(event)
|
||||
|
||||
except ImportError as e:
|
||||
except ImportError:
|
||||
|
||||
def show_exception_box(log_msg: str) -> None:
|
||||
...
|
||||
|
||||
logger.error(str(e))
|
||||
logger.exception("Qt unavailable")
|
||||
qt_available = False
|
||||
|
||||
|
||||
|
@ -17,8 +17,12 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import locale
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import settngs
|
||||
@ -48,6 +52,49 @@ except Exception:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def _lang_code_mac() -> str:
|
||||
"""
|
||||
stolen from https://github.com/mu-editor/mu
|
||||
Returns the user's language preference as defined in the Language & Region
|
||||
preference pane in macOS's System Preferences.
|
||||
"""
|
||||
|
||||
# Uses the shell command `defaults read -g AppleLocale` that prints out a
|
||||
# language code to standard output. Assumptions about the command:
|
||||
# - It exists and is in the shell's PATH.
|
||||
# - It accepts those arguments.
|
||||
# - It returns a usable language code.
|
||||
#
|
||||
# Reference documentation:
|
||||
# - The man page for the `defaults` command on macOS.
|
||||
# - The macOS underlying API:
|
||||
# https://developer.apple.com/documentation/foundation/nsuserdefaults.
|
||||
|
||||
lang_detect_command = "defaults read -g AppleLocale"
|
||||
|
||||
status, output = subprocess.getstatusoutput(lang_detect_command)
|
||||
if status == 0:
|
||||
# Command was successful.
|
||||
lang_code = output
|
||||
else:
|
||||
logging.warning("Language detection command failed: %r", output)
|
||||
lang_code = ""
|
||||
|
||||
return lang_code
|
||||
|
||||
|
||||
def configure_locale() -> None:
|
||||
if sys.platform == "darwin" and "LANG" not in os.environ:
|
||||
code = _lang_code_mac()
|
||||
if code != "":
|
||||
os.environ["LANG"] = f"{code}.utf-8"
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "")
|
||||
sys.stdout.reconfigure(encoding=sys.getdefaultencoding()) # type: ignore[attr-defined]
|
||||
sys.stderr.reconfigure(encoding=sys.getdefaultencoding()) # type: ignore[attr-defined]
|
||||
sys.stdin.reconfigure(encoding=sys.getdefaultencoding()) # type: ignore[attr-defined]
|
||||
|
||||
|
||||
def update_publishers(config: settngs.Config[settngs.Namespace]) -> None:
|
||||
json_file = config[0].runtime_config.user_config_dir / "publishers.json"
|
||||
if json_file.exists():
|
||||
@ -66,6 +113,7 @@ class App:
|
||||
self.config_load_success = False
|
||||
|
||||
def run(self) -> None:
|
||||
configure_locale()
|
||||
conf = self.initialize()
|
||||
self.initialize_dirs(conf.config)
|
||||
self.load_plugins(conf)
|
||||
|
50
localefix.py
50
localefix.py
@ -1,50 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def _lang_code_mac() -> str:
|
||||
"""
|
||||
stolen from https://github.com/mu-editor/mu
|
||||
Returns the user's language preference as defined in the Language & Region
|
||||
preference pane in macOS's System Preferences.
|
||||
"""
|
||||
|
||||
# Uses the shell command `defaults read -g AppleLocale` that prints out a
|
||||
# language code to standard output. Assumptions about the command:
|
||||
# - It exists and is in the shell's PATH.
|
||||
# - It accepts those arguments.
|
||||
# - It returns a usable language code.
|
||||
#
|
||||
# Reference documentation:
|
||||
# - The man page for the `defaults` command on macOS.
|
||||
# - The macOS underlying API:
|
||||
# https://developer.apple.com/documentation/foundation/nsuserdefaults.
|
||||
|
||||
lang_detect_command = "defaults read -g AppleLocale"
|
||||
|
||||
status, output = subprocess.getstatusoutput(lang_detect_command)
|
||||
if status == 0:
|
||||
# Command was successful.
|
||||
lang_code = output
|
||||
else:
|
||||
logging.warning("Language detection command failed: %r", output)
|
||||
lang_code = ""
|
||||
|
||||
return lang_code
|
||||
|
||||
|
||||
def configure_locale() -> None:
|
||||
if sys.platform == "darwin" and "LANG" not in os.environ:
|
||||
code = _lang_code_mac()
|
||||
if code != "":
|
||||
os.environ["LANG"] = f"{code}.utf-8"
|
||||
|
||||
locale.setlocale(locale.LC_ALL, "")
|
||||
sys.stdout.reconfigure(encoding=sys.getdefaultencoding()) # type: ignore[attr-defined]
|
||||
sys.stderr.reconfigure(encoding=sys.getdefaultencoding()) # type: ignore[attr-defined]
|
||||
sys.stdin.reconfigure(encoding=sys.getdefaultencoding()) # type: ignore[attr-defined]
|
2
setup.py
2
setup.py
@ -36,7 +36,7 @@ install_requires = read("requirements.txt").splitlines()
|
||||
extras_require = {}
|
||||
extra_req_files = glob.glob("requirements-*.txt")
|
||||
for extra_req_file in extra_req_files:
|
||||
name = os.path.splitext(extra_req_file)[0].replace("requirements-", "", 1)
|
||||
name = os.path.splitext(extra_req_file)[0].removeprefix("requirements-")
|
||||
extras_require[name] = read(extra_req_file).splitlines()
|
||||
|
||||
# If there are any extras, add a catch-all case that includes everything.
|
||||
|
@ -7,6 +7,46 @@ import pytest
|
||||
import comicapi.utils
|
||||
|
||||
|
||||
def test_os_sorted():
|
||||
page_name_list = [
|
||||
"cover.jpg",
|
||||
"Page1.jpeg",
|
||||
"!cover.jpg",
|
||||
"page4.webp",
|
||||
"test/!cover.tar.gz",
|
||||
"!cover.tar.gz",
|
||||
"00.jpg",
|
||||
"ignored.txt",
|
||||
"page0.jpg",
|
||||
"test/00.tar.gz",
|
||||
".ignored.jpg",
|
||||
"Page3.gif",
|
||||
"!cover.tar.gz",
|
||||
"Page2.png",
|
||||
"page10.jpg",
|
||||
"!cover",
|
||||
]
|
||||
|
||||
assert comicapi.utils.os_sorted(page_name_list) == [
|
||||
"!cover",
|
||||
"!cover.jpg",
|
||||
"!cover.tar.gz",
|
||||
"!cover.tar.gz", # Depending on locale punctuation or numbers might come first (Linux, MacOS)
|
||||
".ignored.jpg",
|
||||
"00.jpg",
|
||||
"cover.jpg",
|
||||
"ignored.txt",
|
||||
"page0.jpg",
|
||||
"Page1.jpeg",
|
||||
"Page2.png",
|
||||
"Page3.gif",
|
||||
"page4.webp",
|
||||
"page10.jpg",
|
||||
"test/!cover.tar.gz",
|
||||
"test/00.tar.gz",
|
||||
]
|
||||
|
||||
|
||||
def test_recursive_list_with_file(tmp_path) -> None:
|
||||
foo_png = tmp_path / "foo.png"
|
||||
foo_png.write_text("not a png")
|
||||
|
Loading…
Reference in New Issue
Block a user