content: [project]
  name = "mitmproxy"
  description = "An interactive, SSL/TLS-capable intercepting proxy for HTTP/1, HTTP/2, and WebSockets."
  readme = "README.md"
  requires-python = ">=3.12"
  license = {file="LICENSE"}
  authors = [{name = "Aldo Cortesi", email = "aldo@corte.si"}]
  maintainers = [{name = "Maximilian Hils", email = "mitmproxy@maximilianhils.com"}]
  dynamic = ["version"]
  
  classifiers = [
      "License :: OSI Approved :: MIT License",
      "Development Status :: 5 - Production/Stable",
      "Environment :: Console :: Curses",
      "Operating System :: MacOS",
      "Operating System :: POSIX",
      "Operating System :: Microsoft :: Windows",
      "Programming Language :: Python :: 3 :: Only",
      "Programming Language :: Python :: 3.12",
      "Programming Language :: Python :: 3.13",
      "Programming Language :: Python :: Implementation :: CPython",
      "Topic :: Security",
      "Topic :: Internet :: WWW/HTTP",
      "Topic :: Internet :: Proxy Servers",
      "Topic :: System :: Networking :: Monitoring",
      "Topic :: Software Development :: Testing",
      "Typing :: Typed",
  ]
  
  # https://packaging.python.org/en/latest/discussions/install-requires-vs-requirements/#install-requires
  # It is not considered best practice to use install_requires to pin dependencies to specific versions.
  dependencies = [
      "aioquic>=1.2.0,<=1.2.0",
      "argon2-cffi>=23.1.0,<=25.1.0",
      "asgiref>=3.2.10,<=3.9.1",
      "bcrypt>=5.0.0,<=5.0.0",
      "Brotli>=1.0,<=1.1.0",
      "certifi>=2019.9.11",  # no upper bound here to get latest CA bundle
      "cryptography>=42.0,<45.1",  # relaxed upper bound here to get security fixes
      "flask>=3.0,<=3.1.2",
      "h11>=0.16.0,<=0.16.0",
      "h2>=4.3.0,<=4.3.0",
      "hyperframe>=6.0,<=6.1.0",
      "kaitaistruct>=0.10,<=0.10",
      "ldap3>=2.8,<=2.9.1",
      "mitmproxy_rs>=0.12.6,<0.13",  # relaxed upper bound here: we control this
      "msgpack>=1.0.0,<=1.1.1",
      "pydivert>=2.0.3,<=2.1.0; sys_platform == 'win32'",
      "pyOpenSSL>=24.3,<=25.1.0",
      "pyparsing>=2.4.2,<=3.2.3",
      "pyperclip<=1.9.0,>=1.9.0",
      "ruamel.yaml>=0.18.10,<=0.18.15",
      "sortedcontainers>=2.3,<=2.4.0",
      "tornado>=6.5.0,<=6.5.2",
      "typing-extensions>=4.13.2,<=4.14; python_version < '3.13'",
      "urwid>=2.6.14,<=2.6.16",
      "wsproto>=1.0,<=1.2.0",
      "publicsuffix2>=2.20190812,<=2.20191221",
      "zstandard>=0.15,<=0.24.0",
  ]
  
  [dependency-groups]
  dev = [
      "click==8.2.1",
      "hypothesis==6.130.6",
      "maturin==1.9.3",
      "pdoc==15.0.4",
      "pyinstaller==6.15.0",
      "pyinstaller-hooks-contrib==2025.8",
      "pytest-asyncio==1.1.0",
      "pytest-cov==6.2.1",
      "pytest-timeout==2.4.0",
      "pytest-xdist==3.8.0",
      "pytest==8.4.1",
      "requests==2.32.5",
      "wheel==0.45.1",
      "build==1.3.0",
      "mypy==1.17.1",
      "types-requests==2.32.4.20250809",
      {include-group = "tox"},
      {include-group = "ruff"},
  ]
  tox = [
      "tox==4.28.4",
      "tox-uv==1.28.0",
  ]
  ruff = [
      "ruff==0.12.10",
  ]
  deploy = [
      "awscli==1.42.16",
      "twine==6.1.0",
  ]
  
  [project.urls]
  Homepage = "https://mitmproxy.org"
  Source = "https://github.com/mitmproxy/mitmproxy/"
  Documentation = "https://docs.mitmproxy.org/stable/"
  Issues = "https://github.com/mitmproxy/mitmproxy/issues"
  
  [project.scripts]
  mitmproxy = "mitmproxy.tools.main:mitmproxy"
  mitmdump = "mitmproxy.tools.main:mitmdump"
  mitmweb = "mitmproxy.tools.main:mitmweb"
  
  [project.entry-points.pyinstaller40]
  hook-dirs = "mitmproxy.utils.pyinstaller:hook_dirs"
  
  [build-system]
  requires = ["setuptools"]
  build-backend = "setuptools.build_meta"
  
  [tool.setuptools.dynamic]
  version = {attr = "mitmproxy.version.VERSION"}
  
  [tool.setuptools.packages.find]
  include = ["mitmproxy*"]
  
  [tool.coverage.run]
  branch = false
  omit = [
      "*contrib*",
      "*tnetstring*",
      "*platform*",
      "*main.py",
  ]
  
  [tool.coverage.report]
  show_missing = true
  exclude_lines = [
      "pragma: no cover",
      "raise NotImplementedError",
      "raise AssertionError",
      "if typing.TYPE_CHECKING:",
      "if TYPE_CHECKING:",
      "@overload",
      "@abstractmethod",
      "assert_never",
      "\\.\\.\\.",
  ]
  
  [tool.pytest.ini_options]
  asyncio_mode = "auto"
  asyncio_default_fixture_loop_scope = "function"
  testpaths = "test"
  addopts = "--capture=no --color=yes"
  filterwarnings = [
      "ignore::DeprecationWarning:tornado.*:",
      "ignore:datetime.datetime.utcnow:DeprecationWarning:aioquic.*:",
      "error::RuntimeWarning",
      "error::pytest.PytestUnraisableExceptionWarning",
  ]
  
  [tool.pytest.individual_coverage]
  exclude = [
    "mitmproxy/addons/__init__.py",
    "mitmproxy/addons/onboarding.py",
    "mitmproxy/addons/onboardingapp/__init__.py",
    "mitmproxy/contentviews/__init__.py",
    "mitmproxy/contentviews/base.py",
    "mitmproxy/contentviews/grpc.py",
    "mitmproxy/contrib/*",
    "mitmproxy/ctx.py",
    "mitmproxy/exceptions.py",
    "mitmproxy/flow.py",
    "mitmproxy/io/io.py",
    "mitmproxy/io/tnetstring.py",
    "mitmproxy/log.py",
    "mitmproxy/master.py",
    "mitmproxy/net/check.py",
    "mitmproxy/net/http/cookies.py",
    "mitmproxy/net/http/multipart.py",
    "mitmproxy/net/tls.py",
    "mitmproxy/platform/__init__.py",
    "mitmproxy/platform/linux.py",
    "mitmproxy/platform/openbsd.py",
    "mitmproxy/platform/osx.py",
    "mitmproxy/platform/pf.py",
    "mitmproxy/platform/windows.py",
    "mitmproxy/proxy/__init__.py",
    "mitmproxy/proxy/layers/http/__init__.py",
    "mitmproxy/proxy/layers/http/_base.py",
    "mitmproxy/proxy/layers/http/_events.py",
    "mitmproxy/proxy/layers/http/_hooks.py",
    "mitmproxy/proxy/layers/http/_http1.py",
    "mitmproxy/proxy/layers/http/_http2.py",
    "mitmproxy/proxy/layers/http/_http3.py",
    "mitmproxy/proxy/layers/http/_http_h2.py",
    "mitmproxy/proxy/layers/http/_http_h3.py",
    "mitmproxy/proxy/layers/http/_upstream_proxy.py",
    "mitmproxy/proxy/layers/tls.py",
    "mitmproxy/proxy/server.py",
    "mitmproxy/test/taddons.py",
    "mitmproxy/test/tflow.py",
    "mitmproxy/test/tutils.py",
    "mitmproxy/tools/console/commander/commander.py",
    "mitmproxy/tools/console/commandexecutor.py",
    "mitmproxy/tools/console/commands.py",
    "mitmproxy/tools/console/common.py",
    "mitmproxy/tools/console/consoleaddons.py",
    "mitmproxy/tools/console/eventlog.py",
    "mitmproxy/tools/console/flowdetailview.py",
    "mitmproxy/tools/console/flowlist.py",
    "mitmproxy/tools/console/flowview.py",
    "mitmproxy/tools/console/grideditor/base.py",
    "mitmproxy/tools/console/grideditor/col_bytes.py",
    "mitmproxy/tools/console/grideditor/col_subgrid.py",
    "mitmproxy/tools/console/grideditor/col_text.py",
    "mitmproxy/tools/console/grideditor/col_viewany.py",
    "mitmproxy/tools/console/grideditor/editors.py",
    "mitmproxy/tools/console/help.py",
    "mitmproxy/tools/console/keybindings.py",
    "mitmproxy/tools/console/keymap.py",
    "mitmproxy/tools/console/layoutwidget.py",
    "mitmproxy/tools/console/master.py",
    "mitmproxy/tools/console/options.py",
    "mitmproxy/tools/console/overlay.py",
    "mitmproxy/tools/console/quickhelp.py",
    "mitmproxy/tools/console/searchable.py",
    "mitmproxy/tools/console/signals.py",
    "mitmproxy/tools/console/statusbar.py",
    "mitmproxy/tools/console/tabs.py",
    "mitmproxy/tools/console/window.py",
    "mitmproxy/tools/main.py",
    "mitmproxy/tools/web/app.py",
    "mitmproxy/tools/web/master.py",
    "mitmproxy/tools/web/webaddons.py",
    "mitmproxy/utils/bits.py",
    "mitmproxy/utils/pyinstaller/*",
    "mitmproxy/utils/vt_codes.py",
  ]
  
  [tool.mypy]
  check_untyped_defs = true
  ignore_missing_imports = true
  files = [
      "mitmproxy",
      "examples/addons",
      "release/*.py",
  ]
  exclude = [
      "^docs/",
      "^release/build/",
      "^examples/contrib/",
  ]
  
  [[tool.mypy.overrides]]
  module = "mitmproxy.contrib.*"
  ignore_errors = true
  
  [[tool.mypy.overrides]]
  module = "tornado.*"
  ignore_errors = true
  
  [[tool.mypy.overrides]]
  module = "test.*"
  ignore_errors = true
  
  [tool.ruff]
  extend-exclude = ["mitmproxy/contrib/"]
  
  [tool.ruff.lint]
  select = ["E", "F", "I", "TID251"]
  ignore = ["F541", "E501"]
  
  [tool.ruff.lint.per-file-ignores]
  "examples/**" = ["TID251"]
  "test/**" = ["TID251"]
  
  [tool.ruff.lint.flake8-tidy-imports.banned-api]
  "asyncio.create_task".msg = "Use mitmproxy.utils.asyncio_utils.create_task instead to avoid GC footgun."
  
  
  [tool.ruff.lint.isort]
  # these rules are a bit weird, but they mimic our existing reorder_python_imports style.
  # if we break compatibility here, consider removing all customization + enforce absolute imports.
  force-single-line = true
  order-by-type = false
  section-order = ["future", "standard-library", "third-party", "local-folder","first-party"]
  no-lines-before = ["first-party"]
  known-first-party = ["test", "mitmproxy", "mitmproxy_rs"]
  
  [tool.tox]
  env_list = ["lint", "mypy", "py"]
  
  [tool.tox.env_run_base]
  runner = "uv-venv-lock-runner"
  package = "editable"
  dependency_groups = ["dev"]
  commands = [
      ["mitmdump", "--version"],
      ["pytest",
          "-vv",
          "--cov-report", "xml",
          "--continue-on-collection-errors",
          "--cov=mitmproxy",
          "--cov=release",
          { replace = "posargs", default = ["--timeout", "60"], extend = true }
      ],
  ]
  
  [tool.tox.env.test-offline]
  commands = [["bash", "test/run-tests-offline.sh"]]
  allowlist_externals = ["bash"]
  
  [tool.tox.env.lint]
  commands = [["ruff", "check",  "."]]
  dependency_groups = ["ruff"]
  
  [tool.tox.env.filename_matching]
  commands = [["python", "./test/filename_matching.py"]]
  dependency_groups = []
  
  [tool.tox.env.mypy]
  commands = [["mypy"]]
  
  [tool.tox.env.individual_coverage]
  commands = [["python", "./test/individual_coverage.py", { default = [], replace = "posargs", extend = true }]]
  
  [tool.tox.env.old-dependencies]
  uv_resolution = "lowest-direct"
  runner = "uv-venv-runner"
  
  [tool.tox.env.fix]
  commands = [
      ["ruff", "check", "--fix-only", "."],
      ["ruff", "format", "."],
  ]
  dependency_groups = ["ruff"]
  