[project] name = "theHarvester" description = "theHarvester is a very simple, yet effective tool designed to be used in the early stages of a penetration test" readme = "README.md" license = "GPL-2.0-only" authors = [ { name = "Christian Martorella", email = "cmartorella@edge-security.com" }, { name = "Jay Townsend", email = "jay@cybermon.uk" }, { name = "Matt Brown", email = "36310667+NotoriousRebel@users.noreply.github.com" }, ] requires-python = ">=3.14" urls.Homepage = "https://github.com/laramies/theHarvester" classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.14", "Operating System :: OS Independent", ] dynamic = ["version"] dependencies = [ "aiodns==4.0.4", "aiohttp==3.14.3", "aiohttp-socks==0.11.0", "aiosqlite==0.22.1", "beautifulsoup4==4.15.0", "certifi==2026.6.17", "fastapi==0.138.1", "netaddr==1.3.0", "playwright==1.60.0", "PyYAML==6.0.3", "python-dateutil==2.9.0.post0", "sqlalchemy==2.0.51", "uvicorn==0.52.1", "uvloop==0.22.1; platform_system != 'Windows'", "winloop==0.6.3; platform_system == 'Windows'", ] [dependency-groups] dev = [ "httpx==0.28.1", "mypy==2.1.0", "pytest==9.1.1", "pytest-asyncio==1.4.0", "pytest-playwright==0.8.0", "types-python-dateutil==2.9.0.20260518", "types-PyYAML==6.0.12.20250915", "ruff==0.16.1", ] [project.scripts] theHarvester = "theHarvester.theHarvester:main" harvestview = "theHarvester.harvestview:main" [tool.pytest.ini_options] minversion = "8.3.3" asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" addopts = "--no-header --strict-markers -m 'not harvestview_e2e'" markers = [ "live_network: contacts an external service and runs only with --run-live-network", "provider_contract(source): deterministic offline contract for one canonical discovery source", "harvestview_e2e: real-browser tests against an isolated local HarvestView server", ] testpaths = ["tests"] [build-system] requires = ["flit_core >=3.11,<4"] build-backend = "flit_core.buildapi" [tool.mypy] python_version = "3.14" warn_unused_configs = true ignore_missing_imports = true show_traceback = true show_error_codes = true namespace_packages = true check_untyped_defs = true [tool.uv] python-preference = "managed" exclude-newer = "7 days" [tool.uv.pip] python-version = "3.14" [tool.ruff] # Exclude a variety of commonly ignored directories. exclude = [ "tests", ".eggs", ".git", ".git-rewrite", ".mypy_cache", ".pyenv", ".pytest_cache", ".pytype", ".ruff_cache", ".github", ".venv", ".vscode", ".idea", "__pypackages__", "build", "dist", "site-packages", "venv", ] line-length = 130 target-version = "py314" show-fixes = true [tool.ruff.lint] select = ["E", "F", "N", "I", "B", "UP", "FA", "FAST", "RUF", "PT", "TC", "FURB", "ASYNC", "T20" ] ignore = [ "B018", "B904", "E501", "N999", ] # Allow fix for all enabled rules (when `--fix`) is provided. fixable = ["ALL"] unfixable = [] # Allow unused variables when underscore-prefixed. dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" [tool.ruff.format] # Like Black, use double quotes for strings. quote-style = "single" indent-style = "space" # Like Black, respect magic trailing commas. skip-magic-trailing-comma = false # Like Black, automatically detect the appropriate line ending. line-ending = "auto"