[project] name = "calibre" description = "The one stop solution to all your e-book needs" readme = "README.md" requires-python = ">=3.10" license = {text="GPL-3.0-only"} dynamic = ["version"] dependencies = [ "six == 1.16.0", "unrardll == 0.1.7", "lxml == 6.0.1", "pychm == 0.8.6", "html5-parser == 0.4.12", "css-parser == 1.0.10", "python-dateutil == 2.8.2", "jeepney == 0.8.0", "dnspython == 2.6.1", "mechanize == 0.4.8", "feedparser == 6.0.10", "sgmllib3k == 1.0.0", "Markdown == 3.4.4", "html2text == 2020.1.16", "soupsieve == 2.5", "beautifulsoup4 == 4.12.2", "regex == 2023.8.8", "chardet == 5.2.0", "msgpack == 1.0.7", "Pygments == 2.16.1", "pycryptodome == 3.19.1", "apsw == 3.50.4.0", "webencodings == 0.5.1", "html5lib == 1.1", "pillow == 10.3.0", "netifaces == 0.11.0", "psutil == 5.9.5", "ifaddr == 0.2.0", "texttable == 1.6.7", "multivolumefile == 0.2.3", "Brotli == 1.1.0", "pyzstd == 0.17.0", "pyppmd == 1.2.0", "pybcj == 1.0.1", "inflate64 == 1.0.3", "py7zr == 1.0.0", "jaconv == 0.4.0", "wrapt == 1.16.0", "Deprecated == 1.2.14", "pykakasi == 2.3.0", "zeroconf == 0.115.0", "fonttools == 4.47.0", "lxml_html_clean == 0.4.2", "PyQt6_sip == 13.10.0", "PyQt6 == 6.8.1", "PyQt6_WebEngine == 6.8.0", "MacFSEvents == 0.8.4; sys_platform == 'darwin'", "xxhash == 3.3.0", ] [project.urls] Homepage = "https://calibre-ebook.com" FAQ = "https://manual.calibre-ebook.com/faq.html" Documentation = "https://manual.calibre-ebook.com" Repository = "https://github.com/kovidgoyal/calibre.git" Issues = "https://bugs.launchpad.net/calibre" Changelog = "https://github.com/kovidgoyal/calibre/blob/master/Changelog.txt" Community-Forum = "https://www.mobileread.com/forums/forumdisplay.php?f=166" [build-system] requires = [ "installer == 0.7.0", # Needed for installing pure python packages at build time "packaging == 23.1", # Needed for build which is needed for setuptools "pyproject_hooks == 1.0.0", # Needed for build which is needed for setuptools "wheel == 0.41.2", # Needed for build which is needed for setuptools "build == 1.0.3", # Needed for build which is needed for setuptools "setuptools == 78.1.1", # Some packages (xxhash/py7zr/etc) erroneously declare this as a dependency even # though it is needed only for sdist not building wheels "setuptools_scm == 8.0.3", "poetry_core == 1.7.0", # needed for building zeroconf "ply == 3.11", # needed for sip "sip == 6.10.0", "PyQt_builder == 1.18.1", ] [tool.ruff] line-length = 160 builtins = ['_', 'I', 'P'] include = ['*.py', '*.recipe'] exclude = [ "*_ui.py", "bypy/*", "setup/polib.py", "setup/linux-installer.py", "src/css_selectors/*", "src/polyglot/*", "src/templite/*", "src/tinycss/*", ] preview = true [tool.ruff.format] quote-style = 'single' [tool.ruff.lint] explicit-preview-rules = true ignore = [ 'E402', 'E741', 'UP012', 'UP030', 'C413', 'C420', 'PIE790', 'ISC003', 'RUF001', 'RUF002', 'RUF003', 'RUF005', 'RUF012', 'RUF013', 'RUF015', 'RUF031', 'RUF100', 'RUF059', # unused unpacked variable ] select = [ 'E', 'F', 'I', 'W', 'INT', 'Q', 'UP', 'YTT', 'TID', 'C4', 'COM818', 'PIE', 'RET501', 'ISC', 'RUF', # note: RUF can flag many unsolicited errors # preview rules 'RUF051', 'RUF056', # useless dict operation 'RUF055', # unnecessary regex 'RUF039', # always use raw-string for regex 'RUF047', # needless else 'E302', 'E303', 'E304', 'E305', 'W391', # blank-line standard 'E111', 'E112', 'E113', 'E117', # code indentation 'E114', 'E115', 'E116', 'E261', 'E262', 'E265', # comment formatting 'E201', 'E202', 'E211', 'E251', 'E275', # various whitespace ] unfixable = ['PIE794', 'ISC001'] [tool.ruff.lint.per-file-ignores] "recipes/*" = ['UP'] "setup/changelog.py" = ['ISC001'] "src/calibre/ebooks/unihandecode/*codepoints.py" = ['E501'] "src/calibre/ebooks/metadata/sources/*" = ['UP'] "src/calibre/gui2/store/stores/*" = ['UP'] "src/qt/*.py" = ['I', 'E302'] "src/qt/*.pyi" = ['I'] [tool.ruff.lint.isort] detect-same-package = true extra-standard-library = ["aes", "elementmaker", "encodings"] known-first-party = ["calibre_extensions", "calibre_plugins", "polyglot"] known-third-party = ["odf", "qt", "templite", "tinycss", "css_selectors"] relative-imports-order = "closest-to-furthest" split-on-trailing-comma = false section-order = ['__python__', "future", "standard-library", "third-party", "first-party", "local-folder"] [tool.ruff.lint.isort.sections] '__python__' = ['__python__'] [tool.ruff.lint.flake8-comprehensions] allow-dict-calls-with-keyword-arguments = true [tool.ruff.lint.flake8-quotes] avoid-escape = true docstring-quotes = 'single' inline-quotes = 'single' multiline-quotes = 'single' [tool.codespell] count = false summary = false quiet-level = 3 regex = '''\b[\w\-'’]+\b''' ignore-regex = '''\b[\w\-'’]*&(amp;)?[\w\-'’]*\b''' builtin = [ 'clear', 'rare', 'informal', 'code', ] exclude-file = "codespell.exclude" ignore-words-list = [ "alo", "ans", "clen", "eto", "fo", "nam", "nd", "som", "te", "atLeast", "Implementor", "implementor", "Implementors", "implementors", "missings", "re-use", "re-used", "re-using", "splited", "succeded", # code "ro", "ws", "deque", "assertIn", "atEnd", "errorString", "FocusIn", "iff", "lets", "lite", "UINT", "uInt", "uint", "KeyPair", "Keypair", "keypair", "seeked", "stdio", "thead", ] uri-ignore-words-list = '*' skip = [ "*.svg", "*.rcc", "*_ui.py", "./src/calibre/ebooks/rtf2xml/char_set.py", "./src/calibre/ebooks/unihandecode/*", "./src/calibre/ebooks/html_entities.h", "./src/calibre/ebooks/html_entities.py", "./src/calibre/utils/icu_test.py", "./src/calibre/utils/search_query_parser_test.py", "./Changelog.old.txt", "./COPYRIGHT", "./LICENSE", "./LICENSE.rtf", "./session.vim", "./build/*", "./docs/*", "./nbproject/*", "./recipes/*", "./translations/*", "./tags/*", "./manual/generated/*", "./manual/locale/*", "./resources/dictionaries/*", "./resources/localization/*", "./resources/hyphenation/*", "./resources/mathjax/*", "./resources/builtin_recipes.xml", "./resources/changelog.json", "./resources/editor.js", "./resources/editor-functions.json", "./resources/mime.types", "./resources/piper-voices.json", "./resources/stylelint-bundle.min.js", "./resources/user-manual-translation-stats.json", "./resources/template-functions.json", "./resources/viewer.js", "./resources/viewer.html", "./resources/content-server/index-generated.html", "./setup/installer/*", "./setup/pyqt_enums/*", "./setup/lc_data.py", "./setup/linux-installer.py", "./src/css_selectors/*", "./src/polyglot/*", "./src/templite/*", "./src/tinycss/*", "./src/unicode_names/*", ] [tool.flynt] line-length = 400 # over value to catch every case transform-format = false # don't transform already existing format call exclude = [ "bypy/", "setup/polib.py", "setup/linux-installer.py", "src/calibre/ebooks/metadata/sources/", "src/calibre/gui2/store/stores/", "src/css_selectors/", "src/polyglot/", "src/templite/", "src/tinycss/", ] [tool.pylsp-mypy] enabled = false