From c38c01fa4fc1c526d3e61ef3d468a76571b996fa Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Sun, 26 Mar 2023 19:40:32 +0200 Subject: [PATCH] Switch to pyproject.toml (#6016) * switch to pyproject.toml * fix mypy * fix pyinstaller --- .github/workflows/main.yml | 2 +- examples/addons/http-modify-form.py | 2 +- examples/addons/http-trailers.py | 1 + mitmproxy/tools/console/grideditor/base.py | 4 +- pyproject.toml | 217 +++++++++++++++++++++ release/build.py | 7 +- setup.cfg | 42 ---- setup.py | 123 ------------ tox.ini | 55 ------ 9 files changed, 225 insertions(+), 228 deletions(-) create mode 100644 pyproject.toml delete mode 100644 setup.py delete mode 100644 tox.ini diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0c8962700..cf70a1fcb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -100,7 +100,7 @@ jobs: with: path: release/installbuilder/setup key: installbuilder - - run: pip install -e .[dev] + - run: pip install .[dev] # pyinstaller 5.9 does not like pyproject.toml + editable installs. - run: python -u release/build.py standalone-binaries - if: matrix.platform == 'linux' run: python -u release/build.py --dirty wheel diff --git a/examples/addons/http-modify-form.py b/examples/addons/http-modify-form.py index b4ad178fd..d3c73a72a 100644 --- a/examples/addons/http-modify-form.py +++ b/examples/addons/http-modify-form.py @@ -9,4 +9,4 @@ def request(flow: http.HTTPFlow) -> None: else: # One can also just pass new form data. # This sets the proper content type and overrides the body. - flow.request.urlencoded_form = [("foo", "bar")] + flow.request.urlencoded_form = [("foo", "bar")] # type: ignore[assignment] diff --git a/examples/addons/http-trailers.py b/examples/addons/http-trailers.py index 4a7f56d61..2ac026cc0 100644 --- a/examples/addons/http-trailers.py +++ b/examples/addons/http-trailers.py @@ -33,6 +33,7 @@ def request(flow: http.HTTPFlow): def response(flow: http.HTTPFlow): + assert flow.response if flow.response.trailers: print("HTTP Trailers detected! Response contains:", flow.response.trailers) diff --git a/mitmproxy/tools/console/grideditor/base.py b/mitmproxy/tools/console/grideditor/base.py index 830f4bf7b..843b932f9 100644 --- a/mitmproxy/tools/console/grideditor/base.py +++ b/mitmproxy/tools/console/grideditor/base.py @@ -258,7 +258,7 @@ class BaseGridEditor(urwid.WidgetWrap): value: Any, callback: Callable[..., None], *cb_args, - **cb_kwargs + **cb_kwargs, ) -> None: value = self.data_in(copy.deepcopy(value)) self.master = master @@ -402,7 +402,7 @@ class GridEditor(BaseGridEditor): value: Any, callback: Callable[..., None], *cb_args, - **cb_kwargs + **cb_kwargs, ) -> None: super().__init__( master, self.title, self.columns, value, callback, *cb_args, **cb_kwargs diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..62b14b0d8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,217 @@ +[project] +name = "mitmproxy" +description = "An interactive, SSL/TLS-capable intercepting proxy for HTTP/1, HTTP/2, and WebSockets." +readme = "README.md" +requires-python = ">=3.10" +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.10", + "Programming Language :: Python :: 3.11", + "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_mitmproxy>=0.9.20,<0.10", + "asgiref>=3.2.10,<3.7", + "Brotli>=1.0,<1.1", + "certifi>=2019.9.11", # no semver here - this should always be on the last release! + "cryptography>=38.0,<40.1", + "flask>=1.1.1,<2.3", + "h11>=0.11,<0.15", + "h2>=4.1,<5", + "hyperframe>=6.0,<7", + "kaitaistruct>=0.10,<0.11", + "ldap3>=2.8,<2.10", + "mitmproxy_rs>=0.2.0b1,<0.3", + "msgpack>=1.0.0, <1.1.0", + "passlib>=1.6.5, <1.8", + "protobuf>=3.14,<5", + "pydivert>=2.0.3,<2.2; sys_platform == 'win32'", + "pyOpenSSL>=22.1,<23.2", + "pyparsing>=2.4.2,<3.1", + "pyperclip>=1.6.0,<1.9", + "ruamel.yaml>=0.16,<0.18", + "sortedcontainers>=2.3,<2.5", + "tornado>=6.2,<7", + "typing-extensions>=4.3,<4.6; python_version<'3.11'", + "urwid-mitmproxy>=2.1.1,<2.2", + "wsproto>=1.0,<1.3", + "publicsuffix2>=2.20190812,<3", + "zstandard>=0.11,<0.21", +] + +[project.optional-dependencies] +dev = [ + "click>=7.0,<8.2", + "hypothesis>=5.8,<7", + "pdoc>=4.0.0", + "pyinstaller==5.9.0", + "pytest-asyncio>=0.17,<0.21", + "pytest-cov>=2.7.1,<4.1", + "pytest-timeout>=1.3.3,<2.2", + "pytest-xdist>=2.1.0,<3.3", + "pytest>=6.1.0,<8", + "requests>=2.9.1,<3", + "tox>=3.5,<5", + "wheel>=0.36.2,<0.39", + "build>=0.10.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" +testpaths = "test" +addopts = "--capture=no --color=yes" +filterwarnings = [ + "ignore::DeprecationWarning:tornado.*:", +] + +[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.tox] +legacy_tox_ini = """ +[tox] +envlist = py, flake8, mypy +skipsdist = True +toxworkdir={env:TOX_WORK_DIR:.tox} + +[testenv] +deps = + -e .[dev] +setenv = HOME = {envtmpdir} +commands = + mitmdump --version + pytest --timeout 60 -vv --cov-report xml \ + --continue-on-collection-errors \ + --cov=mitmproxy --cov=release \ + --full-cov=mitmproxy/ \ + {posargs} + +[testenv:flake8] +deps = + flake8>=3.8.4,<6.1 + flake8-tidy-imports>=4.2.0,<5 +commands = + flake8 --jobs 8 mitmproxy examples test release {posargs} + +[testenv:filename_matching] +deps = +commands = + python ./test/filename_matching.py + +[testenv:mypy] +deps = + mypy==1.0.0 + types-certifi==2021.10.8.3 + types-Flask==1.1.6 + types-Werkzeug==1.0.9 + types-requests==2.28.11.11 + types-cryptography==3.3.23.2 + types-pyOpenSSL==23.0.0.2 + -e .[dev] + +commands = + mypy {posargs} + +[testenv:individual_coverage] +commands = + python ./test/individual_coverage.py {posargs} + +[testenv:wheeltest] +recreate = True +deps = +commands = + pip install {posargs} + mitmproxy --version + mitmdump --version + mitmweb --version +""" diff --git a/release/build.py b/release/build.py index 6f7f10c77..f14adaf0f 100644 --- a/release/build.py +++ b/release/build.py @@ -46,10 +46,9 @@ def wheel(): subprocess.check_call( [ "python", - "setup.py", - "-q", - "bdist_wheel", - "--dist-dir", + "-m", + "build", + "--outdir", DIST_DIR, ] ) diff --git a/setup.cfg b/setup.cfg index 5010e3f70..a482c0839 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,48 +5,6 @@ ignore = E203,E251,E252,C901,W292,W503,W504,W605,E741,E126,F541 exclude = mitmproxy/contrib/*,test/mitmproxy/data/*,release/build/* addons = file,open,basestring,xrange,unicode,long,cmp -[tool:pytest] -asyncio_mode = auto -testpaths = test -addopts = --capture=no --color=yes -filterwarnings = - ignore::DeprecationWarning:tornado.*: - -[coverage:run] -branch = False -omit = *contrib*, *tnetstring*, *platform*, *main.py - -[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 - \.\.\. - -[mypy] -check_untyped_defs = True -ignore_missing_imports = True -files = mitmproxy,examples/addons,release/*.py - -[mypy-mitmproxy.contrib.*] -ignore_errors = True - -[mypy-tornado.*] -ignore_errors = True - -[mypy-test.*] -ignore_errors = True - -# https://github.com/python/mypy/issues/3004 -[mypy-http-modify-form,http-trailers] -ignore_errors = True - [tool:full_coverage] exclude = mitmproxy/tools/ diff --git a/setup.py b/setup.py deleted file mode 100644 index 7224e7f53..000000000 --- a/setup.py +++ /dev/null @@ -1,123 +0,0 @@ -import os -import re -from codecs import open - -from setuptools import find_packages -from setuptools import setup - -# Based on https://github.com/pypa/sampleproject/blob/main/setup.py -# and https://python-packaging-user-guide.readthedocs.org/ - -here = os.path.abspath(os.path.dirname(__file__)) - -with open(os.path.join(here, "README.md"), encoding="utf-8") as f: - long_description = f.read() -long_description_content_type = "text/markdown" - -with open(os.path.join(here, "mitmproxy/version.py")) as f: - match = re.search(r'VERSION = "(.+?)"', f.read()) - assert match - VERSION = match.group(1) - -setup( - name="mitmproxy", - version=VERSION, - description="An interactive, SSL/TLS-capable intercepting proxy for HTTP/1, HTTP/2, and WebSockets.", - long_description=long_description, - long_description_content_type=long_description_content_type, - url="http://mitmproxy.org", - author="Aldo Cortesi", - author_email="aldo@corte.si", - license="MIT", - 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.10", - "Programming Language :: Python :: 3.11", - "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", - ], - project_urls={ - "Documentation": "https://docs.mitmproxy.org/stable/", - "Source": "https://github.com/mitmproxy/mitmproxy/", - "Tracker": "https://github.com/mitmproxy/mitmproxy/issues", - }, - packages=find_packages( - include=[ - "mitmproxy", - "mitmproxy.*", - ] - ), - include_package_data=True, - entry_points={ - "console_scripts": [ - "mitmproxy = mitmproxy.tools.main:mitmproxy", - "mitmdump = mitmproxy.tools.main:mitmdump", - "mitmweb = mitmproxy.tools.main:mitmweb", - ], - "pyinstaller40": [ - "hook-dirs = mitmproxy.utils.pyinstaller:hook_dirs", - ], - }, - python_requires=">=3.10", - # 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. - install_requires=[ - "aioquic_mitmproxy>=0.9.20,<0.10", - "asgiref>=3.2.10,<3.7", - "Brotli>=1.0,<1.1", - "certifi>=2019.9.11", # no semver here - this should always be on the last release! - "cryptography>=38.0,<40.1", - "flask>=1.1.1,<2.3", - "h11>=0.11,<0.15", - "h2>=4.1,<5", - "hyperframe>=6.0,<7", - "kaitaistruct>=0.10,<0.11", - "ldap3>=2.8,<2.10", - "mitmproxy_rs>=0.2.0b1,<0.3", - "msgpack>=1.0.0, <1.1.0", - "passlib>=1.6.5, <1.8", - "protobuf>=3.14,<5", - "pyOpenSSL>=22.1,<23.2", - "pyparsing>=2.4.2,<3.1", - "pyperclip>=1.6.0,<1.9", - "ruamel.yaml>=0.16,<0.18", - "sortedcontainers>=2.3,<2.5", - "tornado>=6.2,<7", - "urwid-mitmproxy>=2.1.1,<2.2", - "wsproto>=1.0,<1.3", - "publicsuffix2>=2.20190812,<3", - "zstandard>=0.11,<0.21", - "typing-extensions>=4.3,<4.6; python_version<'3.11'", - ], - extras_require={ - ':sys_platform == "win32"': [ - "pydivert>=2.0.3,<2.2", - ], - "dev": [ - "click>=7.0,<8.2", - "hypothesis>=5.8,<7", - "parver>=0.1,<2.0", - "pdoc>=4.0.0", - "pyinstaller==5.8.0", - "pytest-asyncio>=0.17,<0.21", - "pytest-cov>=2.7.1,<4.1", - "pytest-timeout>=1.3.3,<2.2", - "pytest-xdist>=2.1.0,<3.3", - "pytest>=6.1.0,<8", - "requests>=2.9.1,<3", - "tox>=3.5,<5", - "wheel>=0.36.2,<0.39", - ], - }, -) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 5f3c0df80..000000000 --- a/tox.ini +++ /dev/null @@ -1,55 +0,0 @@ -[tox] -envlist = py, flake8, mypy -skipsdist = True -toxworkdir={env:TOX_WORK_DIR:.tox} - -[testenv] -deps = - -e .[dev] -setenv = HOME = {envtmpdir} -commands = - mitmdump --version - pytest --timeout 60 -vv --cov-report xml \ - --continue-on-collection-errors \ - --cov=mitmproxy --cov=release \ - --full-cov=mitmproxy/ \ - {posargs} - -[testenv:flake8] -deps = - flake8>=3.8.4,<6.1 - flake8-tidy-imports>=4.2.0,<5 -commands = - flake8 --jobs 8 mitmproxy examples test release {posargs} - -[testenv:filename_matching] -deps = -commands = - python ./test/filename_matching.py - -[testenv:mypy] -deps = - mypy==1.0.0 - types-certifi==2021.10.8.3 - types-Flask==1.1.6 - types-Werkzeug==1.0.9 - types-requests==2.28.11.11 - types-cryptography==3.3.23.2 - types-pyOpenSSL==23.0.0.2 - -e .[dev] - -commands = - mypy {posargs} - -[testenv:individual_coverage] -commands = - python ./test/individual_coverage.py {posargs} - -[testenv:wheeltest] -recreate = True -deps = -commands = - pip install {posargs} - mitmproxy --version - mitmdump --version - mitmweb --version