diff --git a/.circleci/config.yml b/.circleci/config.yml index 57a69a8c..32163c58 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -55,7 +55,7 @@ aliases: - nix_docker: &NIX_DOCKER # Run in a highly Nix-capable environment. - - image: "nixos/nix:2.15.0" + - image: "nixos/nix:2.18.9" - nix_environ: &NIX_ENVIRON # Let us use features marked "experimental". For example, most/all of @@ -515,6 +515,8 @@ workflows: py-version: - "39" - "310" + - "311" + - "312" tahoe-lafs: - "1_18_0" # This is usually not master@HEAD because it is still pinned to diff --git a/flake.nix b/flake.nix index 8971377d..43d7493e 100644 --- a/flake.nix +++ b/flake.nix @@ -31,7 +31,7 @@ # The names of the nixpkgs Python derivations for which we will expose # packages. - pyVersions = [ "python310" "python39" ]; + pyVersions = [ "python312" "python311" "python310" "python39" ]; # All of the versions our Tahoe-LAFS dependency for which we will expose # packages. diff --git a/nix/collections-extended.nix b/nix/collections-extended.nix new file mode 100644 index 00000000..85dfc034 --- /dev/null +++ b/nix/collections-extended.nix @@ -0,0 +1,44 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + hypothesis, + poetry-core, + pytestCheckHook, + pythonOlder, + pythonAtLeast, +}: + +buildPythonPackage rec { + pname = "collections-extended"; + version = "2.0.2.post1"; + format = "pyproject"; + + # https://github.com/mlenzen/collections-extended/issues/198 + # My own running the test suggest Python 3.12 is still fine. + disabled = pythonOlder "3.6" || pythonAtLeast "3.13"; + + src = fetchFromGitHub { + owner = "mlenzen"; + repo = pname; + # This version includes our hero JP's patches for Python 3.11. + rev = "8b93390636d58d28012b8e9d22334ee64ca37d73"; + hash = "sha256-e7RCpNsqyS1d3q0E+uaE4UOEQziueYsRkKEvy3gCHt0="; + }; + + nativeBuildInputs = [ poetry-core ]; + + nativeCheckInputs = [ + hypothesis + pytestCheckHook + ]; + + pythonImportsCheck = [ "collections_extended" ]; + + meta = with lib; { + description = "Extra Python Collections - bags (multisets), setlists (unique list/indexed set), RangeMap and IndexedDict"; + homepage = "https://github.com/mlenzen/collections-extended"; + license = licenses.asl20; + maintainers = with maintainers; [ exarkun ]; + }; +} diff --git a/nix/compose.nix b/nix/compose.nix index 19facc18..6cc0bf41 100644 --- a/nix/compose.nix +++ b/nix/compose.nix @@ -2,11 +2,11 @@ buildPythonPackage rec { pname = "compose"; - version = "1.4.8"; + version = "1.6.2"; src = fetchPypi { inherit pname version; - sha256 = "sha256-mpRabfC4LE6xYlHmQbHb1yXxLDtH5idwN4GbUnCPGTo="; + sha256 = "sha256-yUP6goTByziSklOIhi4gPJiISE5M4/1RcVBnaWkNi00="; }; meta = with lib; { diff --git a/nix/eliot-tree.nix b/nix/eliot-tree.nix new file mode 100644 index 00000000..3a8c809f --- /dev/null +++ b/nix/eliot-tree.nix @@ -0,0 +1,54 @@ +{ + lib, + python3Packages, + fetchPypi, +}: + +python3Packages.buildPythonApplication rec { + pname = "eliot-tree"; + version = "21.0.0"; + pyproject = true; + + src = fetchPypi { + inherit pname version; + hash = "sha256-hTl+r+QJPPQ7ss73lty3Wm7DLy2SKGmmgIuJx38ilO8="; + }; + + # Patch Python 3.12 incompatibilities in versioneer.py. + postPatch = '' + substituteInPlace versioneer.py \ + --replace-fail SafeConfigParser ConfigParser \ + --replace-fail readfp read_file + ''; + + build-system = with python3Packages; [ setuptools ]; + + dependencies = with python3Packages; [ + colored + eliot + iso8601 + jmespath + toolz + ]; + + nativeCheckInputs = with python3Packages; [ + pytestCheckHook + testtools + ]; + + # Tests run eliot-tree in out/bin. + preCheck = '' + export PATH=$out/bin:$PATH + ''; + + pythonImportsCheck = [ "eliottree" ]; + + meta = { + homepage = "https://github.com/jonathanj/eliottree"; + changelog = "https://github.com/jonathanj/eliottree/blob/${version}/NEWS.rst"; + description = "Render Eliot logs as an ASCII tree"; + mainProgram = "eliot-tree"; + license = lib.licenses.mit; + maintainers = [ lib.maintainers.dpausp ]; + }; +} diff --git a/nix/eliot.nix b/nix/eliot.nix new file mode 100644 index 00000000..b521e6d7 --- /dev/null +++ b/nix/eliot.nix @@ -0,0 +1,66 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + pythonOlder, + aiocontextvars, + boltons, + hypothesis, + pyrsistent, + pytestCheckHook, + setuptools, + six, + testtools, + zope-interface, +}: + +buildPythonPackage rec { + pname = "eliot"; + version = "1.15.0"; + format = "setuptools"; + + disabled = pythonOlder "3.6"; + + src = fetchFromGitHub { + owner = "itamarst"; + repo = "eliot"; + rev = "1.15.0"; + hash = "sha256-Ur7q7PZ5HH4ttD3b0HyBTe1B7eQ2nEWcTBR/Hjeg9yw="; + }; + + propagatedBuildInputs = [ + aiocontextvars + boltons + pyrsistent + setuptools + six + zope-interface + ]; + + nativeCheckInputs = [ + hypothesis + pytestCheckHook + testtools + ]; + + pythonImportsCheck = [ "eliot" ]; + + # Tests run eliot-prettyprint in out/bin. + preCheck = '' + export PATH=$out/bin:$PATH + ''; + + disabledTests = [ + "test_parse_stream" + # AttributeError: module 'inspect' has no attribute 'getargspec' + "test_default" + ]; + + meta = with lib; { + homepage = "https://eliot.readthedocs.io"; + description = "Logging library that tells you why it happened"; + mainProgram = "eliot-prettyprint"; + license = licenses.asl20; + maintainers = with maintainers; [ dpausp ]; + }; +} diff --git a/nix/flake8-black.nix b/nix/flake8-black.nix index a3e27ff1..96c3c1f5 100644 --- a/nix/flake8-black.nix +++ b/nix/flake8-black.nix @@ -4,6 +4,7 @@ , black , tomli , setuptools +, pip }: buildPythonPackage rec { pname = "flake8-black"; @@ -16,7 +17,7 @@ buildPythonPackage rec { format = "pyproject"; # doCheck = false; - buildInputs = [ setuptools ]; + buildInputs = [ setuptools pip ]; propagatedBuildInputs = [ flake8 black tomli ]; pythonImportsCheck = [ "flake8_black" ]; } diff --git a/nix/flake8-isort.nix b/nix/flake8-isort.nix index 45a6d3e1..a7532b2c 100644 --- a/nix/flake8-isort.nix +++ b/nix/flake8-isort.nix @@ -5,11 +5,11 @@ }: buildPythonPackage rec { pname = "flake8-isort"; - version = "6.0.0"; + version = "6.1.0"; src = fetchPypi { inherit pname version; - hash = "sha256-U39FOmYNfpA/YC7Po2E2sUDeJ531jQLrG2oMhOg8Uow="; + hash = "sha256-1GOTQ7rFQBlMWfsWGKwsKFs+J2CfNTvvb1CQTUDBZD4="; }; doCheck = false; diff --git a/nix/hypothesis.nix b/nix/hypothesis.nix deleted file mode 100644 index 7f475b82..00000000 --- a/nix/hypothesis.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ hypothesis, fetchFromGitHub }: -hypothesis.overrideAttrs (old: rec { - version = "6.74.1"; - name = "hypothesis-${version}"; - src = fetchFromGitHub { - owner = "HypothesisWorks"; - repo = "hypothesis"; - rev = "hypothesis-python-${version}"; - hash = "sha256-bzbC9TmqqvrgTkJ3aZjp3Dd9MgeGxOkj1bz03Ng2sCo="; - }; -}) diff --git a/nix/lib.nix b/nix/lib.nix index d25f5c45..bbba8753 100644 --- a/nix/lib.nix +++ b/nix/lib.nix @@ -69,6 +69,9 @@ rec { # tokenize-rt = null; }); + # Something wants ipython - it breaks Python39 though, so we turn it off. + ipython = null; + tqdm = dontCheck super.tqdm; isort = dontCheck super.isort; @@ -84,11 +87,25 @@ rec { mypy-zope = self.callPackage ./mypy-zope.nix {}; types-PyYAML = self.callPackage ./types-pyyaml.nix {}; - # Hypothesis 6.54-ish has a bug that causes our test suite to fail. - # Get a newer one. - hypothesis = self.callPackage ./hypothesis.nix { - inherit (super) hypothesis; - }; + # Only the current master tip is Python 3.12 ready. + magic-wormhole-transit-relay = self.callPackage ./magic-wormhole-transit-relay.nix {}; + magic-wormhole-mailbox-server = self.callPackage ./magic-wormhole-mailbox-server.nix {}; + # Magic Wormhole tests break with the updated version of transit-relay from above. + magic-wormhole = self.callPackage ./magic-wormhole.nix {}; + # Latest magic-wormhole requires latest spake2 + spake2 = self.callPackage ./spake2.nix {}; + + # collections-extended isn't maintained anymore. + collections-extended = self.callPackage ./collections-extended.nix {}; + + # eliot 1.15 upgrades its bundled versioneer and works with Python 3.12 + eliot = self.callPackage ./eliot.nix {}; + eliot-tree = self.callPackage ./eliot-tree.nix {}; + + # Twisted runtimeDeps check fails to find zope-interface on Python 3.9 + twisted = super.twisted.overrideAttrs (old: { + dontCheckRuntimeDeps = true; + }); }; }); in with python.pkgs; buildPythonPackage rec { @@ -109,7 +126,7 @@ rec { testresources hypothesis openapi-spec-validator - (toPythonModule (pkgs.eliot-tree.override { python3Packages = python.pkgs; })) + (toPythonModule (eliot-tree.override { python3Packages = python.pkgs; })) ]; postFixup = '' diff --git a/nix/magic-wormhole-mailbox-server.nix b/nix/magic-wormhole-mailbox-server.nix new file mode 100644 index 00000000..72f0dc4e --- /dev/null +++ b/nix/magic-wormhole-mailbox-server.nix @@ -0,0 +1,63 @@ +{ + lib, + stdenv, + buildPythonPackage, + fetchFromGitHub, + fetchpatch, + setuptools, + six, + attrs, + twisted, + autobahn, + treq, + mock, + pythonOlder, + pythonAtLeast, + pytestCheckHook, +}: + +buildPythonPackage rec { + pname = "magic-wormhole-mailbox-server"; + version = "0.4.1.post1"; + pyproject = true; + + # python 3.12 support: https://github.com/magic-wormhole/magic-wormhole-mailbox-server/issues/41 + disabled = pythonOlder "3.7" || pythonAtLeast "3.13"; + + src = fetchFromGitHub { + owner = "magic-wormhole"; + repo = "magic-wormhole-mailbox-server"; + rev = "30ecb6e3f6f487c915e7ff0acdf2e630cbe17dc8"; + hash = "sha256-I07bQmWrGppxBvQyCndPlkc94KjBfcswVa8aTjHE66o="; + }; + + nativeBuildInputs = [ setuptools ]; + + propagatedBuildInputs = [ + attrs + six + twisted + autobahn + ] ++ autobahn.optional-dependencies.twisted ++ twisted.optional-dependencies.tls; + + pythonImportsCheck = [ "wormhole_mailbox_server" ]; + + nativeCheckInputs = [ + pytestCheckHook + treq + mock + ]; + + disabledTestPaths = lib.optionals stdenv.isDarwin [ + # these tests fail in Darwin's sandbox + "src/wormhole_mailbox_server/test/test_web.py" + ]; + + meta = { + description = "Securely transfer data between computers"; + homepage = "https://github.com/magic-wormhole/magic-wormhole-mailbox-server"; + changelog = "https://github.com/magic-wormhole/magic-wormhole-mailbox-server/blob/${version}/NEWS.md"; + license = lib.licenses.mit; + maintainers = [ lib.maintainers.mjoerg ]; + }; +} diff --git a/nix/magic-wormhole-transit-relay.nix b/nix/magic-wormhole-transit-relay.nix new file mode 100644 index 00000000..89366bc4 --- /dev/null +++ b/nix/magic-wormhole-transit-relay.nix @@ -0,0 +1,60 @@ +{ + lib, + buildPythonPackage, + fetchPypi, + setuptools, + autobahn, + mock, + twisted, + python, + pytestCheckHook, +}: + +buildPythonPackage rec { + pname = "magic-wormhole-transit-relay"; + version = "0.3.1"; + pyproject = true; + + src = fetchPypi { + inherit pname version; + hash = "sha256-LvLvvk008OYkhw+EIln9czuncVLtMQr0NJd0piiEkA4="; + }; + + postPatch = '' + # Passing the environment to twistd is necessary to preserve Python's site path. + substituteInPlace src/wormhole_transit_relay/test/test_backpressure.py --replace-fail \ + 'reactor.spawnProcess(proto, exe, args)' \ + 'reactor.spawnProcess(proto, exe, args, None)' + ''; + + build-system = [ setuptools ]; + + dependencies = [ + autobahn + setuptools # pkg_resources is referenced at runtime + twisted + ]; + + pythonImportsCheck = [ "wormhole_transit_relay" ]; + + nativeCheckInputs = [ + pytestCheckHook + mock + twisted + ]; + + __darwinAllowLocalNetworking = true; + + postCheck = '' + # Avoid collision with twisted's plugin cache (#164775). + rm "$out/${python.sitePackages}/twisted/plugins/dropin.cache" + ''; + + meta = { + description = "Transit Relay server for Magic-Wormhole"; + homepage = "https://github.com/magic-wormhole/magic-wormhole-transit-relay"; + changelog = "https://github.com/magic-wormhole/magic-wormhole-transit-relay/blob/${version}/NEWS.md"; + license = lib.licenses.mit; + maintainers = [ lib.maintainers.mjoerg ]; + }; +} diff --git a/nix/magic-wormhole.nix b/nix/magic-wormhole.nix new file mode 100644 index 00000000..6d64ee1a --- /dev/null +++ b/nix/magic-wormhole.nix @@ -0,0 +1,147 @@ +{ + lib, + stdenv, + buildPythonPackage, + fetchPypi, + pythonAtLeast, + + # build-system + setuptools, + + # dependencies + spake2, + pynacl, + six, + attrs, + twisted, + autobahn, + automat, + tqdm, + click, + humanize, + iterable-io, + txtorcon, + zipstream-ng, + + # optional-dependencies + noiseprotocol, + + # tests + nettools, + unixtools, + mock, + magic-wormhole-transit-relay, + magic-wormhole-mailbox-server, + pytestCheckHook, +}: + +let + # magic-wormhole relies on the internal API of + # magic-wormhole-transit-relay < 0.3.0 for testing. + magic-wormhole-transit-relay_0_2_1 = + magic-wormhole-transit-relay.overridePythonAttrs + (oldAttrs: rec { + version = "0.2.1"; + + src = fetchPypi { + pname = "magic-wormhole-transit-relay"; + inherit version; + hash = "sha256-y0gBtGiQ6v+XKG4OP+xi0dUv/jF9FACDtjNqH7To+l4="; + }; + + postPatch = ""; + + postCheck = ""; + + meta.broken = pythonAtLeast "3.12"; + }); +in +buildPythonPackage rec { + pname = "magic-wormhole"; + version = "0.16.0"; + pyproject = true; + + src = fetchPypi { + inherit pname version; + hash = "sha256-FObBRomNvaem0ZAmJiOmlBmVU2Pn5DTWSq0tIz1tlMk="; + }; + + postPatch = + # enable tests by fixing the location of the wormhole binary + '' + substituteInPlace src/wormhole/test/test_cli.py --replace-fail \ + 'locations = procutils.which("wormhole")' \ + 'return "${placeholder "out"}/bin/wormhole"' + '' + # fix the location of the ifconfig binary + + lib.optionalString stdenv.hostPlatform.isLinux '' + sed -i -e "s|'ifconfig'|'${nettools}/bin/ifconfig'|" src/wormhole/ipaddrs.py + ''; + + build-system = [ setuptools ]; + + dependencies = [ + attrs + autobahn + automat + click + humanize + iterable-io + pynacl + six + spake2 + tqdm + twisted + txtorcon + zipstream-ng + ] ++ autobahn.optional-dependencies.twisted ++ twisted.optional-dependencies.tls; + + optional-dependencies = { + dilation = [ noiseprotocol ]; + }; + + nativeCheckInputs = + # For Python 3.12, remove magic-wormhole-mailbox-server and magic-wormhole-transit-relay from test dependencies, + # which are not yet supported with this version. + lib.optionals + (!magic-wormhole-mailbox-server.meta.broken && !magic-wormhole-transit-relay_0_2_1.meta.broken) + [ + magic-wormhole-mailbox-server + magic-wormhole-transit-relay_0_2_1 + ] + ++ [ + mock + pytestCheckHook + ] + ++ optional-dependencies.dilation + ++ lib.optionals stdenv.hostPlatform.isDarwin [ unixtools.locale ]; + + __darwinAllowLocalNetworking = true; + + disabledTestPaths = + # For Python 3.12, remove the tests depending on magic-wormhole-mailbox-server and magic-wormhole-transit-relay, + # which are not yet supported with this version. + lib.optionals + (magic-wormhole-mailbox-server.meta.broken || magic-wormhole-transit-relay_0_2_1.meta.broken) + [ + "src/wormhole/test/dilate/test_full.py" + "src/wormhole/test/test_args.py" + "src/wormhole/test/test_cli.py" + "src/wormhole/test/test_transit.py" + "src/wormhole/test/test_wormhole.py" + "src/wormhole/test/test_xfer_util.py" + ]; + + postInstall = '' + install -Dm644 docs/wormhole.1 $out/share/man/man1/wormhole.1 + ''; + + meta = { + changelog = "https://github.com/magic-wormhole/magic-wormhole/blob/${version}/NEWS.md"; + description = "Securely transfer data between computers"; + homepage = "https://github.com/magic-wormhole/magic-wormhole"; + license = lib.licenses.mit; + maintainers = [ lib.maintainers.mjoerg ]; + mainProgram = "wormhole"; + }; +} diff --git a/nix/mypy-zope.nix b/nix/mypy-zope.nix index ff0114f5..821b0299 100644 --- a/nix/mypy-zope.nix +++ b/nix/mypy-zope.nix @@ -5,12 +5,12 @@ , zope_schema }: buildPythonPackage rec { - pname = "mypy-zope"; - version = "0.3.11"; + pname = "mypy_zope"; + version = "1.0.9"; src = fetchPypi { inherit pname version; - hash = "sha256-1CVfnwTUjHkIO71OL+oGUTpqx7jeBvjEzlY/2FFCygU="; + hash = "sha256-N9aYXfsFpMJ7Nc/0dXf9W62HjbSJPd7fVNFl9ziaHNs="; }; # doCheck = false; diff --git a/nix/pycddl.nix b/nix/pycddl.nix index 0f6a0329..9392add4 100644 --- a/nix/pycddl.nix +++ b/nix/pycddl.nix @@ -1,12 +1,12 @@ { lib, fetchPypi, buildPythonPackage, rustPlatform }: buildPythonPackage rec { pname = "pycddl"; - version = "0.4.0"; + version = "0.6.3"; format = "pyproject"; src = fetchPypi { inherit pname version; - sha256 = "sha256-w0CGbPeiXyS74HqZXyiXhvaAMUaIj5onwjl9gWKAjqY="; + sha256 = "sha256-lVybSr+QvyepdTZfiTjqU0ENu6TT87ZZXIECBA8nMV4="; }; nativeBuildInputs = with rustPlatform; [ @@ -17,6 +17,6 @@ buildPythonPackage rec { cargoDeps = rustPlatform.fetchCargoTarball { inherit src; name = "${pname}-${version}"; - hash = "sha256-g96eeaqN9taPED4u+UKUcoitf5aTGFrW2/TOHoHEVHs="; + hash = "sha256-VpJ/PLAwwuakwsNAtLDdWGXCxl6jGMTvsEhzIHk6a0g="; }; } diff --git a/nix/pyopenssl.nix b/nix/pyopenssl.nix index b8966fad..100be478 100644 --- a/nix/pyopenssl.nix +++ b/nix/pyopenssl.nix @@ -1,10 +1,10 @@ { pyopenssl, fetchPypi, isPyPy }: pyopenssl.overrideAttrs (old: rec { pname = "pyOpenSSL"; - version = "23.2.0"; + version = "24.1.0"; name = "${pname}-${version}"; src = fetchPypi { inherit pname version; - sha256 = "J2+TH1WkUufeppxxc+mE6ypEB85BPJGKo0tV+C+bi6w="; + sha256 = "yr7Uv6pd+fGhbA72Sgy2Uxi1zQd6ftp9aXATHKL0Gm8="; }; }) diff --git a/nix/spake2.nix b/nix/spake2.nix new file mode 100644 index 00000000..98602e7d --- /dev/null +++ b/nix/spake2.nix @@ -0,0 +1,38 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + fetchpatch2, + setuptools, + cryptography, + pytestCheckHook, +}: + +buildPythonPackage rec { + pname = "spake2"; + version = "0.9"; + pyproject = true; + + src = fetchFromGitHub { + owner = "warner"; + repo = "python-spake2"; + rev = "refs/tags/v${version}"; + hash = "sha256-WPMGH1OzG+5O+2lNl2sv06/dNardY+BHYDS290Z36vQ="; + }; + + build-system = [ setuptools ]; + + dependencies = [ cryptography ]; + + pythonImportsCheck = [ "spake2" ]; + + nativeCheckInputs = [ pytestCheckHook ]; + + meta = with lib; { + changelog = "https://github.com/warner/python-spake2/blob/v${version}/NEWS"; + description = "SPAKE2 password-authenticated key exchange library"; + homepage = "https://github.com/warner/python-spake2"; + license = licenses.mit; + maintainers = with maintainers; [ dotlambda ]; + }; +} diff --git a/nix/tahoe-lafs.nix b/nix/tahoe-lafs.nix index f2ae1a1d..6f6df041 100644 --- a/nix/tahoe-lafs.nix +++ b/nix/tahoe-lafs.nix @@ -42,5 +42,7 @@ buildPythonPackage { appdirs bcrypt aniso8601 + pip + orjson ]; } diff --git a/nix/types-pyyaml.nix b/nix/types-pyyaml.nix index 98cec85d..98b7b6f6 100644 --- a/nix/types-pyyaml.nix +++ b/nix/types-pyyaml.nix @@ -3,10 +3,10 @@ }: buildPythonPackage rec { pname = "types-PyYAML"; - version = "6.0.12.9"; + version = "6.0.12.20240917"; src = fetchPypi { inherit pname version; - hash = "sha256-xRsb1tmd3wqiiEp6MogQ6/cKQmLCkhldP0+aAAX57rY="; + hash = "sha256-0UBahvlXZoIjTvg7y05v/3yTBcix+61eC81Pfb3JxYc="; }; }