diff --git a/docs/source/installation.rst b/docs/source/installation.rst index d0a5413..021637f 100644 --- a/docs/source/installation.rst +++ b/docs/source/installation.rst @@ -56,6 +56,9 @@ If you encounter frequent false positive results, we recommend installing the la # install from pypi pip3 install maigret + # install with PDF report support + pip3 install maigret[pdf] + # usage maigret username diff --git a/maigret/report.py b/maigret/report.py index 2b6648c..1c131dc 100644 --- a/maigret/report.py +++ b/maigret/report.py @@ -79,7 +79,13 @@ def save_pdf_report(filename: str, context: dict): filled_template = template.render(**context) # moved here to speed up the launch of Maigret - from xhtml2pdf import pisa # type: ignore[import-untyped] + try: + from xhtml2pdf import pisa # type: ignore[import-untyped] + except ImportError: + raise ImportError( + "PDF report generation requires the 'xhtml2pdf' package. " + "Install it with: pip install maigret[pdf]" + ) with open(filename, "w+b") as f: pisa.pisaDocument(io.StringIO(filled_template), dest=f, default_css=css) diff --git a/opensuse.txt b/opensuse.txt index 5eb8e26..a70da86 100644 --- a/opensuse.txt +++ b/opensuse.txt @@ -8,7 +8,6 @@ aiodns>=3.0.0 aiohttp>=3.8.6 aiohttp-socks>=0.7.1 -arabic-reshaper~=3.0.0 async-timeout attrs>=22.2.0 certifi>=2023.7.22 @@ -24,9 +23,7 @@ MarkupSafe mock>=4.0.3 multidict pycountry>=22.3.5 -PyPDF2>=3.0.1 PySocks>=1.7.1 -python-bidi>=0.4.2 requests requests-futures>=1.0.0 six>=1.16.0 @@ -37,11 +34,12 @@ torrequest>=0.1.0 tqdm typing-extensions webencodings>=0.5.1 -svglib -xhtml2pdf~=0.2.11 XMind>=1.2.0 yarl networkx pyvis>=0.2.1 -reportlab cloudscraper>=1.2.71 +# Optional PDF dependencies (install separately for PDF report support): +# xhtml2pdf~=0.2.11 +# arabic-reshaper~=3.0.0 +# reportlab diff --git a/poetry.lock b/poetry.lock index b40f05d..a539bca 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.3 and should not be changed by hand. [[package]] name = "about-time" @@ -234,9 +234,10 @@ graphemeu = "0.7.2" name = "arabic-reshaper" version = "3.0.0" description = "Reconstruct Arabic sentences to be used in applications that do not support Arabic" -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "arabic_reshaper-3.0.0-py3-none-any.whl", hash = "sha256:3f71d5034bb694204a239a6f1ebcf323ac3c5b059de02259235e2016a1a5e2dc"}, {file = "arabic_reshaper-3.0.0.tar.gz", hash = "sha256:ffcd13ba5ec007db71c072f5b23f420da92ac7f268512065d49e790e62237099"}, @@ -267,9 +268,10 @@ tests = ["mypy (>=1.14.0)", "pytest", "pytest-asyncio"] name = "asn1crypto" version = "1.5.1" description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, @@ -852,9 +854,10 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""] name = "cryptography" version = "46.0.6" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -optional = false +optional = true python-versions = "!=3.9.0,!=3.9.1,>=3.8" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "cryptography-46.0.6-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:64235194bad039a10bb6d2d930ab3323baaec67e2ce36215fd0952fad0930ca8"}, {file = "cryptography-46.0.6-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:26031f1e5ca62fcb9d1fcb34b2b60b390d1aacaa15dc8b895a9ed00968b97b30"}, @@ -925,9 +928,10 @@ test-randomorder = ["pytest-randomly"] name = "cssselect2" version = "0.7.0" description = "CSS selectors for Python ElementTree" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "cssselect2-0.7.0-py3-none-any.whl", hash = "sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969"}, {file = "cssselect2-0.7.0.tar.gz", hash = "sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a"}, @@ -1072,9 +1076,10 @@ dotenv = ["python-dotenv"] name = "freetype-py" version = "2.5.1" description = "Freetype python bindings" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "freetype-py-2.5.1.zip", hash = "sha256:cfe2686a174d0dd3d71a9d8ee9bf6a2c23f5872385cf8ce9f24af83d076e2fbd"}, {file = "freetype_py-2.5.1-py3-none-macosx_10_9_universal2.whl", hash = "sha256:d01ded2557694f06aa0413f3400c0c0b2b5ebcaabeef7aaf3d756be44f51e90b"}, @@ -2089,9 +2094,10 @@ test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] name = "oscrypto" version = "1.3.0" description = "TLS (SSL) sockets, key generation, encryption, decryption, signing, verification and KDFs using the OS crypto libraries. Does not require a compiler, and relies on the OS for patching. Works on Windows, OS X and Linux/BSD." -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "oscrypto-1.3.0-py2.py3-none-any.whl", hash = "sha256:2b2f1d2d42ec152ca90ccb5682f3e051fb55986e1b170ebde472b133713e7085"}, {file = "oscrypto-1.3.0.tar.gz", hash = "sha256:6f5fef59cb5b3708321db7cca56aed8ad7e662853351e7991fcf60ec606d47a4"}, @@ -2262,6 +2268,7 @@ files = [ {file = "pillow-12.1.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:cb9bb857b2d057c6dfc72ac5f3b44836924ba15721882ef103cecb40d002d80e"}, {file = "pillow-12.1.1.tar.gz", hash = "sha256:9ad8fa5937ab05218e2b6a4cff30295ad35afd2f83ac592e68c0d871bb0fdbc4"}, ] +markers = {main = "extra == \"pdf\""} [package.extras] docs = ["furo", "olefile", "sphinx (>=8.2)", "sphinx-autobuild", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] @@ -2438,9 +2445,10 @@ tests = ["pytest"] name = "pycairo" version = "1.29.0" description = "Python interface for cairo" -optional = false +optional = true python-versions = ">=3.10" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "pycairo-1.29.0-cp310-cp310-win32.whl", hash = "sha256:96c67e6caba72afd285c2372806a0175b1aa2f4537aa88fb4d9802d726effcd1"}, {file = "pycairo-1.29.0-cp310-cp310-win_amd64.whl", hash = "sha256:65bddd944aee9f7d7d72821b1c87e97593856617c2820a78d589d66aa8afbd08"}, @@ -2634,9 +2642,10 @@ windows-terminal = ["colorama (>=0.4.6)"] name = "pyhanko" version = "0.25.3" description = "Tools for stamping and signing PDF files" -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "pyHanko-0.25.3-py3-none-any.whl", hash = "sha256:d66ec499f057191df100f322c2fd22949057a9b0d981f4e75bc077c1a817497f"}, {file = "pyhanko-0.25.3.tar.gz", hash = "sha256:e879fd44e20f4b7726e75c62e8c7b0c41ea41f8fa5bda626bc7d206ae3d30dec"}, @@ -2670,9 +2679,10 @@ xmp = ["defusedxml (>=0.7.1,<0.8.0)"] name = "pyhanko-certvalidator" version = "0.26.5" description = "Validates X.509 certificates and paths; forked from wbond/certvalidator" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "pyhanko_certvalidator-0.26.5-py3-none-any.whl", hash = "sha256:86a56df420bfb273ba881826b76245a53b2bd039fea7a7826231dbe76d761a8a"}, {file = "pyhanko_certvalidator-0.26.5.tar.gz", hash = "sha256:800f5a7744d23870a5203cb38007689902c79c44e7374dab0c9b02e1b1a89bd4"}, @@ -2709,9 +2719,10 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pypdf" version = "6.9.2" description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" -optional = false +optional = true python-versions = ">=3.9" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "pypdf-6.9.2-py3-none-any.whl", hash = "sha256:662cf29bcb419a36a1365232449624ab40b7c2d0cfc28e54f42eeecd1fd7e844"}, {file = "pypdf-6.9.2.tar.gz", hash = "sha256:7f850faf2b0d4ab936582c05da32c52214c2b089d61a316627b5bfb5b0dab46c"}, @@ -2728,25 +2739,6 @@ docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"] full = ["Pillow (>=8.0.0)", "cryptography"] image = ["Pillow (>=8.0.0)"] -[[package]] -name = "pypdf2" -version = "3.0.1" -description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "PyPDF2-3.0.1.tar.gz", hash = "sha256:a74408f69ba6271f71b9352ef4ed03dc53a31aa404d29b5d31f53bfecfee1440"}, - {file = "pypdf2-3.0.1-py3-none-any.whl", hash = "sha256:d16e4205cfee272fbdc0568b68d82be796540b1537508cef59388f839c191928"}, -] - -[package.extras] -crypto = ["PyCryptodome"] -dev = ["black", "flit", "pip-tools", "pre-commit (<2.18.0)", "pytest-cov", "wheel"] -docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"] -full = ["Pillow", "PyCryptodome"] -image = ["Pillow"] - [[package]] name = "pysocks" version = "1.7.1" @@ -2860,9 +2852,10 @@ pytest = ">=7.4,<8.2.2 || >8.2.2" name = "python-bidi" version = "0.6.7" description = "Python Bidi layout wrapping the Rust crate unicode-bidi" -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "python_bidi-0.6.7-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:94dbfd6a6ec0ae64b5262290bf014d6063f9ac8688bda9ec668dc175378d2c80"}, {file = "python_bidi-0.6.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8274ff02d447cca026ba00f56070ba15f95e184b2d028ee0e4b6c9813d2aaf9"}, @@ -3086,9 +3079,10 @@ networkx = ">=1.11" name = "pyyaml" version = "6.0.2" description = "YAML parser and emitter for Python" -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -3149,9 +3143,10 @@ files = [ name = "qrcode" version = "8.0" description = "QR Code image generator" -optional = false +optional = true python-versions = "<4.0,>=3.9" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "qrcode-8.0-py3-none-any.whl", hash = "sha256:9fc05f03305ad27a709eb742cf3097fa19e6f6f93bb9e2f039c0979190f6f1b1"}, {file = "qrcode-8.0.tar.gz", hash = "sha256:025ce2b150f7fe4296d116ee9bad455a6643ab4f6e7dce541613a4758cbce347"}, @@ -3176,6 +3171,7 @@ files = [ {file = "reportlab-4.4.10-py3-none-any.whl", hash = "sha256:5abc815746ae2bc44e7ff25db96814f921349ca814c992c7eac3c26029bf7c24"}, {file = "reportlab-4.4.10.tar.gz", hash = "sha256:5cbbb34ac3546039d0086deb2938cdec06b12da3cdb836e813258eb33cd28487"}, ] +markers = {main = "extra == \"pdf\""} [package.dependencies] charset-normalizer = "*" @@ -3266,9 +3262,10 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "rlpycairo" version = "0.4.0" description = "Plugin backend renderer for reportlab.graphics.renderPM" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "rlpycairo-0.4.0-py3-none-any.whl", hash = "sha256:3ce83825d5761c03bc3571c7db12a336ad51417e63189e3512d11b8922576aa9"}, {file = "rlpycairo-0.4.0.tar.gz", hash = "sha256:07c2c3c47828e83d9c09657a54ecbcd1a97aac9dc199780234456d3473faadc7"}, @@ -3354,9 +3351,10 @@ files = [ name = "svglib" version = "1.6.0" description = "A pure-Python library for reading and converting SVG" -optional = false +optional = true python-versions = ">=3.9" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "svglib-1.6.0-py3-none-any.whl", hash = "sha256:9aea8e2e81cbbf9c844460e4c7dc90e0a06aea7983bc201975ccd279d7b2d194"}, {file = "svglib-1.6.0.tar.gz", hash = "sha256:4c38a274a744ef0d1677f55d5d62fc0fb798819f813e52872a796e615741733d"}, @@ -3376,9 +3374,10 @@ dev = ["mypy (>=1.18.1)", "pre-commit (>=4.3.0)", "pytest (>=8.3.5)", "pytest-co name = "tinycss2" version = "1.4.0" description = "A tiny CSS parser" -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"}, {file = "tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"}, @@ -3506,10 +3505,10 @@ files = [ name = "tzdata" version = "2024.2" description = "Provider of IANA time zone data" -optional = false +optional = true python-versions = ">=2" groups = ["main"] -markers = "platform_system == \"Windows\"" +markers = "extra == \"pdf\" and platform_system == \"Windows\"" files = [ {file = "tzdata-2024.2-py2.py3-none-any.whl", hash = "sha256:a48093786cdcde33cad18c2555e8532f34422074448fbc874186f0abd79565cd"}, {file = "tzdata-2024.2.tar.gz", hash = "sha256:7d85cc416e9382e69095b7bdf4afd9e3880418a2413feec7069d533d6b4e31cc"}, @@ -3519,9 +3518,10 @@ files = [ name = "tzlocal" version = "5.2" description = "tzinfo object for the local timezone" -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, {file = "tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e"}, @@ -3537,9 +3537,10 @@ devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3) name = "uritools" version = "4.0.3" description = "URI parsing, classification and composition" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "uritools-4.0.3-py3-none-any.whl", hash = "sha256:bae297d090e69a0451130ffba6f2f1c9477244aa0a5543d66aed2d9f77d0dd9c"}, {file = "uritools-4.0.3.tar.gz", hash = "sha256:ee06a182a9c849464ce9d5fa917539aacc8edd2a4924d1b7aabeeecabcae3bc2"}, @@ -3609,9 +3610,10 @@ watchdog = ["watchdog (>=2.3)"] name = "xhtml2pdf" version = "0.2.17" description = "PDF generator using HTML and CSS" -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] +markers = "extra == \"pdf\"" files = [ {file = "xhtml2pdf-0.2.17-py3-none-any.whl", hash = "sha256:61a7ecac829fed518f7dbcb916e9d56bea6e521e02e54644b3d0ca33f0658315"}, {file = "xhtml2pdf-0.2.17.tar.gz", hash = "sha256:09ddbc31aa0e38a16f2f3cb73be89af5f7c968c17a564afdd685d280e39c526d"}, @@ -3790,7 +3792,10 @@ idna = ">=2.0" multidict = ">=4.0" propcache = ">=0.2.1" +[extras] +pdf = ["xhtml2pdf"] + [metadata] lock-version = "2.1" python-versions = "^3.10" -content-hash = "64280126055cdc808ace9bcaa01a1aa2ed2c1ee8892e4acf6a093441168535c8" +content-hash = "c7cc6e5d313cef228fbc78ee078748e94b65339a667f8e9fb5d396ce582a0793" diff --git a/pyproject.toml b/pyproject.toml index ede48c5..ed3ceb4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,6 @@ python = "^3.10" aiodns = ">=3,<5" aiohttp = "^3.12.14" aiohttp-socks = ">=0.10.1,<0.12.0" -arabic-reshaper = "^3.0.0" async-timeout = "^5.0.1" attrs = ">=25.3,<27.0" certifi = ">=2025.6.15,<2027.0.0" @@ -50,9 +49,7 @@ MarkupSafe = "^3.0.2" mock = "^5.1.0" multidict = "^6.6.3" pycountry = ">=24.6.1,<27.0.0" -PyPDF2 = "^3.0.1" PySocks = "^1.7.1" -python-bidi = "^0.6.3" requests = "^2.32.4" requests-futures = "^1.0.2" requests-toolbelt = "^1.0.0" @@ -64,17 +61,19 @@ torrequest = "^0.1.0" alive_progress = "^3.2.0" typing-extensions = "^4.14.1" webencodings = "^0.5.1" -xhtml2pdf = "^0.2.11" XMind = "^1.2.0" yarl = "^1.20.1" networkx = "^2.6.3" pyvis = "^0.3.2" -reportlab = "^4.4.3" cloudscraper = "^1.2.71" flask = {extras = ["async"], version = "^3.1.1"} asgiref = "^3.9.1" platformdirs = "^4.3.8" curl-cffi = ">=0.14,<1.0" +xhtml2pdf = {version = "^0.2.11", optional = true} + +[tool.poetry.extras] +pdf = ["xhtml2pdf"] [tool.poetry.group.dev.dependencies]