[build-system] # 77 is the first setuptools that accepts an SPDX `license` string with # `license-files` (PEP 639). requires = ["setuptools>=77"] build-backend = "setuptools.build_meta" [project] name = "memanga" # The version is set once, as `__version__` in memanga/__init__.py. dynamic = ["version"] description = "Automatic manga downloader with Kindle support" readme = "README.md" license = "MIT" license-files = ["LICENSE"] authors = [{name = "meellm"}] requires-python = ">=3.11" keywords = [ "manga", "manga-downloader", "comics", "kindle", "e-reader", "epub", "cbz", "pdf", ] classifiers = [ "Development Status :: 4 - Beta", "Environment :: Console", "Environment :: X11 Applications :: Qt", "Intended Audience :: End Users/Desktop", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Internet :: WWW/HTTP", "Topic :: Multimedia :: Graphics", "Topic :: Utilities", ] dependencies = [ "rich>=13.0.0", "pyyaml>=6.0", "requests>=2.28.0", # Security floor for the urllib3 that requests pulls in. "urllib3>=2.8.0", "img2pdf>=0.5.0", "Pillow>=10.0.0", "beautifulsoup4>=4.12.0", "playwright>=1.40.0", "cloudscraper>=1.2.71", "pikepdf>=8.0.0", "keyring>=24.0.0", "playwright-stealth>=2.0,<3", ] [project.optional-dependencies] # This file is the only place dependencies are declared. The pinned # installs in requirements/ are generated from it; after a change here run # `python scripts/lock_dependencies.py` (see CONTRIBUTING.md). # # The desktop app. The default install is the CLI only, for servers, # containers and scheduled checks. gui = ["PySide6>=6.5.0"] # The GUI tests and the desktop build need the app's Qt runtime. dev = [ "memanga[gui]", "pytest>=8.0", "pytest-qt>=4.4", "pytest-mock>=3.12", "pytest-env>=1.1", # Parses version specifiers in the dependency-declaration tests. "packaging>=21.0", # Runs unrelated test files in parallel: pytest -n auto "pytest-xdist>=3.5", # Coverage report: pytest --cov=memanga --cov-report=html "pytest-cov>=4.1", ] build = [ "memanga[gui]", "pyinstaller>=6.0,<7.0", "certifi>=2024.7.0", # Backs keyring's Windows Credential Manager backend. keyring already # requires it on Windows; it is listed so the frozen app keeps it even # if a keyring release dropped it, which would leave the app on # keyring's Null backend (saved email passwords silently lost). 'pywin32-ctypes>=0.2.0; sys_platform == "win32"', ] [project.urls] Homepage = "https://github.com/meellm/MeManga" Documentation = "https://github.com/meellm/MeManga/blob/main/docs/Guide.md" Repository = "https://github.com/meellm/MeManga" Issues = "https://github.com/meellm/MeManga/issues" Changelog = "https://github.com/meellm/MeManga/blob/main/CHANGELOG.md" Releases = "https://github.com/meellm/MeManga/releases" # memanga-gui stays a console script, not a gui-script: on Windows a # gui-script has no console, so the error printed without the gui extra # would not be seen. The release downloads are the windowed app. [project.scripts] memanga = "memanga.cli:main" memanga-gui = "memanga.gui:launch_gui" # Which versions requirements/*.txt pin: each package at its newest # release that fits the bounds above, as PyPI was at `resolve-at` (UTC), # or at the time listed for it below. Nothing else picks them, so # `python scripts/lock_dependencies.py --check` can regenerate the locks # and compare. To update a package, move its time (or `resolve-at` for # all the others) and regenerate. [tool.lock-dependencies] resolve-at = "2026-05-25T08:00:00Z" # Packages read from a later PyPI: the urllib3 security floor, the # certifi, Pillow and soupsieve releases with fixes for known # vulnerabilities (#385), the Linux keyring backend of the Docker image, # and the test and build tools with their own dependencies. [tool.lock-dependencies.resolve-package-at] certifi = "2026-11-02T00:00:00Z" cffi = "2026-11-02T00:00:00Z" coverage = "2026-11-02T00:00:00Z" cryptography = "2026-11-02T00:00:00Z" importlib-metadata = "2026-11-02T00:00:00Z" iniconfig = "2026-11-02T00:00:00Z" pillow = "2026-11-02T00:00:00Z" pluggy = "2026-11-02T00:00:00Z" pycparser = "2026-11-02T00:00:00Z" pyinstaller = "2026-11-02T00:00:00Z" pyinstaller-hooks-contrib = "2026-11-02T00:00:00Z" pytest = "2026-11-02T00:00:00Z" pytest-env = "2026-11-02T00:00:00Z" pytest-mock = "2026-11-02T00:00:00Z" python-dotenv = "2026-11-02T00:00:00Z" setuptools = "2026-11-02T00:00:00Z" soupsieve = "2026-11-02T00:00:00Z" urllib3 = "2026-11-02T00:00:00Z" zipp = "2026-11-02T00:00:00Z" [tool.setuptools.dynamic] version = {attr = "memanga.__version__"} [tool.setuptools.packages.find] include = ["memanga*"]