diff --git a/.devcontainer.json b/.devcontainer.json index e3c39242c..a0ba06dc2 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -8,5 +8,5 @@ }, "image": "ghcr.io/cachix/devenv:latest", "overrideCommand": false, - "updateContentCommand": "devenv ci" + "updateContentCommand": "devenv test" } diff --git a/.envrc b/.envrc index 648c747af..cf905f7c4 100755 --- a/.envrc +++ b/.envrc @@ -4,10 +4,10 @@ set -euo pipefail # Use our own last built devenv/nix in CLI -devenv_bin=$(nix build --print-out-paths --accept-flake-config) -PATH_add "$devenv_bin/bin" +nix build --print-out-paths --accept-flake-config || echo "nix build failed, using previous build" +PATH_add "result/bin" # External users should use `source_url` to load this file source_env ./direnvrc -use devenv \ No newline at end of file +use devenv diff --git a/.github/workflows/buildtest.yml b/.github/workflows/buildtest.yml index be32836b8..89ec41c4a 100644 --- a/.github/workflows/buildtest.yml +++ b/.github/workflows/buildtest.yml @@ -25,7 +25,7 @@ jobs: - run: nix build - name: Run tests run: | - ./result/bin/devenv ci + ./result/bin/devenv test ./result/bin/devenv shell devenv-run-tests ./result/bin/devenv search ncdu | grep "pkgs\.ncdu" pin: diff --git a/.gitignore b/.gitignore index 8de6048b7..ba54410a6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,12 +3,12 @@ result .env .env.* .devenv* +.direnv* /.cache /.pre-commit-config.yaml # examples examples/rust/app/target -# Python -/.venv -*.pyc +# Rust +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..80784216c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1961 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansiterm" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ab587f5395da16dd2e6939adf53dede583221b320cadfb94e02b5b7b9bf24cc" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "backtrace-ext" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" +dependencies = [ + "backtrace", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "bumpalo" +version = "3.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "castaway" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +dependencies = [ + "rustversion", +] + +[[package]] +name = "cc" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_derive 3.2.25", + "clap_lex 0.2.4", + "indexmap 1.9.3", + "once_cell", + "strsim 0.10.0", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +dependencies = [ + "clap_builder", + "clap_derive 4.5.0", +] + +[[package]] +name = "clap_builder" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +dependencies = [ + "anstream", + "anstyle", + "clap_lex 0.7.0", + "strsim 0.11.0", +] + +[[package]] +name = "clap_derive" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "clap_derive" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "cli-table" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adfbb116d9e2c4be7011360d0c0bee565712c11e969c9609b25b619366dc379d" +dependencies = [ + "cli-table-derive", + "csv", + "termcolor", + "unicode-width", +] + +[[package]] +name = "cli-table-derive" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af3bfb9da627b0a6c467624fb7963921433774ed435493b5c08a3053e829ad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "ryu", + "static_assertions", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 2.0.51", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "devenv" +version = "1.0.0" +dependencies = [ + "ansiterm", + "clap 4.5.1", + "cli-table", + "dotlock", + "fs2", + "include_dir", + "indoc", + "miette", + "nix", + "regex", + "schematic", + "serde", + "serde_json", + "serde_yaml", + "tempdir", + "tracing", + "which", + "xdg", +] + +[[package]] +name = "devenv-run-tests" +version = "0.1.0" +dependencies = [ + "clap 3.2.25", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dotlock" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30c541575b952e53113caddb5be24869705052591b534ea11a81a3d4743416a3" +dependencies = [ + "tempfile", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-io", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "garde" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fa8fb3ffe035745c6194540b2064b2fe275f32367fbb4eb026024b7921e2e5" +dependencies = [ + "compact_str", + "garde_derive", + "once_cell", + "regex", + "smallvec", +] + +[[package]] +name = "garde_derive" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf62650515830c41553b72bd49ec20fb120226f9277c7f2847f071cf998325b" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.51", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.2.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "include_dir" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18762faeff7122e89e0857b02f7ce6fcc0d101d5e9ad2ad7846cc01d61b7f19e" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "is_ci" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" + +[[package]] +name = "js-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.2", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "markdown" +version = "1.0.0-alpha.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0f0025e8c0d89b84d6dc63e859475e40e8e82ab1a08be0a93ad5731513a508" +dependencies = [ + "unicode-id", +] + +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + +[[package]] +name = "miette" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baed61d13cc3723ee6dbed730a82bfacedc60a85d81da2d77e9c3e8ebc0b504a" +dependencies = [ + "backtrace", + "backtrace-ext", + "miette-derive", + "owo-colors", + "supports-color", + "supports-hyperlinks", + "supports-unicode", + "terminal_size", + "textwrap", + "thiserror", + "unicode-width", +] + +[[package]] +name = "miette-derive" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301c3f54f98abc6c212ee722f5e5c62e472a334415840669e356f04850051ec" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.8", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "owo-colors" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +dependencies = [ + "bitflags 2.4.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "serde", + "serde_json", +] + +[[package]] +name = "schematic" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709e1f0b0a3db267a98da09c89a7818e307cc8daea841e1079eb5f5a02591d54" +dependencies = [ + "garde", + "indexmap 2.2.3", + "markdown", + "miette", + "reqwest", + "schemars", + "schematic_macros", + "schematic_types", + "serde", + "serde_json", + "serde_path_to_error", + "serde_yaml", + "starbase_styles", + "thiserror", + "tracing", +] + +[[package]] +name = "schematic_macros" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31af7347544d97d00870a5865d2077dac07c069a5290c26215ddd1138b302590" +dependencies = [ + "convert_case", + "darling", + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "schematic_types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3adfbe1c90a6a9643433e490ef1605c6a99f93be37e4c83fe5149fca9698c6" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "serde_json" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +dependencies = [ + "indexmap 2.2.3", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +dependencies = [ + "indexmap 2.2.3", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" + +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "starbase_styles" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e06fa37c027e48ef341787d8c3d26cfbe8507aa4e2e8c61fcba82fe931bb598" +dependencies = [ + "dirs", + "owo-colors", + "supports-color", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" + +[[package]] +name = "supports-color" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9829b314621dfc575df4e409e79f9d6a66a3bd707ab73f23cb4aa3a854ac854f" +dependencies = [ + "is_ci", +] + +[[package]] +name = "supports-hyperlinks" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c0a1e5168041f5f3ff68ff7d95dcb9c8749df29f6e7e89ada40dd4c9de404ee" + +[[package]] +name = "supports-unicode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab617d94515e94ae53b8406c628598680aa0c9587474ecbe58188f7b345d66c" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand", + "remove_dir_all", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +dependencies = [ + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-id" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1b6def86329695390197b82c1e244a54a131ceb66c996f2088a3876e2ae083f" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "unsafe-libyaml" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.51", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877b9c3f61ceea0e56331985743b13f3d25c406a7098d45180fb5f09bc19ed97" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838" + +[[package]] +name = "web-sys" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "which" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.3", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f" +dependencies = [ + "windows_aarch64_gnullvm 0.52.3", + "windows_aarch64_msvc 0.52.3", + "windows_i686_gnu 0.52.3", + "windows_i686_msvc 0.52.3", + "windows_x86_64_gnu 0.52.3", + "windows_x86_64_gnullvm 0.52.3", + "windows_x86_64_msvc 0.52.3", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6" + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "xdg" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..6e0add60e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +resolver = "2" +members = [ + "devenv", + "devenv-run-tests", +] \ No newline at end of file diff --git a/README.md b/README.md index 5bd450ec8..b35be99e6 100644 --- a/README.md +++ b/README.md @@ -44,13 +44,39 @@ And ``devenv shell`` activates the environment. ## Commands -- ``devenv init``: Scaffold devenv.yaml, devenv.nix, and .envrc. -- ``devenv shell``: Activate the developer environment. -- ``devenv shell CMD ARGS``: Run CMD with ARGS in the developer environment. -- ``devenv update``: Update devenv.lock from devenv.yaml inputs. See http://devenv.sh/inputs/#locking-and-updating-inputs. -- ``devenv up``: Start processes in foreground. See http://devenv.sh/processes. -- ``devenv gc``: Remove old devenv generations. See http://devenv.sh/garbage-collection. -- ``devenv ci``: Build your developer environment and make sure all checks pass. +``` +$ devenv + +Usage: devenv [OPTIONS] + +Commands: + init Scaffold devenv.yaml, devenv.nix, .gitignore and .envrc. + shell Activate the developer environment. https://devenv.sh/basics/ + update Update devenv.lock from devenv.yaml inputs. http://devenv.sh/inputs/ + search Search for packages and options in nixpkgs. https://devenv.sh/packages/#searching-for-a-file + info Print information about this developer environment. + up Start processes in the foreground. https://devenv.sh/processes/ + processes Start or stop processes. + test Run tests. http://devenv.sh/tests/ + container Build, copy, or run a container. https://devenv.sh/containers/ + inputs Add an input to devenv.yaml. https://devenv.sh/inputs/ + gc Deletes previous shell generations. See http://devenv.sh/garbage-collection + build Build any attribute in devenv.nix. + version Print the version of devenv. + help Print this message or the help of the given subcommand(s) + +Options: + -v, --verbose + Enable debug log level. + -s, --system + [default: x86_64-linux] + -d, --nix-debugger + Enter Nix debugger on failure. + -n, --nix-option + Pass additional options to nix commands, see `man nix.conf` for full list. + -h, --help + Print help +``` ## Documentation diff --git a/build_cloudflare.sh b/build_cloudflare.sh index 4b6b8353c..923f5e6f5 100755 --- a/build_cloudflare.sh +++ b/build_cloudflare.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash set -xe -poetry install --with docs -poetry run -- mkdocs build +pip install -r requirements.txt +mkdocs build \ No newline at end of file diff --git a/devenv-run-tests/Cargo.toml b/devenv-run-tests/Cargo.toml new file mode 100644 index 000000000..8f3258ed6 --- /dev/null +++ b/devenv-run-tests/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "devenv-run-tests" +version = "0.1.0" +edition = "2018" + +[dependencies] +clap = { version = "3", features = ["derive"] } \ No newline at end of file diff --git a/devenv-run-tests/src/main.rs b/devenv-run-tests/src/main.rs new file mode 100644 index 000000000..a53b3fba9 --- /dev/null +++ b/devenv-run-tests/src/main.rs @@ -0,0 +1,110 @@ +use clap::Parser; +use std::fs; +use std::path::{Path, PathBuf}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + #[clap(long, value_parser, help = "Exclude these tests.")] + exclude: Vec, + + #[clap(long, value_parser, help = "Only run these tests.")] + only: Vec, + + #[clap(value_parser, required = true)] + directories: Vec, +} + +struct TestResult { + name: String, + passed: bool, +} + +fn run_tests_in_directory(args: &Args) -> Result, Box> { + let cwd = std::env::current_dir()?; + let cwd = cwd.display(); + + let mut test_results = vec![]; + + for directory in &args.directories { + println!("Running in directory {}", directory.display()); + let paths = fs::read_dir(directory)?; + + for path in paths { + let path = path?.path(); + if path.is_dir() { + let dir_name_path = path.file_name().unwrap(); + let dir_name = dir_name_path.to_str().unwrap(); + + if !args.only.is_empty() { + let mut found = false; + for only in &args.only { + if path.as_path().ends_with(only) { + found = true; + break; + } + } + if !found { + continue; + } + } else { + for exclude in &args.exclude { + if path.as_path().ends_with(exclude) { + println!("Skipping {}", dir_name); + continue; + } + } + } + + println!(" Running {}", dir_name); + // if .setup.sh exists, run it + let setup_script = path.join(".setup.sh"); + if setup_script.exists() { + println!(" Running .setup.sh"); + let _ = std::process::Command::new("bash") + .arg(".setup.sh") + .current_dir(&path) + .status()?; + } + // TODO: use as a library + let status = std::process::Command::new("devenv") + .args([ + "--override-input", + "devenv", + &format!("path:{cwd}?dir=src/modules"), + ]) + .arg("test") + .current_dir(&path) + .status()?; + + let result = TestResult { + name: dir_name.to_string(), + passed: status.success(), + }; + test_results.push(result); + } + } + } + + Ok(test_results) +} + +fn main() -> Result<(), Box> { + let args = Args::parse(); + + let test_results = run_tests_in_directory(&args)?; + let num_tests = test_results.len(); + let num_failed_tests = test_results.iter().filter(|r| !r.passed).count(); + + println!(); + + for result in test_results { + if !result.passed { + println!("{}: Failed", result.name); + }; + } + + println!(); + println!("Ran {} tests, {} failed.", num_tests, num_failed_tests); + Ok(()) +} diff --git a/devenv.lock b/devenv.lock index 182c4450a..fd6e746b8 100644 --- a/devenv.lock +++ b/devenv.lock @@ -2,11 +2,13 @@ "nodes": { "devenv": { "locked": { - "path": "./src/modules", + "dir": "src/modules", + "path": ".", "type": "path" }, "original": { - "path": "./src/modules", + "dir": "src/modules", + "path": ".", "type": "path" }, "parent": [] @@ -48,11 +50,29 @@ "systems": "systems" }, "locked": { - "lastModified": 1705309234, + "lastModified": 1709126324, "owner": "numtide", "repo": "flake-utils", - "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", - "treeHash": "80a852cb0f5bf29497a20ca4f37ba97b0e85c721", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "treeHash": "f52cf07f5dc7208c6379eb10b7505fda4c429b88", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1709126324, + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "treeHash": "f52cf07f5dc7208c6379eb10b7505fda4c429b88", "type": "github" }, "original": { @@ -69,11 +89,11 @@ ] }, "locked": { - "lastModified": 1703887061, + "lastModified": 1709087332, "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", - "treeHash": "2dd7f68f94467b298f778300ce0248117d6c500e", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "treeHash": "ca14199cabdfe1a06a7b1654c76ed49100a689f9", "type": "github" }, "original": { @@ -91,11 +111,11 @@ "nixpkgs-regression": "nixpkgs-regression" }, "locked": { - "lastModified": 1708370782, + "lastModified": 1709513008, "owner": "domenkozar", "repo": "nix", - "rev": "3b944df09a1d3606f094bd4b32c56846efc99ddf", - "treeHash": "401993a9735c08297eff0a593f6ac5adac68c8b9", + "rev": "d61bd1c0dda0ec7466079531547bbafdf538ed71", + "treeHash": "450086431140936247448766aecc37b90f4ff39e", "type": "github" }, "original": { @@ -105,19 +125,40 @@ "type": "github" } }, + "nix2container": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1708764364, + "owner": "nlewo", + "repo": "nix2container", + "rev": "c891f90d2e3c48a6b33466c96e4851e0fc0cf455", + "treeHash": "747af167fd4350bd81b11ce824a756bb85b1757c", + "type": "github" + }, + "original": { + "owner": "nlewo", + "repo": "nix2container", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1708373374, - "owner": "NixOS", + "lastModified": 1709280738, + "owner": "domenkozar", "repo": "nixpkgs", - "rev": "93e1c2d08467d1117ebac45689469613a9fe8453", - "treeHash": "a71be29ec9a1d906373bc8e8feac400a1bc378bf", + "rev": "0e172b739ff09c9dc652f2c9175ac0cf745cca81", + "treeHash": "ac7b46db5871ff29667646a328f426b945d3013c", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", + "owner": "domenkozar", "repo": "nixpkgs", + "rev": "0e172b739ff09c9dc652f2c9175ac0cf745cca81", "type": "github" } }, @@ -139,11 +180,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1708294118, + "lastModified": 1709128929, "owner": "NixOS", "repo": "nixpkgs", - "rev": "e0da498ad77ac8909a980f07eff060862417ccf7", - "treeHash": "6080d79e20d8f9fce719e518f10143595514df54", + "rev": "c8e74c2f83fe12b4e5a8bd1abbc090575b0f7611", + "treeHash": "087dfee039daa2a8e336580010af1f20c03569d0", "type": "github" }, "original": { @@ -156,7 +197,7 @@ "pre-commit-hooks": { "inputs": { "flake-compat": "flake-compat_2", - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "gitignore": "gitignore", "nixpkgs": [ "nixpkgs" @@ -181,6 +222,7 @@ "inputs": { "devenv": "devenv", "nix": "nix", + "nix2container": "nix2container", "nixpkgs": "nixpkgs", "pre-commit-hooks": "pre-commit-hooks" } @@ -199,6 +241,21 @@ "repo": "default", "type": "github" } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "treeHash": "cce81f2a0f0743b2eb61bc2eb6c7adbe2f2c6beb", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/devenv.nix b/devenv.nix index eccd4a528..f7117e187 100644 --- a/devenv.nix +++ b/devenv.nix @@ -8,14 +8,17 @@ pkgs.xorg.libxcb pkgs.yaml2json pkgs.tesh - pkgs.python3Packages.black - ]; - - languages.nix.enable = true; + ] ++ lib.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk; [ + frameworks.SystemConfiguration + ]); + + #languages.nix.enable = true; + # for cli + languages.rust.enable = true; + # for docs languages.python.enable = true; - languages.python.poetry.enable = true; - languages.python.poetry.install.installRootPackage = true; - languages.python.poetry.install.groups = [ "docs" ]; + languages.python.venv.enable = true; + languages.python.venv.requirements = ./requirements.txt; devcontainer.enable = true; devcontainer.settings.customizations.vscode.extensions = [ "jnoortheen.nix-ide" ]; @@ -31,7 +34,7 @@ echo assuming you bumped the version in mkdocs.yml, populating src/modules/latest-version cat mkdocs.yml | yaml2json | jq -r '.extra.devenv.version' > src/modules/latest-version ''; - scripts.devenv-run-tests.exec = '' + scripts.devenv-test-cli.exec = '' set -xe set -o pipefail @@ -43,11 +46,8 @@ tmp="$(mktemp -d)" devenv init "$tmp" pushd "$tmp" - echo -e " devenv:\n url: path:${config.devenv.root}?dir=src/modules" >> devenv.yaml - cat devenv.yaml devenv version - devenv ci - devenv test + devenv test --override-input devenv path:${config.devenv.root}?dir=src/modules popd rm -rf "$tmp" @@ -121,8 +121,9 @@ pre-commit.hooks = { nixpkgs-fmt.enable = true; - shellcheck.enable = true; - black.enable = true; + #shellcheck.enable = true; + clippy.enable = true; + rustfmt.enable = true; #markdownlint.enable = true; }; pre-commit.settings.markdownlint.config = { @@ -132,7 +133,4 @@ MD033 = false; MD034 = false; }; - - tests = config.lib.mkTests ./examples - // config.lib.mkTests ./tests; } diff --git a/devenv.yaml b/devenv.yaml index 01be806ad..4ba91d45e 100644 --- a/devenv.yaml +++ b/devenv.yaml @@ -1,13 +1,18 @@ inputs: - nixpkgs: - url: github:NixOS/nixpkgs/nixpkgs-unstable + nix2container: + url: github:nlewo/nix2container + inputs: + nixpkgs: + follows: nixpkgs + devenv: + url: path:.?dir=src/modules nix: url: github:domenkozar/nix/devenv-2.21 inputs: nixpkgs: follows: nixpkgs - devenv: - url: path:./src/modules + nixpkgs: + url: github:domenkozar/nixpkgs/0e172b739ff09c9dc652f2c9175ac0cf745cca81 pre-commit-hooks: url: github:cachix/pre-commit-hooks.nix inputs: diff --git a/devenv/Cargo.toml b/devenv/Cargo.toml new file mode 100644 index 000000000..e6dfcda3e --- /dev/null +++ b/devenv/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "devenv" +version = "1.0.0" +edition = "2021" +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +ansiterm = "0.12.2" +clap = { version = "4.5.1", features = ["derive", "cargo"] } +cli-table = "0.4.7" +dotlock = "0.5.0" +fs2 = "0.4.3" +include_dir = "0.7.3" +indoc = "2.0.4" +miette = { version = "7.1.0", features = ["fancy"] } +nix = { version = "0.28.0", features = ["signal"] } +regex = "1.10.3" +schematic = { version = "0.14.3", features = ["schema", "yaml", "renderer_template", "renderer_json_schema"] } +serde = "1.0.197" +serde_json = "1.0.114" +serde_yaml = "0.9.32" +tempdir = "0.3.7" +tracing = "0.1.40" +which = "6.0.0" +xdg = "2.5.2" diff --git a/devenv/init/.envrc b/devenv/init/.envrc new file mode 100644 index 000000000..6de8a8acd --- /dev/null +++ b/devenv/init/.envrc @@ -0,0 +1,3 @@ +source_url "https://raw.githubusercontent.com/cachix/devenv/d1f7b48e35e6dee421cfd0f51481d17f77586997/direnvrc" "sha256-YBzqskFZxmNb3kYVoKD9ZixoPXJh1C9ZvTLGFRkauZ0=" + +use devenv \ No newline at end of file diff --git a/devenv/init/.gitignore b/devenv/init/.gitignore new file mode 100644 index 000000000..4d058db7d --- /dev/null +++ b/devenv/init/.gitignore @@ -0,0 +1,9 @@ +# Devenv +.devenv* +devenv.local.nix + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml diff --git a/devenv/init/devenv.nix b/devenv/init/devenv.nix new file mode 100644 index 000000000..ea2220e91 --- /dev/null +++ b/devenv/init/devenv.nix @@ -0,0 +1,28 @@ +{ pkgs, ... }: + +{ + # https://devenv.sh/basics/ + env.GREET = "devenv"; + + # https://devenv.sh/packages/ + packages = [ pkgs.git ]; + + # https://devenv.sh/scripts/ + scripts.hello.exec = "echo hello from $GREET"; + + enterShell = '' + hello + git --version + ''; + + # https://devenv.sh/languages/ + # languages.nix.enable = true; + + # https://devenv.sh/pre-commit-hooks/ + # pre-commit.hooks.shellcheck.enable = true; + + # https://devenv.sh/processes/ + # processes.ping.exec = "ping example.com"; + + # See full reference at https://devenv.sh/reference/options/ +} diff --git a/examples/gleam/devenv.yaml b/devenv/init/devenv.yaml similarity index 100% rename from examples/gleam/devenv.yaml rename to devenv/init/devenv.yaml diff --git a/devenv/src/command.rs b/devenv/src/command.rs new file mode 100644 index 000000000..99f47d9af --- /dev/null +++ b/devenv/src/command.rs @@ -0,0 +1,160 @@ +use crate::App; +use miette::{bail, Result}; +use std::env; +use std::os::unix::process::CommandExt; + +const NIX_FLAGS: [&str; 11] = [ + "--show-trace", + "--extra-experimental-features", + "nix-command", + "--extra-experimental-features", + "flakes", + // remove unnecessary warnings + "--option", + "warn-dirty", + "false", + // flake caching is too aggressive + "--option", + "eval-cache", + "false", +]; + +pub struct Options { + pub replace_shell: bool, + pub use_cachix: bool, + pub logging: bool, + pub dont_exit: bool, +} + +impl Default for Options { + fn default() -> Self { + Options { + replace_shell: false, + use_cachix: false, + logging: true, + dont_exit: false, + } + } +} + +impl App { + pub fn run_nix( + &mut self, + command: &str, + args: &[&str], + options: &Options, + ) -> Result { + let mut cmd = self.prepare_command(command, args)?; + + if options.replace_shell { + if self.cli.nix_debugger && command.ends_with("bin/nix") { + cmd.arg("--debugger"); + } + let error = cmd.exec(); + self.logger.error(&format!( + "Failed to replace shell with `{} {}`: {error}", + cmd.get_program().to_string_lossy(), + cmd.get_args() + .map(|arg| arg.to_str().unwrap()) + .collect::>() + .join(" ") + )); + bail!("Failed to replace shell") + } else { + let result = if options.logging { + cmd.stdin(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) + .output() + .expect("Failed to run command") + } else { + cmd.output().expect("Failed to run command") + }; + if !result.status.success() { + if options.logging { + println!(); + let code = match result.status.code() { + Some(code) => format!("with exit code {}", code), + None => "without exit code".to_string(), + }; + self.logger.error(&format!( + "Command `{} {}` failed {code} and produced the following output:\n{}\n{}", + cmd.get_program().to_string_lossy(), + cmd.get_args() + .map(|arg| arg.to_str().unwrap()) + .collect::>() + .join(" "), + String::from_utf8_lossy(&result.stdout), + String::from_utf8_lossy(&result.stderr), + )); + } + if self.cli.nix_debugger && command.ends_with("bin/nix") { + self.logger.info("Starting Nix debugger ..."); + cmd.arg("--debugger").exec(); + } + if !options.dont_exit { + bail!("Command failed") + } else { + Ok(result) + } + } else { + Ok(result) + } + } + } + + pub fn prepare_command( + &mut self, + command: &str, + args: &[&str], + ) -> Result { + let cmd = if command.starts_with("nix") { + let mut flags = NIX_FLAGS.to_vec(); + + // handle --nix-option key value + for chunk in self.cli.nix_option.chunks_exact(2) { + flags.push("--option"); + flags.push(&chunk[0]); + flags.push(&chunk[1]); + } + + flags.extend_from_slice(args); + + let mut cmd = match env::var("DEVENV_NIX") { + Ok(devenv_nix) => std::process::Command::new(format!("{devenv_nix}/bin/{command}")), + Err(_) => { + self.logger.error( + "$DEVENV_NIX is not set, but required as devenv doesn't work without a few Nix patches." + ); + self.logger.error( + "Please follow https://devenv.sh/getting-started/ to install devenv.", + ); + bail!("$DEVENV_NIX is not set") + } + }; + + if self.cli.impure || self.config.impure { + flags.push("--impure"); + } + + cmd.args(flags); + cmd + } else { + let mut cmd = std::process::Command::new(command); + cmd.args(args); + cmd + }; + + if self.cli.verbose { + self.logger.debug(&format!( + "Running command: {} {}", + command, + cmd.get_args() + .map(|arg| arg.to_str().unwrap()) + .collect::>() + .join(" ") + )); + } + + Ok(cmd) + } +} diff --git a/devenv/src/config.rs b/devenv/src/config.rs new file mode 100644 index 000000000..61383b801 --- /dev/null +++ b/devenv/src/config.rs @@ -0,0 +1,144 @@ +use miette::{IntoDiagnostic, Result}; +use schematic::{schema::JsonSchemaRenderer, schema::SchemaGenerator, ConfigLoader}; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, path::Path}; + +const YAML_CONFIG: &str = "devenv.yaml"; + +#[derive(schematic::Config, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[config(rename_all = "camelCase")] +#[serde(rename_all = "camelCase")] +pub struct Input { + #[serde(skip_serializing_if = "Option::is_none", default)] + pub url: Option, + #[serde(skip_serializing_if = "is_true", default = "true_default")] + #[setting(default = true)] + pub flake: bool, + #[serde(skip_serializing_if = "Option::is_none", default)] + pub follows: Option, + #[serde(skip_serializing_if = "HashMap::is_empty", default)] + pub inputs: HashMap, + #[serde(skip_serializing_if = "Vec::is_empty", default)] + pub overlays: Vec, +} + +impl Input { + pub fn new() -> Self { + Input { + url: None, + flake: true, + follows: None, + inputs: HashMap::new(), + overlays: Vec::new(), + } + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct FlakeInput { + pub url: Option, + pub inputs: HashMap, + pub flake: bool, +} + +impl From<&Input> for FlakeInput { + fn from(input: &Input) -> Self { + FlakeInput { + url: input.url.clone(), + inputs: input.inputs.clone(), + flake: input.flake, + } + } +} + +fn true_default() -> bool { + true +} +fn false_default() -> bool { + false +} +fn is_true(b: &bool) -> bool { + *b +} + +fn is_false(b: &bool) -> bool { + !*b +} + +#[derive(schematic::Config, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub struct Clean { + pub enabled: bool, + pub keep: Vec, + // TODO: executables? +} + +#[derive(schematic::Config, Clone, Serialize, Debug)] +#[config(rename_all = "camelCase")] +#[serde(rename_all = "camelCase")] +pub struct Config { + #[serde(skip_serializing_if = "HashMap::is_empty", default)] + #[setting(nested)] + pub inputs: HashMap, + #[serde(skip_serializing_if = "is_false", default = "false_default")] + pub allow_unfree: bool, + #[serde(skip_serializing_if = "is_false", default = "false_default")] + pub allow_broken: bool, + #[serde(skip_serializing_if = "Vec::is_empty", default)] + pub imports: Vec, + #[serde(skip_serializing_if = "Vec::is_empty", default)] + pub permitted_insecure_packages: Vec, + #[serde(skip_serializing_if = "Option::is_none", default = "std::option::None")] + #[setting(nested)] + pub clean: Option, + #[serde(skip_serializing_if = "is_false", default = "false_default")] + pub impure: bool, +} + +pub fn write_json_schema() { + let mut generator = SchemaGenerator::default(); + generator.add::(); + generator + .generate("devenv.schema.json", JsonSchemaRenderer::default()) + .expect("can't generate schema"); +} + +impl Config { + pub fn load() -> Result { + let mut loader = ConfigLoader::::new(); + let file = Path::new(YAML_CONFIG); + let _ = loader.file_optional(file); + let result = loader.load().into_diagnostic(); + Ok(result?.config) + } + + pub fn write(&self) { + let yaml = serde_yaml::to_string(&self).unwrap(); + std::fs::write(YAML_CONFIG, yaml).expect("Failed to write devenv.yaml"); + } + + pub fn add_input(&mut self, name: &str, url: &str, follows: &[String]) { + let mut inputs = HashMap::new(); + + let mut input_names = self.inputs.clone(); + // we know we have a default for this one + input_names.insert(String::from("nixpkgs"), Input::new()); + + for follow in follows { + // check if it's not in self.inputs + match input_names.get(follow) { + Some(_) => { + let mut input = Input::new(); + input.follows = Some(follow.to_string()); + inputs.insert(follow.to_string(), input); + } + None => { + panic!("Input {follow} does not exist so it can't be followed."); + } + } + } + let mut input = Input::new(); + input.url = Some(url.to_string()); + input.inputs = inputs; + self.inputs.insert(name.to_string(), input); + } +} diff --git a/devenv/src/flake.tmpl.nix b/devenv/src/flake.tmpl.nix new file mode 100644 index 000000000..6d7d0ec30 --- /dev/null +++ b/devenv/src/flake.tmpl.nix @@ -0,0 +1,103 @@ +{ + inputs = + let + __DEVENV_VARS__ + in { + pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; + pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + devenv.url = "github:cachix/devenv?dir=src/modules"; + } // (if builtins.pathExists (devenv_dotfile + "/flake.json") + then builtins.fromJSON (builtins.readFile (devenv_dotfile + "/flake.json")) + else { }); + + outputs = { nixpkgs, ... }@inputs: + let + __DEVENV_VARS__ + devenv = + if builtins.pathExists (devenv_dotfile + "/devenv.json") + then builtins.fromJSON (builtins.readFile (devenv_dotfile + "/devenv.json")) + else { }; + getOverlays = inputName: inputAttrs: + map + (overlay: + let + input = inputs.${inputName} or (throw "No such input `${inputName}` while trying to configure overlays."); + in + input.overlays.${overlay} or (throw "Input `${inputName}` has no overlay called `${overlay}`. Supported overlays: ${nixpkgs.lib.concatStringsSep ", " (builtins.attrNames input.overlays)}")) + inputAttrs.overlays or [ ]; + overlays = nixpkgs.lib.flatten (nixpkgs.lib.mapAttrsToList getOverlays (devenv.inputs or { })); + pkgs = import nixpkgs { + inherit system; + config = { + allowUnfree = devenv.allowUnfree or false; + allowBroken = devenv.allowBroken or false; + permittedInsecurePackages = devenv.permittedInsecurePackages or [ ]; + }; + inherit overlays; + }; + lib = pkgs.lib; + importModule = path: + if lib.hasPrefix "./" path + then if lib.hasSuffix ".nix" path + then ./. + (builtins.substring 1 255 path) + else ./. + (builtins.substring 1 255 path) + "/devenv.nix" + else if lib.hasPrefix "../" path + then throw "devenv: ../ is not supported for imports" + else + let + paths = lib.splitString "/" path; + name = builtins.head paths; + input = inputs.${name} or (throw "Unknown input ${name}"); + subpath = "/${lib.concatStringsSep "/" (builtins.tail paths)}"; + devenvpath = "${input}" + subpath + "/devenv.nix"; + in + if builtins.pathExists devenvpath + then devenvpath + else throw (devenvpath + " file does not exist for input ${name}."); + project = pkgs.lib.evalModules { + specialArgs = inputs // { inherit inputs pkgs; }; + modules = [ + (inputs.devenv.modules + /top-level.nix) + { + devenv.cliVersion = version; + devenv.root = devenv_root; + devenv.dotfile = pkgs.lib.mkForce (devenv_root + "/" + devenv_dotfile_string); + } + (if container_name != null then { + container.isBuilding = pkgs.lib.mkForce true; + containers.${container_name}.isBuilding = true; + } else { }) + ] ++ (map importModule (devenv.imports or [ ])) ++ [ + ./devenv.nix + (devenv.devenv or { }) + (if builtins.pathExists ./devenv.local.nix then ./devenv.local.nix else { }) + ]; + }; + config = project.config; + + options = pkgs.nixosOptionsDoc { + options = builtins.removeAttrs project.options [ "_module" ]; + # Unpack Nix types, e.g. literalExpression, mDoc. + transformOptions = + let isDocType = v: builtins.elem v [ "literalDocBook" "literalExpression" "literalMD" "mdDoc" ]; + in lib.attrsets.mapAttrs (_: v: + if v ? _type && isDocType v._type then + v.text + else if v ? _type && v._type == "derivation" then + v.name + else + v + ); + }; + in + { + packages."${system}" = { + optionsJSON = options.optionsJSON; + inherit (config) info procfileScript procfileEnv procfile; + ci = config.ciDerivation; + }; + devenv = config; + devShell."${system}" = config.shell; + }; + } diff --git a/devenv/src/log.rs b/devenv/src/log.rs new file mode 100644 index 000000000..2a028729e --- /dev/null +++ b/devenv/src/log.rs @@ -0,0 +1,100 @@ +use ansiterm::Colour::{Blue, DarkGray, Green, Red, Yellow}; +use std::io::Write; +use std::time::Instant; + +pub struct LogProgress { + message: String, + start: Option, + pub failed: bool, +} + +impl LogProgress { + pub fn new(message: &str, newline: bool) -> LogProgress { + let prefix = Blue.paint("•"); + print!("{} {} ...", prefix, message); + if newline { + println!(); + } + std::io::stdout().flush().unwrap(); + LogProgress { + message: message.to_string(), + start: Some(Instant::now()), + failed: false, + } + } +} + +impl Drop for LogProgress { + fn drop(&mut self) { + let duration = self.start.unwrap_or_else(Instant::now).elapsed(); + let prefix = if self.failed { + Red.paint("✖") + } else { + Green.paint("✔") + }; + println!( + "\r{} {} in {:.1}s.", + prefix, + self.message, + duration.as_secs_f32() + ); + } +} + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum Level { + Error, + Warn, + Info, + Debug, +} + +pub struct Logger { + level: Level, +} + +impl Logger { + pub fn new(level: Level) -> Logger { + Logger { level } + } + + pub fn info(&self, message: &str) { + self.log(message, Level::Info); + } + + pub fn error(&self, message: &str) { + self.log(message, Level::Error); + } + + pub fn debug(&self, message: &str) { + self.log(message, Level::Debug); + } + + pub fn warn(&self, message: &str) { + self.log(message, Level::Warn); + } + + fn log(&self, message: &str, level: Level) { + if level > self.level { + return; + } + match level { + Level::Info => { + let prefix = Blue.paint("•"); + println!("{} {}", prefix, message); + } + Level::Error => { + let prefix = Red.paint("✖"); + println!("{} {}", prefix, message); + } + Level::Warn => { + let prefix = Yellow.paint("•"); + println!("{} {}", prefix, message); + } + Level::Debug => { + let prefix = DarkGray.paint("•"); + println!("{} {}", prefix, message); + } + } + } +} diff --git a/devenv/src/main.rs b/devenv/src/main.rs new file mode 100644 index 000000000..f90bf1421 --- /dev/null +++ b/devenv/src/main.rs @@ -0,0 +1,1210 @@ +mod command; +mod config; +mod log; + +use clap::{crate_version, Parser, Subcommand}; +use cli_table::{print_stderr, Table, WithTitle}; +use include_dir::{include_dir, Dir}; +use miette::{bail, Result}; +use serde::Deserialize; +use std::collections::HashMap; +use std::os::unix::fs::symlink; +use std::str::FromStr; +use std::time::{SystemTime, UNIX_EPOCH}; +use std::{ + fs, + os::unix::{fs::PermissionsExt, process::CommandExt}, + path::{Path, PathBuf}, +}; + +// templates +const FLAKE_TMP: &str = include_str!("flake.tmpl.nix"); +const REQUIRED_FILES: [&str; 4] = ["devenv.nix", "devenv.yaml", ".envrc", ".gitignore"]; +const PROJECT_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/init"); +// project vars +const DEVENV_FLAKE: &str = ".devenv.flake.nix"; + +#[derive(Parser)] +#[command( + color = clap::ColorChoice::Auto, + dont_delimit_trailing_values = true, + about = format!("https://devenv.sh {}: Fast, Declarative, Reproducible, and Composable Developer Environments", crate_version!()) +)] +struct Cli { + #[arg(short, long, help = "Enable debug log level.")] + verbose: bool, + + #[arg(short, long, default_value_t = default_system())] + system: String, + + #[arg(short, long, help = "Relax the hermeticity of the environment.")] + impure: bool, + + // TODO: --no-clean? + #[arg( + short, + long, + num_args = 0.., + value_delimiter = ',', + help = "Ignore existing environment variables when entering the shell. Pass a list of comma-separated environment variables to let through." + )] + clean: Option>, + + #[arg(short = 'd', long, help = "Enter Nix debugger on failure.")] + nix_debugger: bool, + + #[arg( + short, + long, + num_args = 2, + value_delimiter = ' ', + help = "Pass additional options to nix commands, see `man nix.conf` for full list." + )] + nix_option: Vec, + + #[arg( + short, + long, + num_args = 2, + value_delimiter = ' ', + help = "Override inputs in devenv.yaml." + )] + override_input: Vec, + + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand, Clone)] +enum Commands { + #[command(about = "Scaffold devenv.yaml, devenv.nix, .gitignore and .envrc.")] + Init { target: Option }, + + #[command(about = "Activate the developer environment. https://devenv.sh/basics/")] + Shell { + cmd: Option, + args: Vec, + }, + + #[command(about = "Update devenv.lock from devenv.yaml inputs. http://devenv.sh/inputs/")] + Update { name: Option }, + + #[command( + about = "Search for packages and options in nixpkgs. https://devenv.sh/packages/#searching-for-a-file" + )] + Search { name: String }, + + #[command( + alias = "show", + about = "Print information about this developer environment." + )] + Info {}, + + #[command(about = "Start processes in the foreground. https://devenv.sh/processes/")] + Up { + #[arg(help = "Start a specific process.")] + process: Option, + + #[arg(short, long, help = "Start processes in the background.")] + detach: bool, + }, + + Processes { + #[command(subcommand)] + command: ProcessesCommand, + }, + + #[command(about = "Run tests. http://devenv.sh/tests/", alias = "ci")] + Test { + #[arg(short, long, help = "Don't override .devenv to a temporary directory.")] + dont_override_dotfile: bool, + }, + + Container { + #[arg(short, long)] + registry: Option, + + #[arg(long, hide = true)] + copy: bool, + + #[arg(long, hide = true)] + docker_run: bool, + + #[arg(short, long)] + copy_args: Vec, + + #[arg(hide = true)] + name: Option, + + #[command(subcommand)] + command: Option, + }, + + Inputs { + #[command(subcommand)] + command: InputsCommand, + }, + + #[command( + about = "Deletes previous shell generations. See http://devenv.sh/garbage-collection" + )] + Gc {}, + + #[command(about = "Build any attribute in devenv.nix.")] + Build { + #[arg(num_args=1..)] + attributes: Vec, + }, + + #[command(about = "Print the version of devenv.")] + Version {}, + + #[clap(hide = true)] + Assemble, + + #[clap(hide = true)] + PrintDevEnv { + #[arg(short, long)] + json: bool, + }, + + #[clap(hide = true)] + GenerateJSONSchema, +} + +#[derive(Subcommand, Clone)] +#[clap(about = "Start or stop processes.")] +enum ProcessesCommand { + #[command(alias = "start")] + Up { + process: Option, + + #[arg(short, long)] + detach: bool, + }, + + #[command(alias = "stop")] + Down {}, + // TODO: Status/Attach +} + +#[derive(Subcommand, Clone)] +#[clap(about = "Build, copy, or run a container. https://devenv.sh/containers/")] +enum ContainerCommand { + #[clap(about = "Build a container.")] + Build { name: String }, + + #[clap(about = "Copy a container.")] + Copy { name: String }, + + #[clap(about = "Run a container.")] + Run { name: String }, +} + +#[derive(Subcommand, Clone)] +#[clap(about = "Add an input to devenv.yaml. https://devenv.sh/inputs/")] +enum InputsCommand { + #[clap(about = "Add an input to devenv.yaml.")] + Add { + #[arg(help = "The name of the input.")] + name: String, + + #[arg( + help = "See https://devenv.sh/reference/yaml-options/#inputsnameurl for possible values." + )] + url: String, + + #[arg(short, long, help = "What inputs should follow your inputs?")] + follows: Vec, + }, +} + +struct App { + cli: Cli, + config: config::Config, + logger: log::Logger, + has_processes: Option, + container_name: Option, + // all kinds of paths + devenv_root: PathBuf, + devenv_dotfile: PathBuf, + devenv_dot_gc: PathBuf, + devenv_home_gc: PathBuf, +} + +fn main() -> Result<()> { + let cli = Cli::parse(); + + let level = if cli.verbose { + log::Level::Debug + } else { + log::Level::Info + }; + + let xdg_dirs = xdg::BaseDirectories::with_prefix("devenv").unwrap(); + xdg_dirs + .create_data_directory(Path::new("devenv")) + .expect("Failed to create DEVENV_HOME directory"); + let devenv_home = xdg_dirs.get_data_home(); + let devenv_home_gc = devenv_home.join("gc"); + std::fs::create_dir_all(&devenv_home_gc).expect("Failed to create DEVENV_HOME_GC directory"); + let devenv_root = std::env::current_dir().expect("Failed to get current directory"); + let devenv_dot_gc = devenv_root.join(".devenv").join("gc"); + std::fs::create_dir_all(&devenv_dot_gc).expect("Failed to create .devenv/gc directory"); + let devenv_dotfile = devenv_root.join(".devenv"); + let logger = log::Logger::new(level); + let mut config = config::Config::load()?; + for input in cli.override_input.chunks_exact(2) { + config.add_input(&input[0].clone(), &input[1].clone(), &[]); + } + + let mut app = App { + cli, + config, + has_processes: None, + logger, + container_name: None, + devenv_root, + devenv_dotfile, + devenv_dot_gc, + devenv_home_gc, + }; + + match app.cli.command.clone() { + Commands::Shell { cmd, args } => app.shell(&cmd, &args, true), + Commands::Test { + dont_override_dotfile, + } => app.test(dont_override_dotfile), + Commands::Version {} => Ok(println!("devenv {} ({})", crate_version!(), app.cli.system)), + Commands::Container { + registry, + copy, + docker_run, + copy_args, + name, + command, + } => { + app.container_name = name.clone(); + match name { + None => { + if let Some(c) = command { + match c { + ContainerCommand::Build { name } => { + app.container_name = Some(name.clone()); + let _ = app.container_build(&name)?; + } + ContainerCommand::Copy { name } => { + app.container_name = Some(name.clone()); + app.container_copy(&name, ©_args, registry.as_deref())?; + } + ContainerCommand::Run { name } => { + app.container_name = Some(name.clone()); + app.container_run(&name, ©_args, registry.as_deref())?; + } + } + } + } + Some(name) => { + match (copy, docker_run) { + (true, false) => { + app.logger.warn( + "--copy flag is deprecated, use `devenv container copy` instead", + ); + app.container_copy(&name, ©_args, registry.as_deref())?; + } + (_, true) => { + app.logger.warn( + "--docker-run flag is deprecated, use `devenv container run` instead", + ); + app.container_run(&name, ©_args, registry.as_deref())?; + } + _ => { + app.logger.warn("Calling without a subcommand is deprecated, use `devenv container build` instead"); + let _ = app.container_build(&name)?; + } + }; + } + }; + Ok(()) + } + Commands::Init { target } => app.init(&target), + Commands::Search { name } => app.search(&name), + Commands::Gc {} => app.gc(), + Commands::Info {} => app.info(), + Commands::Build { attributes } => app.build(&attributes), + Commands::Update { name } => app.update(&name), + Commands::Up { process, detach } => app.up(process.as_deref(), &detach), + Commands::Processes { command } => match command { + ProcessesCommand::Up { process, detach } => app.up(process.as_deref(), &detach), + ProcessesCommand::Down {} => app.down(), + }, + Commands::Inputs { command } => match command { + InputsCommand::Add { name, url, follows } => app.inputs_add(&name, &url, &follows), + }, + // hidden + Commands::Assemble => app.assemble(), + Commands::PrintDevEnv { json } => app.print_dev_env(json), + Commands::GenerateJSONSchema => { + config::write_json_schema(); + Ok(()) + } + } +} + +impl App { + fn processes_log(&self) -> PathBuf { + self.devenv_dotfile.join("processes.log") + } + + fn processes_pid(&self) -> PathBuf { + self.devenv_dotfile.join("processes.pid") + } + + fn init(&self, target: &Option) -> Result<()> { + let target = target + .clone() + .unwrap_or_else(|| fs::canonicalize(".").expect("Failed to get current directory")); + + // create directory target if not exists + if !target.exists() { + std::fs::create_dir_all(&target).expect("Failed to create target directory"); + } + + // fails if any of the required files already exists + for filename in REQUIRED_FILES { + let file_path = target.join(filename); + if file_path.exists() { + panic!("File already exists {}", file_path.display()); + } + } + + for filename in REQUIRED_FILES { + let path = PROJECT_DIR + .get_file(filename) + .unwrap_or_else(|| panic!("missing {} in the executable", filename)); + + // write path.contents to target/filename + let target_path = target.join(filename); + std::fs::write(target_path, path.contents()).expect("Failed to write file"); + + // check if direnv executable is available + let Ok(direnv) = which::which("direnv") else { + return Ok(()); + }; + + // run direnv allow + let status = std::process::Command::new(direnv) + .arg("allow") + .current_dir(&target) + .status() + .expect("Failed to run direnv allow"); + + if !status.success() { + match status.code() { + Some(code) => { + panic!("direnv allow failed with code: {code}!"); + } + None => { + panic!("direnv allow failed!"); + } + } + } + } + Ok(()) + } + + fn inputs_add(&mut self, name: &str, url: &str, follows: &[String]) -> Result<()> { + self.config.add_input(name, url, follows); + self.config.write(); + Ok(()) + } + + fn print_dev_env(&mut self, json: bool) -> Result<()> { + let (env, _) = self.get_dev_environment(json, false)?; + print!( + "{}", + String::from_utf8(env).expect("Failed to convert env to utf-8") + ); + Ok(()) + } + + fn shell(&mut self, cmd: &Option, args: &[String], replace_shell: bool) -> Result<()> { + let develop_args = self.prepare_shell(cmd, args)?; + + let options = command::Options { + replace_shell, + ..command::Options::default() + }; + + let develop_args = develop_args + .iter() + .map(|s| s.as_str()) + .collect::>(); + + self.run_nix("nix", &develop_args, &options)?; + Ok(()) + } + + fn prepare_shell(&mut self, cmd: &Option, args: &[String]) -> Result> { + self.assemble()?; + let (_, gc_root) = self.get_dev_environment(false, true)?; + + let mut develop_args = vec![ + "develop", + gc_root.to_str().expect("gc root should be utf-8"), + ]; + + let default_clean = config::Clean { + enabled: false, + keep: vec![], + }; + let config_clean = self.config.clean.as_ref().unwrap_or(&default_clean); + if self.cli.clean.is_some() || config_clean.enabled { + develop_args.push("--ignore-environment"); + + let keep = match &self.cli.clean { + Some(clean) => clean, + None => &config_clean.keep, + }; + + for env in keep { + develop_args.push("--keep"); + develop_args.push(env); + } + + develop_args.push("-c"); + develop_args.push("bash"); + develop_args.push("--norc"); + develop_args.push("--noprofile") + } + + match cmd { + Some(cmd) => { + develop_args.push("-c"); + develop_args.push(cmd); + let args = args.iter().map(|s| s.as_str()).collect::>(); + develop_args.extend_from_slice(&args); + } + None => { + self.logger.info("Entering shell"); + } + }; + + Ok(develop_args.into_iter().map(|s| s.to_string()).collect()) + } + + fn update(&mut self, input_name: &Option) -> Result<()> { + let msg = match input_name { + Some(input_name) => format!("Updating devenv.lock with input {input_name}"), + None => "Updating devenv.lock".to_string(), + }; + let _logprogress = log::LogProgress::new(&msg, true); + self.assemble()?; + + match input_name { + Some(input_name) => { + self.run_nix( + "nix", + &["flake", "lock", "--update-input", input_name], + &command::Options::default(), + )?; + } + None => { + self.run_nix("nix", &["flake", "update"], &command::Options::default())?; + } + } + Ok(()) + } + + fn container_build(&mut self, name: &str) -> Result { + let options = command::Options { + use_cachix: true, + ..command::Options::default() + }; + + let _logprogress = log::LogProgress::new(&format!("Building {name} container"), true); + + self.assemble()?; + + let container_store_path = self.run_nix( + "nix", + &[ + "build", + "--print-out-paths", + "--no-link", + &format!(".#devenv.containers.{name}.derivation"), + ], + &options, + )?; + + let container_store_path_string = String::from_utf8_lossy(&container_store_path.stdout) + .to_string() + .trim() + .to_string(); + println!("{}", container_store_path_string); + Ok(container_store_path_string) + } + + fn container_copy( + &mut self, + name: &str, + copy_args: &[String], + registry: Option<&str>, + ) -> Result<()> { + let spec = self.container_build(name)?; + + let options = command::Options { + use_cachix: true, + ..command::Options::default() + }; + + let _logprogress = log::LogProgress::new(&format!("Copying {name} container"), false); + + let copy_script = self.run_nix( + "nix", + &[ + "build", + "--print-out-paths", + "--no-link", + &format!(".#devenv.containers.{name}.copyScript"), + ], + &options, + )?; + + let copy_script = String::from_utf8_lossy(©_script.stdout) + .to_string() + .trim() + .to_string(); + + let copy_args = [ + spec, + registry.unwrap_or("false").to_string(), + copy_args.join(" "), + ]; + + self.logger + .info(&format!("Running {copy_script} {}", copy_args.join(" "))); + + let status = std::process::Command::new(copy_script) + .args(copy_args) + .status() + .expect("Failed to run copy script"); + + if !status.success() { + bail!("Failed to copy container") + } else { + Ok(()) + } + } + + fn container_run( + &mut self, + name: &str, + copy_args: &[String], + registry: Option<&str>, + ) -> Result<()> { + if registry.is_some() { + self.logger + .warn("Ignoring --registry flag when running container"); + }; + self.container_copy(name, copy_args, Some("docker-daemon:"))?; + + let options = command::Options { + use_cachix: true, + ..command::Options::default() + }; + + let _logprogress = log::LogProgress::new(&format!("Running {name} container"), false); + + let run_script = self.run_nix( + "nix", + &[ + "build", + "--print-out-paths", + "--no-link", + &format!(".#devenv.containers.{name}.dockerRun"), + ], + &options, + )?; + + let run_script = String::from_utf8_lossy(&run_script.stdout) + .to_string() + .trim() + .to_string(); + + let status = std::process::Command::new(run_script) + .status() + .expect("Failed to run container script"); + + if !status.success() { + bail!("Failed to run container") + } else { + Ok(()) + } + } + + fn gc(&mut self) -> Result<()> { + let start = std::time::Instant::now(); + + let (to_gc, removed_symlinks) = { + let _logprogress = log::LogProgress::new( + &format!( + "Removing non-existings symlinks in {} ...", + &self.devenv_home_gc.display() + ), + false, + ); + cleanup_symlinks(&self.devenv_home_gc) + }; + + self.logger + .info(&format!("Found {} active environments.", to_gc.len())); + self.logger.info(&format!( + "Deleted {} dangling environments (most likely due to previous GC).", + removed_symlinks.len() + )); + + { + let _logprogress = log::LogProgress::new( + "Running garbage collection (this process may take some time) ...", + false, + ); + let paths: Vec<&str> = to_gc + .iter() + .filter_map(|path_buf| path_buf.to_str()) + .collect(); + let args: Vec<&str> = ["store", "gc"] + .iter() + .chain(paths.iter()) + .copied() + .collect(); + self.run_nix("nix", &args, &command::Options::default())?; + } + + let (after_gc, _) = cleanup_symlinks(&self.devenv_home_gc); + let end = std::time::Instant::now(); + + println!(); + self.logger.info(&format!( + "Done. Successfully removed {} symlinks in {}s.", + to_gc.len() - after_gc.len(), + (end - start).as_secs_f32() + )); + Ok(()) + } + + fn search(&mut self, name: &str) -> Result<()> { + self.assemble()?; + + let options = self.run_nix( + "nix", + &[ + "--offline", + "build", + "--no-link", + "--print-out-paths", + ".#optionsJSON", + ], + &command::Options { + use_cachix: true, + ..command::Options::default() + }, + )?; + + let options_str = std::str::from_utf8(&options.stdout).unwrap().trim(); + let options_path = PathBuf::from_str(options_str) + .expect("options store path should be a utf-8") + .join("share") + .join("doc") + .join("nixos") + .join("options.json"); + let options_contents = fs::read(options_path).expect("Failed to read options.json"); + let options_json: OptionResults = + serde_json::from_slice(&options_contents).expect("Failed to parse options.json"); + + let options_results = options_json + .0 + .into_iter() + .filter(|(key, _)| key.contains(name)) + .map(|(key, value)| DevenvOptionResult { + name: key, + type_: value.type_, + default: value.default.unwrap_or_default(), + description: value.description, + }) + .collect::>(); + let results_options_count = options_results.len(); + + let search = self.run_nix( + "nix", + &["search", "--json", "nixpkgs", name], + &command::Options::default(), + )?; + let search_json: PackageResults = + serde_json::from_slice(&search.stdout).expect("Failed to parse search results"); + let search_results = search_json + .0 + .into_iter() + .map(|(key, value)| DevenvPackageResult { + name: format!( + "pkgs.{}", + key.split('.').skip(2).collect::>().join(".") + ), + version: value.version, + description: value.description.chars().take(80).collect::(), + }) + .collect::>(); + let search_results_count = search_results.len(); + + if !search_results.is_empty() { + print_stderr(search_results.with_title()).expect("Failed to print search results"); + } + + if !options_results.is_empty() { + print_stderr(options_results.with_title()).expect("Failed to print options results"); + } + + self.logger.info(&format!("Found {search_results_count} packages and {results_options_count} options for '{name}'.")); + Ok(()) + } + + fn has_processes(&mut self) -> Result { + if self.has_processes.is_none() { + let result = self.run_nix( + "nix", + &["eval", ".#devenv.processes", "--json"], + &command::Options::default(), + )?; + let processes = String::from_utf8_lossy(&result.stdout).to_string(); + self.has_processes = Some(processes.trim() != "{}"); + } + Ok(self.has_processes.unwrap()) + } + + fn test(&mut self, dont_override_dotfile: bool) -> Result<()> { + let tmpdir = tempdir::TempDir::new_in(&self.devenv_root, ".devenv") + .expect("Failed to create temporary directory"); + if !dont_override_dotfile { + self.logger.info(&format!( + "Overriding .devenv to {}", + tmpdir.path().file_name().unwrap().to_str().unwrap() + )); + self.devenv_dotfile = tmpdir.as_ref().to_path_buf(); + // TODO: don't add gc roots for tests + self.devenv_dot_gc = self.devenv_dotfile.join("gc"); + } + self.assemble()?; + + // collect tests + let test_script = { + let _logprogress = log::LogProgress::new("Building tests", false); + self.run_nix( + "nix", + &["build", ".#devenv.test", "--no-link", "--print-out-paths"], + &command::Options::default(), + )? + }; + + let test_script_string = String::from_utf8_lossy(&test_script.stdout) + .to_string() + .trim() + .to_string(); + if test_script_string.is_empty() { + self.logger.error("No tests found."); + tmpdir + .close() + .expect("Failed to remove temporary directory"); + bail!("No tests found"); + } + + if self.has_processes()? { + self.up(None, &true)?; + } + + let result = { + let _logprogress = log::LogProgress::new("Running tests", true); + + self.logger + .debug(&format!("Running command: {test_script_string}")); + + let develop_args = self.prepare_shell(&Some(test_script_string), &[])?; + let develop_args = develop_args + .iter() + .map(|s| s.as_str()) + .collect::>(); + let mut cmd = self.prepare_command("nix", &develop_args)?; + cmd.stdin(std::process::Stdio::inherit()); + cmd.stderr(std::process::Stdio::inherit()); + cmd.stdout(std::process::Stdio::inherit()); + cmd.output().expect("Failed to run tests") + }; + + if self.has_processes()? { + self.down()?; + } + + tmpdir + .close() + .expect("Failed to remove temporary directory"); + + if !result.status.success() { + self.logger.error("Tests failed :("); + bail!("Tests failed"); + } else { + self.logger.info("Tests passed :)"); + Ok(()) + } + } + + fn info(&mut self) -> Result<()> { + self.assemble()?; + + // TODO: use --json + let metadata = self.run_nix("nix", &["flake", "metadata"], &command::Options::default())?; + + let re = regex::Regex::new(r"(Inputs:.+)$").unwrap(); + let metadata_str = String::from_utf8_lossy(&metadata.stdout); + let inputs = match re.captures(&metadata_str) { + Some(captures) => captures.get(1).unwrap().as_str(), + None => "", + }; + + let info_ = self.run_nix( + "nix", + &["eval", "--raw", ".#info"], + &command::Options::default(), + )?; + println!("{}\n{}", inputs, &String::from_utf8_lossy(&info_.stdout)); + Ok(()) + } + + fn build(&mut self, attributes: &[String]) -> Result<()> { + self.assemble()?; + + let formatted_strings: Vec = attributes + .iter() + .map(|attr| format!("#.devenv.{}", attr)) + .collect(); + + let mut args: Vec<&str> = formatted_strings.iter().map(|s| s.as_str()).collect(); + + args.insert(0, "build"); + self.run_nix("nix", &args, &command::Options::default())?; + Ok(()) + } + + fn add_gc(&mut self, name: &str, path: &Path) -> Result<()> { + self.run_nix( + "nix-store", + &[ + "--add-root", + self.devenv_dot_gc.join(name).to_str().unwrap(), + "-r", + path.to_str().unwrap(), + ], + &command::Options::default(), + )?; + let link_path = self + .devenv_dot_gc + .join(format!("{}-{}", name, get_now_with_nanoseconds())); + symlink_force(&self.logger, path, &link_path); + Ok(()) + } + + fn up(&mut self, process: Option<&str>, detach: &bool) -> Result<()> { + self.assemble()?; + if !self.has_processes()? { + self.logger + .error("No 'processes' option defined: https://devenv.sh/processes/"); + bail!("No processes defined"); + } + + let proc_script_string: String; + { + let _logprogress = log::LogProgress::new("Building processes", true); + + let options = command::Options { + use_cachix: true, + ..command::Options::default() + }; + let proc_script = self.run_nix( + "nix", + &[ + "build", + "--no-link", + "--print-out-paths", + ".#procfileScript", + ], + &options, + )?; + + proc_script_string = String::from_utf8_lossy(&proc_script.stdout) + .to_string() + .trim() + .to_string(); + self.add_gc("procfilescript", Path::new(&proc_script_string))?; + } + + { + let _logprogress = log::LogProgress::new("Starting processes", false); + + let process = process.unwrap_or(""); + + let processes_script = self.devenv_dotfile.join("processes"); + let tui_enabled = if *detach { "0" } else { "1" }; + fs::write( + &processes_script, + indoc::formatdoc! {" + #!/usr/bin/env bash + export PC_TUI_ENABLED={tui_enabled} + exec {proc_script_string} {process} + "}, + ) + .expect("Failed to write PROCESSES_SCRIPT"); + + std::fs::set_permissions(&processes_script, std::fs::Permissions::from_mode(0o755)) + .expect("Failed to set permissions"); + + let args = + self.prepare_shell(&Some(processes_script.to_str().unwrap().to_string()), &[])?; + let args = args.iter().map(|s| s.as_str()).collect::>(); + let mut cmd = self.prepare_command("nix", &args)?; + + if *detach { + let log_file = std::fs::File::create(self.processes_log()) + .expect("Failed to create PROCESSES_LOG"); + let process = cmd + .stdout(log_file.try_clone().expect("Failed to clone Stdio")) + .stderr(log_file) + .spawn() + .expect("Failed to spawn process"); + + std::fs::write(self.processes_pid(), process.id().to_string()) + .expect("Failed to write PROCESSES_PID"); + self.logger.info(&format!("PID is {}", process.id())); + self.logger.info(&format!( + "See logs: $ tail -f {}", + self.processes_log().display() + )); + self.logger.info("Stop: $ devenv processes stop"); + } else { + cmd.exec(); + } + Ok(()) + } + } + + fn down(&self) -> Result<()> { + if !PathBuf::from(&self.processes_pid()).exists() { + self.logger.error("No processes running."); + bail!("No processes running"); + } + + let pid = std::fs::read_to_string(self.processes_pid()) + .expect("Failed to read PROCESSES_PID") + .parse::() + .expect("Failed to parse PROCESSES_PID"); + + self.logger + .info(&format!("Stopping process with PID {}", pid)); + + let pid = nix::unistd::Pid::from_raw(pid); + match nix::sys::signal::kill(pid, nix::sys::signal::Signal::SIGTERM) { + Ok(_) => {} + Err(_) => { + self.logger + .error(&format!("Process with PID {} not found.", pid)); + bail!("Process not found"); + } + } + + std::fs::remove_file(self.processes_pid()).expect("Failed to remove PROCESSES_PID"); + Ok(()) + } + + fn assemble(&mut self) -> Result<()> { + if !PathBuf::from("devenv.nix").exists() { + panic!(indoc::indoc! {" + File devenv.nix does not exist. To get started, run: + + $ devenv init + "}); + } + std::fs::create_dir_all(&self.devenv_dot_gc) + .unwrap_or_else(|_| panic!("Failed to create {}", self.devenv_dot_gc.display())); + + let mut flake_inputs = HashMap::new(); + for (input, attrs) in self.config.inputs.iter() { + flake_inputs.insert(input.clone(), config::FlakeInput::from(attrs)); + } + fs::write( + self.devenv_dotfile.join("flake.json"), + serde_json::to_string(&flake_inputs).unwrap(), + ) + .expect("Failed to write flake.json"); + fs::write( + self.devenv_dotfile.join("devenv.json"), + serde_json::to_string(&self.config).unwrap(), + ) + .expect("Failed to write devenv.json"); + fs::write( + self.devenv_dotfile.join("imports.txt"), + self.config.imports.join("\n"), + ) + .expect("Failed to write imports.txt"); + + // create flake.devenv.nix + let vars = indoc::formatdoc!( + "version = \"{}\"; + system = \"{}\"; + devenv_root = \"{}\"; + devenv_dotfile = ./{}; + devenv_dotfile_string = \"{}\"; + container_name = {}; + ", + crate_version!(), + self.cli.system, + self.devenv_root.display(), + self.devenv_dotfile.file_name().unwrap().to_str().unwrap(), + self.devenv_dotfile.file_name().unwrap().to_str().unwrap(), + self.container_name + .as_deref() + .map(|s| format!("\"{}\"", s)) + .unwrap_or_else(|| "null".to_string()) + ); + let flake = FLAKE_TMP.replace("__DEVENV_VARS__", &vars); + std::fs::write(DEVENV_FLAKE, flake).expect("Failed to write flake.nix"); + Ok(()) + } + + fn get_dev_environment(&mut self, json: bool, logging: bool) -> Result<(Vec, PathBuf)> { + self.assemble()?; + let _logprogress = if logging { + Some(log::LogProgress::new("Building shell", false)) + } else { + None + }; + let gc_root = self.devenv_dot_gc.join("shell"); + let gc_root_str = gc_root.to_str().expect("gc root should be utf-8"); + + let mut args: Vec<&str> = vec!["print-dev-env", "--profile", gc_root_str]; + if json { + args.push("--json"); + } + + let env_ = self.run_nix("nix", &args, &command::Options::default())?; + + let options = command::Options { + logging: false, + ..command::Options::default() + }; + let args: Vec<&str> = vec!["-p", gc_root_str, "--delete-generations", "old"]; + self.run_nix("nix-env", &args, &options)?; + let now_ns = get_now_with_nanoseconds(); + let target = format!("{}-shell", now_ns); + symlink_force( + &self.logger, + &fs::canonicalize(&gc_root).expect("to resolve gc_root"), + &self.devenv_home_gc.join(target), + ); + + Ok((env_.stdout, gc_root)) + } +} + +fn symlink_force(logger: &log::Logger, link_path: &Path, target: &Path) { + let _lock = dotlock::Dotlock::create(target.with_extension("lock")).unwrap(); + logger.debug(&format!( + "Creating symlink {} -> {}", + link_path.display(), + target.display() + )); + + if target.exists() { + fs::remove_file(target).unwrap_or_else(|_| panic!("Failed to remove {}", target.display())); + } + + symlink(link_path, target).unwrap_or_else(|_| { + panic!( + "Failed to create symlink: {} -> {}", + link_path.display(), + target.display() + ) + }); +} + +fn default_system() -> String { + let arch = std::env::consts::ARCH; + let os = std::env::consts::OS; + format!("{arch}-{os}") +} + +fn get_now_with_nanoseconds() -> String { + let now = SystemTime::now(); + let duration = now.duration_since(UNIX_EPOCH).expect("Time went backwards"); + let secs = duration.as_secs(); + let nanos = duration.subsec_nanos(); + format!("{}.{}", secs, nanos) +} + +#[derive(Deserialize)] +struct PackageResults(HashMap); + +#[derive(Deserialize)] +struct PackageResult { + version: String, + description: String, +} + +#[derive(Deserialize)] +struct OptionResults(HashMap); + +#[derive(Deserialize)] +struct OptionResult { + #[serde(rename = "type")] + type_: String, + default: Option, + description: String, +} + +#[derive(Table)] +struct DevenvOptionResult { + #[table(title = "Option")] + name: String, + #[table(title = "Type")] + type_: String, + #[table(title = "Default")] + default: String, + #[table(title = "Description")] + description: String, +} + +#[derive(Table)] +struct DevenvPackageResult { + #[table(title = "Package")] + name: String, + #[table(title = "Version")] + version: String, + #[table(title = "Description")] + description: String, +} + +fn cleanup_symlinks(root: &Path) -> (Vec, Vec) { + let mut to_gc = Vec::new(); + let mut removed_symlinks = Vec::new(); + + for entry in fs::read_dir(root).expect("Failed to read directory") { + let entry = entry.expect("Failed to read entry"); + let path = entry.path(); + if path.is_symlink() { + let target = fs::canonicalize(&path).expect("Failed to read link"); + if !target.exists() { + removed_symlinks.push(path.clone()); + } else { + to_gc.push(target); + } + } + } + + (to_gc, removed_symlinks) +} diff --git a/docs/getting-started.md b/docs/getting-started.md index 7e48c63e1..493f0412d 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -91,9 +91,9 @@ Done. ## Commands -- ``devenv ci`` builds your developer environment and makes sure that all checks pass. Useful to run in your continuous integration environment. +- ``devenv test`` builds your developer environment and makes sure that all checks pass. Useful to run in your continuous integration environment. - ``devenv shell`` activates your developer environment. -- ``devenv search NAME`` searches packages matching NAME in Nixpkgs input. +- ``devenv search `` searches packages matching NAME in Nixpkgs input. - ``devenv update`` updates and pins inputs from ``devenv.yaml`` into ``devenv.lock``. - ``devenv gc`` [deletes unused environments](garbage-collection.md) to save disk space. - ``devenv up`` starts [processes](processes.md). diff --git a/docs/integrations/github-actions.md b/docs/integrations/github-actions.md index 319ff6916..923aa92cd 100644 --- a/docs/integrations/github-actions.md +++ b/docs/integrations/github-actions.md @@ -55,15 +55,15 @@ The above snippet does the following: If you're using a [self-hosted runner](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners), you can pre-install both Nix and devenv, and skip the associated steps. -### Built-in CI command +### `devenv test` -Devenv provides a convenient built-in `devenv ci` command. +Devenv provides a convenient built-in `devenv test` command. It builds the shell and runs any defined [pre-commit hooks](../pre-commit-hooks.md) against your repository. This is a quick and easy way to test that your development environment works as expected and lint your code at the same time. ```yaml - name: Build the devenv shell and run any pre-commit hooks - run: devenv ci + run: devenv test ``` ### Run a single command @@ -139,7 +139,7 @@ jobs: run: nix profile install --accept-flake-config tarball+https://install.devenv.sh/latest - name: Build the devenv shell and run any pre-commit hooks - run: devenv ci + run: devenv test - name: Run a single command in the devenv shell run: devenv shell hello diff --git a/docs/pre-commit-hooks.md b/docs/pre-commit-hooks.md index 524a86256..a2dd0299a 100644 --- a/docs/pre-commit-hooks.md +++ b/docs/pre-commit-hooks.md @@ -35,7 +35,7 @@ If you commit a Python or Markdown file or a script, these hooks will run at com ### 2) Verify formatting in CI -Run ``devenv ci``. +Run ``devenv test``. See [the list of all available hooks](reference/options.md#pre-commithooks). diff --git a/docs/reference/yaml-options.md b/docs/reference/yaml-options.md index 16cd7557f..fbb5e1a72 100644 --- a/docs/reference/yaml-options.md +++ b/docs/reference/yaml-options.md @@ -10,10 +10,16 @@ | inputs.<name>.overlays | A list of overlays to include from the input. | | imports | A list of relative paths or references to inputs to import ``devenv.nix``. | | permittedInsecurePackages | A list of insecure permitted packages. | +| clean.enabled | Clean the environment when entering the shell. Defaults to `false`. | +| clean.keep | A list of environment variables to keep when cleaning the environment. | +| impure | Relax the hermeticity of the environment. | !!! note "Added in 1.0" - relative file support in imports: `./mymodule.nix` + - `clean` + - `impure` + - `allowBroken` ## inputs.<name>.url diff --git a/docs/tests.md b/docs/tests.md index 6c1f53ff7..2b765034d 100644 --- a/docs/tests.md +++ b/docs/tests.md @@ -1,55 +1,77 @@ -To ease testing of your environments, -we provide a way to define the tests and to run them. +# Tests -## Writing devenv tests +Tests are a way to ensure that your development environment is working as expected. + +Running `devenv test` will build your environment and run the tests defined in `enterTest`. + +If you have [processes](/processes.md) defined in your environment, they will be started and stopped for you. + +## Writing your first test A simple test would look like: ```nix title="devenv.nix" { pkgs, ... }: { - tests.basic = { - nix = '' - { pkgs, ... }: { - packages = [ pkgs.ncdu ]; - } - ''; - test = '' - ncdu --version | grep "ncdu 2.2" - ''; - }; + packages = [ pkgs.ncdu ]; + + enterTest = '' + ncdu --version | grep "ncdu 2.2" + ''; } ``` ```shell-session $ devenv test -✔ Gathering tests in 0.3s. -• Found 1 test(s), running 1: -• Testing basic ... -• Running $ devenv ci -• Running .test.sh. -✔ Running basic in 16.7s. +✔ Building tests in 2.5s. +• Running tests ... +Setting up shell environment... +Running test... +ncdu 2.2 +✔ Running tests in 4.7s. +✔ Tests passed. in 0.0s. ``` -## Defining tests in a folder +By default, the `enterTest` detects if `.test.sh` file exists and runs it. -A simple test with a test script: +## Testing with processes -```shell-session -$ ls tests/mytest/ -.test.sh devenv.nix devenv.yaml -``` - -Define tests: +If you have [processes](/processes.md) defined in your environment, +they will be started and stopped for you. ```nix title="devenv.nix" -{ config, ... }: { - tests = config.lib.mkTests ./tests; +{ pkgs, ... }: { + services.nginx = { + enable = true; + httpConfig = '' + server { + listen 8080; + location / { + return 200 "Hello, world!"; + } + } + ''; + }; + + enterTest = '' + wait_for_port 8080 + curl -s localhost:8080 | grep "Hello, world!" + ''; } ``` -Run tests: - ```shell-session $ devenv test -... +✔ Building tests in 2.5s. +✔ Building processes in 15.7s. +• Starting processes ...• PID is 113105 +• See logs: $ tail -f /run/user/1000/nix-shell.upTad4/.tmpv25BxA/processes.log +• Stop: $ devenv processes stop +✔ Starting processes in 0.0s. +• Running tests ... +Setting up shell environment... +Running test... +ncdu 2.2 +✔ Running tests in 4.7s. +• Stopping process with PID 113105 +✔ Tests passed. in 0.0s. ``` \ No newline at end of file diff --git a/examples/clickhouse/.test.sh b/examples/clickhouse/.test.sh index 4fb1ced15..4670607e7 100755 --- a/examples/clickhouse/.test.sh +++ b/examples/clickhouse/.test.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -set -xe -timeout 20 bash -c 'until echo > /dev/tcp/localhost/9000; do sleep 0.5; done' -sleep 2 +set -xe +wait_for_port 9000 +sleep 2 clickhouse-client --query "SELECT 1" \ No newline at end of file diff --git a/examples/compose/devenv.nix b/examples/compose/devenv.nix new file mode 100644 index 000000000..27b38bda0 --- /dev/null +++ b/examples/compose/devenv.nix @@ -0,0 +1,8 @@ +{ + enterTest = '' + pushd projectB + devenv shell python -- --version + devenv shell cargo -- --version + popd + ''; +} diff --git a/examples/compose/devenv.yaml b/examples/compose/devenv.yaml new file mode 100644 index 000000000..bfc720c95 --- /dev/null +++ b/examples/compose/devenv.yaml @@ -0,0 +1,3 @@ +imports: +- ./projectA +- ./projectB \ No newline at end of file diff --git a/examples/compose/projectA/devenv.nix b/examples/compose/projectA/devenv.nix new file mode 100644 index 000000000..6a5634106 --- /dev/null +++ b/examples/compose/projectA/devenv.nix @@ -0,0 +1,3 @@ +{ + languages.python.enable = true; +} diff --git a/examples/compose/projectB/devenv.nix b/examples/compose/projectB/devenv.nix new file mode 100644 index 000000000..eb6020be4 --- /dev/null +++ b/examples/compose/projectB/devenv.nix @@ -0,0 +1,3 @@ +{ + languages.rust.enable = true; +} diff --git a/examples/compose/projectB/devenv.yaml b/examples/compose/projectB/devenv.yaml new file mode 100644 index 000000000..aff49e1ff --- /dev/null +++ b/examples/compose/projectB/devenv.yaml @@ -0,0 +1,6 @@ +inputs: + root: + url: git+file://. + flake: false +imports: +- root/examples/compose/projectA \ No newline at end of file diff --git a/examples/dotenv/.env b/examples/dotenv/.env deleted file mode 100644 index 118be34b6..000000000 --- a/examples/dotenv/.env +++ /dev/null @@ -1,3 +0,0 @@ -FOO=1 -BAR=2 -BAZ=3 diff --git a/examples/elasticmq/.test.sh b/examples/elasticmq/.test.sh index 8607368d1..e7030c09f 100755 --- a/examples/elasticmq/.test.sh +++ b/examples/elasticmq/.test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -timeout 60 bash -c 'until echo > /dev/tcp/localhost/9325; do sleep 0.5; done' +wait_for_port 9325 60 QUEUE_NAME=$(curl http://localhost:9325/statistics/queues -s | jq .[].name -r) diff --git a/examples/influxdb/.test.sh b/examples/influxdb/.test.sh index 270ec901e..14eec02f5 100755 --- a/examples/influxdb/.test.sh +++ b/examples/influxdb/.test.sh @@ -1,8 +1,7 @@ #!/usr/bin/env bash set -ex -# We test for the none-default port, configured in the nix file -timeout 60 bash -c 'until echo > /dev/tcp/localhost/8087; do sleep 0.5; done' +wait_for_port 8087 60 influx --port 8087 --execute "CREATE DATABASE devenv" DATABASES=$(influx --port 8087 --execute "SHOW DATABASES" | grep devenv) diff --git a/examples/mailpit/.test.sh b/examples/mailpit/.test.sh index 812751e5f..bb9cd59e1 100755 --- a/examples/mailpit/.test.sh +++ b/examples/mailpit/.test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -timeout 20 bash -c 'until echo > /dev/tcp/localhost/1025; do sleep 0.5; done' +wait_for_port 1025 sendmail john@example.com < /dev/tcp/localhost/9000; do sleep 0.5; done' +wait_for_port 9000 mc admin info local \ No newline at end of file diff --git a/examples/phoenix/.test.sh b/examples/phoenix/.test.sh index b687eac17..95a374e03 100755 --- a/examples/phoenix/.test.sh +++ b/examples/phoenix/.test.sh @@ -1,13 +1,12 @@ #!/usr/bin/env bash set -ex -# mix local.hex --force -# mix local.rebar --force -# echo Y | mix archive.install hex phx_new -# echo Y | mix phx.new hello -# sed -i.bak -e "s/username: \"postgres\",/socket_dir: System.get_env(\"PGDATA\"),/" \ -# ./hello/config/dev.exs && rm ./hello/config/dev.exs.bak -# devenv up& -# timeout 20 bash -c 'until echo > /dev/tcp/localhost/4000; do sleep 0.5; done' -# curl -s http://localhost:4000/ | grep "Phoenix Framework" -echo "this example is currently broken" -exit 2 + +mix local.hex --force +mix local.rebar --force +echo Y | mix archive.install hex phx_new +echo Y | mix phx.new hello +sed -i.bak -e "s/username: \"postgres\",/socket_dir: System.get_env(\"PGDATA\"),/" \ + ./hello/config/dev.exs && rm ./hello/config/dev.exs.bak + +wait_for_port 4000 +curl -s http://localhost:4000/ | grep "Phoenix Framework" diff --git a/examples/postgres-timescale/.test.sh b/examples/postgres-timescale/.test.sh index fc2497fb1..cdcefb437 100755 --- a/examples/postgres-timescale/.test.sh +++ b/examples/postgres-timescale/.test.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash set -ex -devenv up& + timeout 20 bash -c 'until psql -c "SELECT 1" mydb; do sleep 0.5; done' diff --git a/examples/postgres/.test.sh b/examples/postgres/.test.sh index 36f49e3d8..3fee75f8d 100755 --- a/examples/postgres/.test.sh +++ b/examples/postgres/.test.sh @@ -1,3 +1,6 @@ #!/usr/bin/env bash set -ex -timeout 20 bash -c 'until psql -h /tmp -c "SELECT 1" mydb 2>/dev/null; do sleep 0.5; done' + +echo $PGHOST + +timeout 20 bash -c 'until psql -c "SELECT 1" mydb 2>/dev/null; do sleep 0.5; done' \ No newline at end of file diff --git a/examples/postgres/devenv.nix b/examples/postgres/devenv.nix index 7c43ce11b..46b277893 100644 --- a/examples/postgres/devenv.nix +++ b/examples/postgres/devenv.nix @@ -8,10 +8,6 @@ initialDatabases = [{ name = "mydb"; }]; - settings = { - unix_socket_directories = "/tmp"; - }; - initialScript = '' CREATE EXTENSION IF NOT EXISTS postgis; ''; diff --git a/examples/rabbitmq/.test.sh b/examples/rabbitmq/.test.sh index 13a5b4bd2..c9959f62c 100755 --- a/examples/rabbitmq/.test.sh +++ b/examples/rabbitmq/.test.sh @@ -1,14 +1,4 @@ #!/usr/bin/env bash set -ex -devenv up & -DEVENV_PID=$! -export DEVENV_PID - -devenv_stop() { - pkill -P "$DEVENV_PID" -} - -trap devenv_stop EXIT - -timeout 20 bash -c 'until rabbitmqctl -q status 2>/dev/null; do sleep 0.5; done' +timeout 20 bash -c 'until rabbitmqctl -q status 2>/dev/null; do sleep 0.5; done' \ No newline at end of file diff --git a/examples/rubyonrails/.test.sh b/examples/rubyonrails/.test.sh index 2e03dd625..a055c6b04 100755 --- a/examples/rubyonrails/.test.sh +++ b/examples/rubyonrails/.test.sh @@ -2,7 +2,7 @@ set -ex pushd blog - timeout 20 bash -c 'until echo > /dev/tcp/localhost/5100; do sleep 0.5; done' + wait_for_port 5100 rails db:create curl -s http://localhost:5100/ | grep "version" popd diff --git a/examples/rust/app/Cargo.toml b/examples/rust/app/Cargo.toml index a79ae575f..df0d217e6 100644 --- a/examples/rust/app/Cargo.toml +++ b/examples/rust/app/Cargo.toml @@ -6,3 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] + + +[workspace] \ No newline at end of file diff --git a/examples/simple/.gitignore b/examples/simple/.gitignore new file mode 100644 index 000000000..4d058db7d --- /dev/null +++ b/examples/simple/.gitignore @@ -0,0 +1,9 @@ +# Devenv +.devenv* +devenv.local.nix + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml diff --git a/examples/varnish/.test.sh b/examples/varnish/.test.sh index 3c7e21296..b35bc9c94 100755 --- a/examples/varnish/.test.sh +++ b/examples/varnish/.test.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -ex -timeout 20 bash -c 'until echo > /dev/tcp/localhost/6081; do sleep 0.5; done' +wait_for_port 6081 caddy=$(curl http://localhost:8001) varnish=$(curl http://localhost:6081) diff --git a/flake.lock b/flake.lock index 1ac91e162..97cfaca12 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "flake-compat": { "flake": false, "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "owner": "edolstra", "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "type": "github" }, "original": { @@ -37,29 +37,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", "type": "github" }, "original": { @@ -76,11 +58,11 @@ ] }, "locked": { - "lastModified": 1660459072, - "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "lastModified": 1703887061, + "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=", "owner": "hercules-ci", "repo": "gitignore.nix", - "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5", "type": "github" }, "original": { @@ -98,11 +80,11 @@ "nixpkgs-regression": "nixpkgs-regression" }, "locked": { - "lastModified": 1708577783, - "narHash": "sha256-92xq7eXlxIT5zFNccLpjiP7sdQqQI30Gyui2p/PfKZM=", + "lastModified": 1709963241, + "narHash": "sha256-8RGoqq9ApGLGh6lNJfBRzqHy/S3u53HL8mDtmI7y9Hc=", "owner": "domenkozar", "repo": "nix", - "rev": "ecd0af0c1f56de32cbad14daa1d82a132bf298f8", + "rev": "e92c1fb8a57fe2e0bee725b1e7c68cfd8ffd55dc", "type": "github" }, "original": { @@ -112,34 +94,13 @@ "type": "github" } }, - "nix-github-actions": { - "inputs": { - "nixpkgs": [ - "poetry2nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1688870561, - "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", - "owner": "nix-community", - "repo": "nix-github-actions", - "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nix-github-actions", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1692808169, - "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "lastModified": 1709069307, + "narHash": "sha256-ER6N232jucnqu4+AK80RdmgBDuk61FAqmp36EMqkQns=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "rev": "9c1ea5e3a2a2578792438cba233f2763593e19c5", "type": "github" }, "original": { @@ -167,48 +128,26 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1685801374, - "narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=", + "lastModified": 1704874635, + "narHash": "sha256-YWuCrtsty5vVZvu+7BchAxmcYzTMfolSPP5io8+WYCg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c37ca420157f4abc31e26f436c1145f8951ff373", + "rev": "3dc440faeee9e889fe2d1b4d25ad0f430d449356", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-23.05", + "ref": "nixos-23.11", "repo": "nixpkgs", "type": "github" } }, - "poetry2nix": { - "inputs": { - "flake-utils": "flake-utils", - "nix-github-actions": "nix-github-actions", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1692876271, - "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", - "owner": "nix-community", - "repo": "poetry2nix", - "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "poetry2nix", - "type": "github" - } - }, "pre-commit-hooks": { "inputs": { "flake-compat": [ "flake-compat" ], - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils", "gitignore": "gitignore", "nixpkgs": [ "nixpkgs" @@ -216,11 +155,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1692274144, - "narHash": "sha256-BxTQuRUANQ81u8DJznQyPmRsg63t4Yc+0kcyq6OLz8s=", + "lastModified": 1708018599, + "narHash": "sha256-M+Ng6+SePmA8g06CmUZWi1AjG2tFBX9WCXElBHEKnyM=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "7e3517c03d46159fdbf8c0e5c97f82d5d4b0c8fa", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", "type": "github" }, "original": { @@ -234,7 +173,6 @@ "flake-compat": "flake-compat", "nix": "nix", "nixpkgs": "nixpkgs", - "poetry2nix": "poetry2nix", "pre-commit-hooks": "pre-commit-hooks" } }, @@ -252,21 +190,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index b548f0091..82eb06a3b 100644 --- a/flake.nix +++ b/flake.nix @@ -22,10 +22,6 @@ url = "github:domenkozar/nix/devenv-2.21"; inputs.nixpkgs.follows = "nixpkgs"; }; - inputs.poetry2nix = { - url = "github:nix-community/poetry2nix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; outputs = { self, nixpkgs, pre-commit-hooks, nix, ... }@inputs: let diff --git a/package.nix b/package.nix index 61c4f7d5a..b7fc8de27 100644 --- a/package.nix +++ b/package.nix @@ -1,33 +1,22 @@ { pkgs, inputs }: -let - python_slim = pkgs.python311.override { - mimetypesSupport = false; - x11Support = false; - stripConfig = true; - stripIdlelib = true; - stripTests = true; - stripTkinter = true; - enableLTO = false; - rebuildBytecode = false; - stripBytecode = true; - includeSiteCustomize = false; - enableOptimizations = false; - bzip2 = null; - gdbm = null; - xz = null; - ncurses = null; - readline = null; - sqlite = null; - tzdata = null; - self = python_slim; +pkgs.rustPlatform.buildRustPackage { + pname = "devenv"; + version = "1.0.0"; + + src = builtins.path { + path = ./.; + filter = path: type: + path != "Cargo.lock" || path != "Cargo.toml" || path != "src/devenv"; + }; + + cargoLock = { + lockFile = ./Cargo.lock; }; -in -(inputs.poetry2nix.legacyPackages.${pkgs.stdenv.system}.mkPoetryApplication { - projectDir = ./.; - python = python_slim; -}).overrideAttrs (old: { - makeWrapperArgs = [ - "--set DEVENV_NIX ${inputs.nix.packages.${pkgs.stdenv.system}.nix}" - ]; -}) + + nativeBuildInputs = [ pkgs.makeWrapper ]; + + postInstall = '' + wrapProgram $out/bin/devenv --set DEVENV_NIX ${inputs.nix.packages.${pkgs.stdenv.system}.nix} + ''; +} diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index e2c5f21ed..000000000 --- a/poetry.lock +++ /dev/null @@ -1,1189 +0,0 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. - -[[package]] -name = "babel" -version = "2.14.0" -description = "Internationalization utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, - {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, -] - -[package.extras] -dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] - -[[package]] -name = "bracex" -version = "2.4" -description = "Bash style brace expander." -optional = false -python-versions = ">=3.8" -files = [ - {file = "bracex-2.4-py3-none-any.whl", hash = "sha256:efdc71eff95eaff5e0f8cfebe7d01adf2c8637c8c92edaf63ef348c241a82418"}, - {file = "bracex-2.4.tar.gz", hash = "sha256:a27eaf1df42cf561fed58b7a8f3fdf129d1ea16a81e1fadd1d17989bc6384beb"}, -] - -[[package]] -name = "cairocffi" -version = "1.6.1" -description = "cffi-based cairo bindings for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "cairocffi-1.6.1-py3-none-any.whl", hash = "sha256:aa78ee52b9069d7475eeac457389b6275aa92111895d78fbaa2202a52dac112e"}, - {file = "cairocffi-1.6.1.tar.gz", hash = "sha256:78e6bbe47357640c453d0be929fa49cd05cce2e1286f3d2a1ca9cbda7efdb8b7"}, -] - -[package.dependencies] -cffi = ">=1.1.0" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "numpy", "pikepdf", "pytest"] -xcb = ["xcffib (>=1.4.0)"] - -[[package]] -name = "cairosvg" -version = "2.7.1" -description = "A Simple SVG Converter based on Cairo" -optional = false -python-versions = ">=3.5" -files = [ - {file = "CairoSVG-2.7.1-py3-none-any.whl", hash = "sha256:8a5222d4e6c3f86f1f7046b63246877a63b49923a1cd202184c3a634ef546b3b"}, - {file = "CairoSVG-2.7.1.tar.gz", hash = "sha256:432531d72347291b9a9ebfb6777026b607563fd8719c46ee742db0aef7271ba0"}, -] - -[package.dependencies] -cairocffi = "*" -cssselect2 = "*" -defusedxml = "*" -pillow = "*" -tinycss2 = "*" - -[package.extras] -doc = ["sphinx", "sphinx-rtd-theme"] -test = ["flake8", "isort", "pytest"] - -[[package]] -name = "certifi" -version = "2023.11.17" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "cssselect2" -version = "0.7.0" -description = "CSS selectors for Python ElementTree" -optional = false -python-versions = ">=3.7" -files = [ - {file = "cssselect2-0.7.0-py3-none-any.whl", hash = "sha256:fd23a65bfd444595913f02fc71f6b286c29261e354c41d722ca7a261a49b5969"}, - {file = "cssselect2-0.7.0.tar.gz", hash = "sha256:1ccd984dab89fc68955043aca4e1b03e0cf29cad9880f6e28e3ba7a74b14aa5a"}, -] - -[package.dependencies] -tinycss2 = "*" -webencodings = "*" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "pytest"] - -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - -[[package]] -name = "filelock" -version = "3.13.1" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.8" -files = [ - {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, - {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] -typing = ["typing-extensions (>=4.8)"] - -[[package]] -name = "ghp-import" -version = "2.1.0" -description = "Copy your docs directly to the gh-pages branch." -optional = false -python-versions = "*" -files = [ - {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, - {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, -] - -[package.dependencies] -python-dateutil = ">=2.8.1" - -[package.extras] -dev = ["flake8", "markdown", "twine", "wheel"] - -[[package]] -name = "gitdb" -version = "4.0.11" -description = "Git Object Database" -optional = false -python-versions = ">=3.7" -files = [ - {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, - {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, -] - -[package.dependencies] -smmap = ">=3.0.1,<6" - -[[package]] -name = "gitpython" -version = "3.1.41" -description = "GitPython is a Python library used to interact with Git repositories" -optional = false -python-versions = ">=3.7" -files = [ - {file = "GitPython-3.1.41-py3-none-any.whl", hash = "sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c"}, - {file = "GitPython-3.1.41.tar.gz", hash = "sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048"}, -] - -[package.dependencies] -gitdb = ">=4.0.1,<5" - -[package.extras] -test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "sumtypes"] - -[[package]] -name = "idna" -version = "3.6" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, -] - -[[package]] -name = "importlib-metadata" -version = "7.0.1" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, - {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] - -[[package]] -name = "jinja2" -version = "3.1.3" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "markdown" -version = "3.5.2" -description = "Python implementation of John Gruber's Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "Markdown-3.5.2-py3-none-any.whl", hash = "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd"}, - {file = "Markdown-3.5.2.tar.gz", hash = "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] -testing = ["coverage", "pyyaml"] - -[[package]] -name = "markupsafe" -version = "2.1.4" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de8153a7aae3835484ac168a9a9bdaa0c5eee4e0bc595503c95d53b942879c84"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e888ff76ceb39601c59e219f281466c6d7e66bd375b4ec1ce83bcdc68306796b"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b838c37ba596fcbfca71651a104a611543077156cb0a26fe0c475e1f152ee8"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac1ebf6983148b45b5fa48593950f90ed6d1d26300604f321c74a9ca1609f8e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fbad3d346df8f9d72622ac71b69565e621ada2ce6572f37c2eae8dacd60385d"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d5291d98cd3ad9a562883468c690a2a238c4a6388ab3bd155b0c75dd55ece858"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a7cc49ef48a3c7a0005a949f3c04f8baa5409d3f663a1b36f0eba9bfe2a0396e"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b83041cda633871572f0d3c41dddd5582ad7d22f65a72eacd8d3d6d00291df26"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win32.whl", hash = "sha256:0c26f67b3fe27302d3a412b85ef696792c4a2386293c53ba683a89562f9399b0"}, - {file = "MarkupSafe-2.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:a76055d5cb1c23485d7ddae533229039b850db711c554a12ea64a0fd8a0129e2"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9e9e3c4020aa2dc62d5dd6743a69e399ce3de58320522948af6140ac959ab863"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0042d6a9880b38e1dd9ff83146cc3c9c18a059b9360ceae207805567aacccc69"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d03fea4c4e9fd0ad75dc2e7e2b6757b80c152c032ea1d1de487461d8140efc"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab3a886a237f6e9c9f4f7d272067e712cdb4efa774bef494dccad08f39d8ae6"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abf5ebbec056817057bfafc0445916bb688a255a5146f900445d081db08cbabb"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e1a0d1924a5013d4f294087e00024ad25668234569289650929ab871231668e7"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e7902211afd0af05fbadcc9a312e4cf10f27b779cf1323e78d52377ae4b72bea"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c669391319973e49a7c6230c218a1e3044710bc1ce4c8e6eb71f7e6d43a2c131"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win32.whl", hash = "sha256:31f57d64c336b8ccb1966d156932f3daa4fee74176b0fdc48ef580be774aae74"}, - {file = "MarkupSafe-2.1.4-cp311-cp311-win_amd64.whl", hash = "sha256:54a7e1380dfece8847c71bf7e33da5d084e9b889c75eca19100ef98027bd9f56"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a76cd37d229fc385738bd1ce4cba2a121cf26b53864c1772694ad0ad348e509e"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:987d13fe1d23e12a66ca2073b8d2e2a75cec2ecb8eab43ff5624ba0ad42764bc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5244324676254697fe5c181fc762284e2c5fceeb1c4e3e7f6aca2b6f107e60dc"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78bc995e004681246e85e28e068111a4c3f35f34e6c62da1471e844ee1446250"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4d176cfdfde84f732c4a53109b293d05883e952bbba68b857ae446fa3119b4f"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f9917691f410a2e0897d1ef99619fd3f7dd503647c8ff2475bf90c3cf222ad74"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f06e5a9e99b7df44640767842f414ed5d7bedaaa78cd817ce04bbd6fd86e2dd6"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396549cea79e8ca4ba65525470d534e8a41070e6b3500ce2414921099cb73e8d"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win32.whl", hash = "sha256:f6be2d708a9d0e9b0054856f07ac7070fbe1754be40ca8525d5adccdbda8f475"}, - {file = "MarkupSafe-2.1.4-cp312-cp312-win_amd64.whl", hash = "sha256:5045e892cfdaecc5b4c01822f353cf2c8feb88a6ec1c0adef2a2e705eef0f656"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7a07f40ef8f0fbc5ef1000d0c78771f4d5ca03b4953fc162749772916b298fc4"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d18b66fe626ac412d96c2ab536306c736c66cf2a31c243a45025156cc190dc8a"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:698e84142f3f884114ea8cf83e7a67ca8f4ace8454e78fe960646c6c91c63bfa"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49a3b78a5af63ec10d8604180380c13dcd870aba7928c1fe04e881d5c792dc4e"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:15866d7f2dc60cfdde12ebb4e75e41be862348b4728300c36cdf405e258415ec"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:6aa5e2e7fc9bc042ae82d8b79d795b9a62bd8f15ba1e7594e3db243f158b5565"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:54635102ba3cf5da26eb6f96c4b8c53af8a9c0d97b64bdcb592596a6255d8518"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win32.whl", hash = "sha256:3583a3a3ab7958e354dc1d25be74aee6228938312ee875a22330c4dc2e41beb0"}, - {file = "MarkupSafe-2.1.4-cp37-cp37m-win_amd64.whl", hash = "sha256:d6e427c7378c7f1b2bef6a344c925b8b63623d3321c09a237b7cc0e77dd98ceb"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bf1196dcc239e608605b716e7b166eb5faf4bc192f8a44b81e85251e62584bd2"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df98d4a9cd6a88d6a585852f56f2155c9cdb6aec78361a19f938810aa020954"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b835aba863195269ea358cecc21b400276747cc977492319fd7682b8cd2c253d"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23984d1bdae01bee794267424af55eef4dfc038dc5d1272860669b2aa025c9e3"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c98c33ffe20e9a489145d97070a435ea0679fddaabcafe19982fe9c971987d5"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9896fca4a8eb246defc8b2a7ac77ef7553b638e04fbf170bff78a40fa8a91474"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b0fe73bac2fed83839dbdbe6da84ae2a31c11cfc1c777a40dbd8ac8a6ed1560f"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c7556bafeaa0a50e2fe7dc86e0382dea349ebcad8f010d5a7dc6ba568eaaa789"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win32.whl", hash = "sha256:fc1a75aa8f11b87910ffd98de62b29d6520b6d6e8a3de69a70ca34dea85d2a8a"}, - {file = "MarkupSafe-2.1.4-cp38-cp38-win_amd64.whl", hash = "sha256:3a66c36a3864df95e4f62f9167c734b3b1192cb0851b43d7cc08040c074c6279"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:765f036a3d00395a326df2835d8f86b637dbaf9832f90f5d196c3b8a7a5080cb"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21e7af8091007bf4bebf4521184f4880a6acab8df0df52ef9e513d8e5db23411"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c31fe855c77cad679b302aabc42d724ed87c043b1432d457f4976add1c2c3e"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7653fa39578957bc42e5ebc15cf4361d9e0ee4b702d7d5ec96cdac860953c5b4"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:47bb5f0142b8b64ed1399b6b60f700a580335c8e1c57f2f15587bd072012decc"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:fe8512ed897d5daf089e5bd010c3dc03bb1bdae00b35588c49b98268d4a01e00"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:36d7626a8cca4d34216875aee5a1d3d654bb3dac201c1c003d182283e3205949"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b6f14a9cd50c3cb100eb94b3273131c80d102e19bb20253ac7bd7336118a673a"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win32.whl", hash = "sha256:c8f253a84dbd2c63c19590fa86a032ef3d8cc18923b8049d91bcdeeb2581fbf6"}, - {file = "MarkupSafe-2.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:8b570a1537367b52396e53325769608f2a687ec9a4363647af1cded8928af959"}, - {file = "MarkupSafe-2.1.4.tar.gz", hash = "sha256:3aae9af4cac263007fd6309c64c6ab4506dd2b79382d9d19a1994f9240b8db4f"}, -] - -[[package]] -name = "mergedeep" -version = "1.3.4" -description = "A deep merge function for 🐍." -optional = false -python-versions = ">=3.6" -files = [ - {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, - {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, -] - -[[package]] -name = "mkdocs" -version = "1.5.3" -description = "Project documentation with Markdown." -optional = false -python-versions = ">=3.7" -files = [ - {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, - {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, -] - -[package.dependencies] -click = ">=7.0" -colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} -ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} -jinja2 = ">=2.11.1" -markdown = ">=3.2.1" -markupsafe = ">=2.0.1" -mergedeep = ">=1.3.4" -packaging = ">=20.5" -pathspec = ">=0.11.1" -platformdirs = ">=2.2.0" -pyyaml = ">=5.1" -pyyaml-env-tag = ">=0.1" -watchdog = ">=2.0" - -[package.extras] -i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] - -[[package]] -name = "mkdocs-include-markdown-plugin" -version = "6.0.4" -description = "Mkdocs Markdown includer plugin." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_include_markdown_plugin-6.0.4-py3-none-any.whl", hash = "sha256:e7b8b5ecc41d6a3e16969cff3725ec3a391b68e9dfe1a4b4e36a8508becda835"}, - {file = "mkdocs_include_markdown_plugin-6.0.4.tar.gz", hash = "sha256:523c9c3a1d6a517386dc11bf60b0c0c564af1071bb6de8d213106d54f752dcc1"}, -] - -[package.dependencies] -mkdocs = ">=1.4" -wcmatch = ">=8,<9" - -[package.extras] -cache = ["platformdirs"] - -[[package]] -name = "mkdocs-markdownextradata-plugin" -version = "0.2.5" -description = "A MkDocs plugin that injects the mkdocs.yml extra variables into the markdown template" -optional = false -python-versions = ">=2.7.9,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -files = [ - {file = "mkdocs-markdownextradata-plugin-0.2.5.tar.gz", hash = "sha256:9c562e8fe375647d5692d11dfe369a7bdd50302174d35995fce2aeca58036ec6"}, -] - -[package.dependencies] -mkdocs = "*" -pyyaml = "*" - -[[package]] -name = "mkdocs-material" -version = "9.5.4" -description = "Documentation that simply works" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material-9.5.4-py3-none-any.whl", hash = "sha256:efd7cc8ae03296d728da9bd38f4db8b07ab61f9738a0cbd0dfaf2a15a50e7343"}, - {file = "mkdocs_material-9.5.4.tar.gz", hash = "sha256:3d196ee67fad16b2df1a458d650a8ac1890294eaae368d26cee71bc24ad41c40"}, -] - -[package.dependencies] -babel = ">=2.10,<3.0" -colorama = ">=0.4,<1.0" -jinja2 = ">=3.0,<4.0" -markdown = ">=3.2,<4.0" -mkdocs = ">=1.5.3,<1.6.0" -mkdocs-material-extensions = ">=1.3,<2.0" -paginate = ">=0.5,<1.0" -pygments = ">=2.16,<3.0" -pymdown-extensions = ">=10.2,<11.0" -regex = ">=2022.4" -requests = ">=2.26,<3.0" - -[package.extras] -git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2,<2.0)"] -imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=9.4,<10.0)"] -recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"] - -[[package]] -name = "mkdocs-material-extensions" -version = "1.3.1" -description = "Extension pack for Python Markdown and MkDocs Material." -optional = false -python-versions = ">=3.8" -files = [ - {file = "mkdocs_material_extensions-1.3.1-py3-none-any.whl", hash = "sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31"}, - {file = "mkdocs_material_extensions-1.3.1.tar.gz", hash = "sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443"}, -] - -[[package]] -name = "mkdocs-rss-plugin" -version = "1.5.0" -description = "MkDocs plugin which generates a static RSS feed using git log and page.meta." -optional = false -python-versions = ">=3.7, <4" -files = [] -develop = false - -[package.dependencies] -GitPython = ">=3.1,<3.2" -mkdocs = ">=1.1,<2" -tzdata = {version = "==2022.*", markers = "python_version >= \"3.9\" and sys_platform == \"win32\""} - -[package.extras] -dev = ["black", "feedparser (>=6.0,<6.1)", "flake8 (>=4,<5.1)", "pre-commit (>=2.10,<2.21)", "pytest-cov (==4.0.*)", "validator-collection (>=1.5,<1.6)"] -doc = ["mkdocs-bootswatch (>=1,<2)", "mkdocs-minify-plugin (==0.5.*)", "pygments (>=2.5,<3)", "pymdown-extensions (>=7,<10)"] - -[package.source] -type = "git" -url = "https://github.com/cachix/mkdocs-rss-plugin" -reference = "no-git" -resolved_reference = "017bdb52095703c79e0632f219b5adf9f212873c" - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "paginate" -version = "0.5.6" -description = "Divides large result sets into pages for easier browsing" -optional = false -python-versions = "*" -files = [ - {file = "paginate-0.5.6.tar.gz", hash = "sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "pillow" -version = "9.5.0" -description = "Python Imaging Library (Fork)" -optional = false -python-versions = ">=3.7" -files = [ - {file = "Pillow-9.5.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:ace6ca218308447b9077c14ea4ef381ba0b67ee78d64046b3f19cf4e1139ad16"}, - {file = "Pillow-9.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3d403753c9d5adc04d4694d35cf0391f0f3d57c8e0030aac09d7678fa8030aa"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ba1b81ee69573fe7124881762bb4cd2e4b6ed9dd28c9c60a632902fe8db8b38"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f36397bf3f7d7c6a3abdea815ecf6fd14e7fcd4418ab24bae01008d8d8ca15e"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:252a03f1bdddce077eff2354c3861bf437c892fb1832f75ce813ee94347aa9b5"}, - {file = "Pillow-9.5.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:85ec677246533e27770b0de5cf0f9d6e4ec0c212a1f89dfc941b64b21226009d"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b416f03d37d27290cb93597335a2f85ed446731200705b22bb927405320de903"}, - {file = "Pillow-9.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1781a624c229cb35a2ac31cc4a77e28cafc8900733a864870c49bfeedacd106a"}, - {file = "Pillow-9.5.0-cp310-cp310-win32.whl", hash = "sha256:8507eda3cd0608a1f94f58c64817e83ec12fa93a9436938b191b80d9e4c0fc44"}, - {file = "Pillow-9.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:d3c6b54e304c60c4181da1c9dadf83e4a54fd266a99c70ba646a9baa626819eb"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:7ec6f6ce99dab90b52da21cf0dc519e21095e332ff3b399a357c187b1a5eee32"}, - {file = "Pillow-9.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:560737e70cb9c6255d6dcba3de6578a9e2ec4b573659943a5e7e4af13f298f5c"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:96e88745a55b88a7c64fa49bceff363a1a27d9a64e04019c2281049444a571e3"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9c206c29b46cfd343ea7cdfe1232443072bbb270d6a46f59c259460db76779a"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cfcc2c53c06f2ccb8976fb5c71d448bdd0a07d26d8e07e321c103416444c7ad1"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:a0f9bb6c80e6efcde93ffc51256d5cfb2155ff8f78292f074f60f9e70b942d99"}, - {file = "Pillow-9.5.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:8d935f924bbab8f0a9a28404422da8af4904e36d5c33fc6f677e4c4485515625"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579"}, - {file = "Pillow-9.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c1170d6b195555644f0616fd6ed929dfcf6333b8675fcca044ae5ab110ded296"}, - {file = "Pillow-9.5.0-cp311-cp311-win32.whl", hash = "sha256:54f7102ad31a3de5666827526e248c3530b3a33539dbda27c6843d19d72644ec"}, - {file = "Pillow-9.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:cfa4561277f677ecf651e2b22dc43e8f5368b74a25a8f7d1d4a3a243e573f2d4"}, - {file = "Pillow-9.5.0-cp311-cp311-win_arm64.whl", hash = "sha256:965e4a05ef364e7b973dd17fc765f42233415974d773e82144c9bbaaaea5d089"}, - {file = "Pillow-9.5.0-cp312-cp312-win32.whl", hash = "sha256:22baf0c3cf0c7f26e82d6e1adf118027afb325e703922c8dfc1d5d0156bb2eeb"}, - {file = "Pillow-9.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:432b975c009cf649420615388561c0ce7cc31ce9b2e374db659ee4f7d57a1f8b"}, - {file = "Pillow-9.5.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:5d4ebf8e1db4441a55c509c4baa7a0587a0210f7cd25fcfe74dbbce7a4bd1906"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:375f6e5ee9620a271acb6820b3d1e94ffa8e741c0601db4c0c4d3cb0a9c224bf"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99eb6cafb6ba90e436684e08dad8be1637efb71c4f2180ee6b8f940739406e78"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfaaf10b6172697b9bceb9a3bd7b951819d1ca339a5ef294d1f1ac6d7f63270"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:763782b2e03e45e2c77d7779875f4432e25121ef002a41829d8868700d119392"}, - {file = "Pillow-9.5.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:35f6e77122a0c0762268216315bf239cf52b88865bba522999dc38f1c52b9b47"}, - {file = "Pillow-9.5.0-cp37-cp37m-win32.whl", hash = "sha256:aca1c196f407ec7cf04dcbb15d19a43c507a81f7ffc45b690899d6a76ac9fda7"}, - {file = "Pillow-9.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322724c0032af6692456cd6ed554bb85f8149214d97398bb80613b04e33769f6"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:a0aa9417994d91301056f3d0038af1199eb7adc86e646a36b9e050b06f526597"}, - {file = "Pillow-9.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8286396b351785801a976b1e85ea88e937712ee2c3ac653710a4a57a8da5d9c"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c830a02caeb789633863b466b9de10c015bded434deb3ec87c768e53752ad22a"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbd359831c1657d69bb81f0db962905ee05e5e9451913b18b831febfe0519082"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8fc330c3370a81bbf3f88557097d1ea26cd8b019d6433aa59f71195f5ddebbf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:7002d0797a3e4193c7cdee3198d7c14f92c0836d6b4a3f3046a64bd1ce8df2bf"}, - {file = "Pillow-9.5.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:229e2c79c00e85989a34b5981a2b67aa079fd08c903f0aaead522a1d68d79e51"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9adf58f5d64e474bed00d69bcd86ec4bcaa4123bfa70a65ce72e424bfb88ed96"}, - {file = "Pillow-9.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:662da1f3f89a302cc22faa9f14a262c2e3951f9dbc9617609a47521c69dd9f8f"}, - {file = "Pillow-9.5.0-cp38-cp38-win32.whl", hash = "sha256:6608ff3bf781eee0cd14d0901a2b9cc3d3834516532e3bd673a0a204dc8615fc"}, - {file = "Pillow-9.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:e49eb4e95ff6fd7c0c402508894b1ef0e01b99a44320ba7d8ecbabefddcc5569"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:482877592e927fd263028c105b36272398e3e1be3269efda09f6ba21fd83ec66"}, - {file = "Pillow-9.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3ded42b9ad70e5f1754fb7c2e2d6465a9c842e41d178f262e08b8c85ed8a1d8e"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c446d2245ba29820d405315083d55299a796695d747efceb5717a8b450324115"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aca1152d93dcc27dc55395604dcfc55bed5f25ef4c98716a928bacba90d33a3"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:608488bdcbdb4ba7837461442b90ea6f3079397ddc968c31265c1e056964f1ef"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:60037a8db8750e474af7ffc9faa9b5859e6c6d0a50e55c45576bf28be7419705"}, - {file = "Pillow-9.5.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:07999f5834bdc404c442146942a2ecadd1cb6292f5229f4ed3b31e0a108746b1"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a127ae76092974abfbfa38ca2d12cbeddcdeac0fb71f9627cc1135bedaf9d51a"}, - {file = "Pillow-9.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:489f8389261e5ed43ac8ff7b453162af39c3e8abd730af8363587ba64bb2e865"}, - {file = "Pillow-9.5.0-cp39-cp39-win32.whl", hash = "sha256:9b1af95c3a967bf1da94f253e56b6286b50af23392a886720f563c547e48e964"}, - {file = "Pillow-9.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:77165c4a5e7d5a284f10a6efaa39a0ae8ba839da344f20b111d62cc932fa4e5d"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:833b86a98e0ede388fa29363159c9b1a294b0905b5128baf01db683672f230f5"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aaf305d6d40bd9632198c766fb64f0c1a83ca5b667f16c1e79e1661ab5060140"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0852ddb76d85f127c135b6dd1f0bb88dbb9ee990d2cd9aa9e28526c93e794fba"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:91ec6fe47b5eb5a9968c79ad9ed78c342b1f97a091677ba0e012701add857829"}, - {file = "Pillow-9.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cb841572862f629b99725ebaec3287fc6d275be9b14443ea746c1dd325053cbd"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c380b27d041209b849ed246b111b7c166ba36d7933ec6e41175fd15ab9eb1572"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c9af5a3b406a50e313467e3565fc99929717f780164fe6fbb7704edba0cebbe"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5671583eab84af046a397d6d0ba25343c00cd50bce03787948e0fff01d4fd9b1"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:84a6f19ce086c1bf894644b43cd129702f781ba5751ca8572f08aa40ef0ab7b7"}, - {file = "Pillow-9.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1e7723bd90ef94eda669a3c2c19d549874dd5badaeefabefd26053304abe5799"}, - {file = "Pillow-9.5.0.tar.gz", hash = "sha256:bf548479d336726d7a0eceb6e767e179fbde37833ae42794602631a070d630f1"}, -] - -[package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "platformdirs" -version = "4.1.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -optional = false -python-versions = ">=3.8" -files = [ - {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, - {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, -] - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] - -[[package]] -name = "pygments" -version = "2.17.2" -description = "Pygments is a syntax highlighting package written in Python." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, - {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, -] - -[package.extras] -plugins = ["importlib-metadata"] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pymdown-extensions" -version = "10.7" -description = "Extension pack for Python Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pymdown_extensions-10.7-py3-none-any.whl", hash = "sha256:6ca215bc57bc12bf32b414887a68b810637d039124ed9b2e5bd3325cbb2c050c"}, - {file = "pymdown_extensions-10.7.tar.gz", hash = "sha256:c0d64d5cf62566f59e6b2b690a4095c931107c250a8c8e1351c1de5f6b036deb"}, -] - -[package.dependencies] -markdown = ">=3.5" -pyyaml = "*" - -[package.extras] -extra = ["pygments (>=2.12)"] - -[[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, -] - -[[package]] -name = "pyyaml-env-tag" -version = "0.1" -description = "A custom YAML tag for referencing environment variables in YAML files. " -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, - {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, -] - -[package.dependencies] -pyyaml = "*" - -[[package]] -name = "regex" -version = "2023.12.25" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.7" -files = [ - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, - {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, - {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, - {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, - {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, - {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, - {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, - {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, - {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, - {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, - {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, - {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, - {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, - {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, - {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, -] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "smmap" -version = "5.0.1" -description = "A pure Python implementation of a sliding window memory map manager" -optional = false -python-versions = ">=3.7" -files = [ - {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, - {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, -] - -[[package]] -name = "strictyaml" -version = "1.7.3" -description = "Strict, typed YAML parser" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "strictyaml-1.7.3-py3-none-any.whl", hash = "sha256:fb5c8a4edb43bebb765959e420f9b3978d7f1af88c80606c03fb420888f5d1c7"}, - {file = "strictyaml-1.7.3.tar.gz", hash = "sha256:22f854a5fcab42b5ddba8030a0e4be51ca89af0267961c8d6cfa86395586c407"}, -] - -[package.dependencies] -python-dateutil = ">=2.6.0" - -[[package]] -name = "terminaltables" -version = "3.1.10" -description = "Generate simple tables in terminals from a nested list of strings." -optional = false -python-versions = ">=2.6" -files = [ - {file = "terminaltables-3.1.10-py2.py3-none-any.whl", hash = "sha256:e4fdc4179c9e4aab5f674d80f09d76fa436b96fdc698a8505e0a36bf0804a874"}, - {file = "terminaltables-3.1.10.tar.gz", hash = "sha256:ba6eca5cb5ba02bba4c9f4f985af80c54ec3dccf94cfcd190154386255e47543"}, -] - -[[package]] -name = "tinycss2" -version = "1.2.1" -description = "A tiny CSS parser" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, - {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, -] - -[package.dependencies] -webencodings = ">=0.4" - -[package.extras] -doc = ["sphinx", "sphinx_rtd_theme"] -test = ["flake8", "isort", "pytest"] - -[[package]] -name = "tzdata" -version = "2022.7" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -files = [ - {file = "tzdata-2022.7-py2.py3-none-any.whl", hash = "sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d"}, - {file = "tzdata-2022.7.tar.gz", hash = "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"}, -] - -[[package]] -name = "urllib3" -version = "2.1.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, - {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "watchdog" -version = "3.0.0" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.7" -files = [ - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, - {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, - {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, - {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, - {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, - {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, - {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, - {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, - {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, - {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, - {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, - {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, - {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, - {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "wcmatch" -version = "8.5" -description = "Wildcard/glob file name matcher." -optional = false -python-versions = ">=3.8" -files = [ - {file = "wcmatch-8.5-py3-none-any.whl", hash = "sha256:14554e409b142edeefab901dc68ad570b30a72a8ab9a79106c5d5e9a6d241bd5"}, - {file = "wcmatch-8.5.tar.gz", hash = "sha256:86c17572d0f75cbf3bcb1a18f3bf2f9e72b39a9c08c9b4a74e991e1882a8efb3"}, -] - -[package.dependencies] -bracex = ">=2.1.1" - -[[package]] -name = "webencodings" -version = "0.5.1" -description = "Character encoding aliases for legacy web content" -optional = false -python-versions = "*" -files = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] - -[[package]] -name = "zipp" -version = "3.17.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.8" -files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[metadata] -lock-version = "2.0" -python-versions = ">=3.9,<3.12" -content-hash = "8b3c5630efc528583af82f6d7aa9d3d28e5f892e7af717e2ceb72676f91f757d" diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 3f9931caf..000000000 --- a/pyproject.toml +++ /dev/null @@ -1,38 +0,0 @@ -[tool.poetry] -name = "devenv" -version = "1.0" -description = "Fast, Declarative, Reproducible, and Composable Developer Environments using Nix" -authors = ["Domen Kožar "] -readme = "README.md" -repository = "https://github.com/cachix/devenv" -packages = [{include = "devenv", from = "src"}] -include = [ - { path = "src", format = ["sdist", "wheel"] }, - { path = "examples/simple", format = ["sdist", "wheel"] } -] - -[tool.poetry.dependencies] -python = ">=3.9,<3.12" -click = "^8.1.4" -strictyaml = "^1.7.3" -terminaltables = "^3.1.10" -filelock = "^3.12.0" -requests = "^2.31.0" - -[tool.poetry.group.docs] -optional = true - -[tool.poetry.group.docs.dependencies] -pillow = "^9.5.0" -cairosvg = "^2.7.0" -mkdocs-markdownextradata-plugin = "^0.2.5" -mkdocs-include-markdown-plugin = "^6.0.1" -mkdocs-material = "^9.4.0" -mkdocs-rss-plugin = {git = "https://github.com/cachix/mkdocs-rss-plugin", rev = "no-git"} - -[tool.poetry.scripts] -devenv = "devenv.cli:cli" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..e36f98f22 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +mkdocs +mkdocs-material[imaging] +mkdocs-rss-plugin +mkdocs-include-markdown-plugin +mkdocs-markdownextradata-plugin diff --git a/src/devenv/__init__.py b/src/devenv/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/devenv/cli.py b/src/devenv/cli.py deleted file mode 100644 index a2a245dc9..000000000 --- a/src/devenv/cli.py +++ /dev/null @@ -1,904 +0,0 @@ -import functools -import os -import shlex -import shutil -import signal -import subprocess -import tempfile -import time -import re -import sys -import pkgutil -import json -from filelock import FileLock -from contextlib import suppress -from pathlib import Path - -import click -import terminaltables -import strictyaml -import requests - -from .yaml import validate_and_parse_yaml, read_yaml, write_yaml, schema -from .log import log, log_task, log_error, log_warning, log_info - - -NIX_FLAGS = [ - "--show-trace", - "--extra-experimental-features", - "nix-command", - "--extra-experimental-features", - "flakes", - # remove unnecessary warnings - "--option", - "warn-dirty", - "false", - # flake caching is too aggressive - "--option", - "eval-cache", - "false", -] -FILE = pkgutil.get_loader(__package__).load_module(__package__).__file__ -if "site-packages" in FILE: - SRC_DIR = Path(FILE, "..", "..", "src") -else: - SRC_DIR = Path(FILE, "..", "..") -DEVENV_DIR = Path(os.getcwd()) / ".devenv" -DEVENV_DIR.mkdir(parents=True, exist_ok=True) -MODULES_DIR = (SRC_DIR / "modules").resolve() -FLAKE_FILE_TEMPL = Path(MODULES_DIR) / "flake.tmpl.nix" -FLAKE_FILE = Path(os.getcwd()) / ".devenv.flake.nix" -FLAKE_LOCK = "devenv.lock" - -# home vars -if "XDG_DATA_HOME" not in os.environ: - DEVENV_HOME = Path(os.environ["HOME"]) / ".devenv" -else: - DEVENV_HOME = Path(os.environ["XDG_DATA_HOME"]) / ".devenv" -DEVENV_HOME_GC = DEVENV_HOME / "gc" -DEVENV_HOME_GC.mkdir(parents=True, exist_ok=True) -CACHIX_KNOWN_PUBKEYS = DEVENV_HOME / "cachix_pubkeys.json" - -# define system like x86_64-linux -SYSTEM = ( - os.uname().machine.lower().replace("arm", "aarch") - + "-" - + os.uname().sysname.lower() -) - - -def run_nix(command: str, **kwargs) -> str: - ctx = click.get_current_context() - nix_flags = ctx.obj["nix_flags"] - flags = " ".join(NIX_FLAGS) + " " + " ".join(nix_flags) - command_flags = " ".join(ctx.obj["command_flags"]) - return run_command(f"nix {flags} {command} {command_flags}", **kwargs) - - -def run_command( - command: str, - disable_stderr=False, - replace_shell=False, - use_cachix=False, - logging=True, - dont_exit=False, -) -> str: - nix = "" - if command.startswith("nix"): - if os.environ.get("DEVENV_NIX"): - nix = os.path.join(os.environ["DEVENV_NIX"], "bin") - command = f"{nix}/{command}" - else: - log( - "$DEVENV_NIX is not set, but required as devenv doesn't work without a few Nix patches.", - level="error", - ) - log( - "Please follow https://devenv.sh/getting-started/ to install devenv.", - level="error", - ) - exit(1) - if use_cachix: - caches, known_keys = get_cachix_caches(logging) - pull_caches = " ".join( - map(lambda cache: f"https://{cache}.cachix.org", caches.get("pull")) - ) - command = f"{command} --option extra-trusted-public-keys '{' '.join(known_keys.values())}'" - command = f"{command} --option extra-substituters '{pull_caches}'" - push_cache = caches.get("push") - if push_cache and os.environ.get("CACHIX_AUTH_TOKEN"): - if shutil.which("cachix") is None: - if logging: - log_warning( - "cachix is not installed, skipping pushing. Please follow https://devenv.sh/getting-started/#2-install-cachix to install cachix.", - level="error", - ) - else: - command = f"cachix watch-exec {push_cache} {command}" - - try: - if click.get_current_context().obj["verbose"]: - log(f"Running command: {command}", level="debug") - if replace_shell: - splitted_command = shlex.split(command.strip()) - os.execv(splitted_command[0], splitted_command) - else: - return subprocess.run( - command, - shell=True, - check=True, - env=os.environ.copy(), - stdout=subprocess.PIPE, - stdin=subprocess.PIPE, - stderr=None if not disable_stderr else subprocess.DEVNULL, - universal_newlines=True, - ).stdout.strip() - except subprocess.CalledProcessError as e: - if logging: - click.echo("\n", err=True) - log( - f"Following command exited with code {e.returncode}:\n\n {e.cmd}", - level="error", - ) - if dont_exit: - raise e - else: - exit(e.returncode) - - -CONTEXT_SETTINGS = dict(max_content_width=120) - - -@click.group(context_settings=CONTEXT_SETTINGS) -@click.option("--verbose", "-v", help="Enable verbose output.", is_flag=True) -@click.option( - "--nix-flags", - "-n", - help='Flags to pass to Nix. See `man nix.conf 5`. Example: --nix-flags "--option bash-prompt >"', - metavar="NIX-FLAGS", - multiple=True, -) -@click.option("--debugger", "-d", help="Enable Nix debugger.", is_flag=True) -@click.option("--system", "-s", help="Nix system to use.", default=SYSTEM) -@click.option("--offline", "-o", help="Disable network access.", is_flag=True) -@click.pass_context -def cli(ctx, offline, system, debugger, nix_flags, verbose): - """https://devenv.sh: Fast, Declarative, Reproducible, and Composable Developer Environments.""" - ctx.ensure_object(dict) - ctx.obj["system"] = system - ctx.obj["verbose"] = verbose - ctx.obj["command_flags"] = [] - ctx.obj["nix_flags"] = list(nix_flags) - ctx.obj["nix_flags"] += ["--system", system] - if offline: - ctx.obj["nix_flags"] += ["--offline"] - if debugger: - # ignore-try is needed to avoid catching unrelated errors - ctx.obj["command_flags"] += ["--debugger", "--ignore-try"] - - ctx.obj["gc_root"] = DEVENV_HOME_GC - ctx.obj["gc_project"] = DEVENV_HOME_GC / str(int(time.time() * 1000)) - - -@cli.group() -def processes(): - pass - - -os.environ["DEVENV_DIR"] = str(DEVENV_DIR) -DEVENV_GC = DEVENV_DIR / "gc" -os.environ["DEVENV_GC"] = str(DEVENV_GC) - -PROCESSES_PID = DEVENV_DIR / "processes.pid" -PROCESSES_LOG = DEVENV_DIR / "processes.log" - - -def add_gc(name, store_path): - """Register a GC root""" - ctx = click.get_current_context() - run_command( - f'nix-store --add-root "{os.environ["DEVENV_GC"]}/{name}" -r {store_path} >/dev/null' - ) - symlink_force(store_path, f'{ctx.obj["gc_project"]}-{name}') - - -@cli.command(hidden=True) -@click.pass_context -def assemble(ctx): - if not os.path.exists("devenv.nix"): - log("File devenv.nix does not exist. To get started, run:", level="error") - log(" $ devenv init", level="error") - exit(1) - - DEVENV_GC.mkdir(parents=True, exist_ok=True) - - if os.path.exists("devenv.yaml"): - validate_and_parse_yaml(DEVENV_DIR) - else: - for file in ["devenv.json", "flake.json", "imports.txt"]: - file_path = DEVENV_DIR / file - file_path.unlink(missing_ok=True) - - with open(FLAKE_FILE_TEMPL) as f: - flake = f.read() - system = ctx.obj["system"] - - with open(FLAKE_FILE, "w") as f: - devenv_vars = f""" - version = "{get_version()}"; - system = "{system}"; - devenv_root = "{os.getcwd()}"; - """ - # replace __DEVENV_VARS__ in flake using regex - flake = re.sub(r"__DEVENV_VARS__", devenv_vars, flake) - f.write(flake) - - -@cli.command( - help="Deletes previous devenv generations. See http://devenv.sh/garbage-collection", - short_help="Deletes previous devenv generations. See http://devenv.sh/garbage-collection", -) -@click.pass_context -def gc(ctx): - GC_ROOTS = ctx.obj["gc_root"] - start = time.time() - - # remove dangling symlinks - with log_task(f"Removing non-existings symlinks in {GC_ROOTS} ..."): - to_gc, removed_symlinks = cleanup_symlinks(GC_ROOTS) - - click.echo(f" Found {len(to_gc)} active symlinks.") - click.echo(f" Deleted {len(removed_symlinks)} dangling symlinks.") - click.echo() - - log( - "Running garbage collection (this process may take some time) ...", level="info" - ) - # TODO: ideally nix would report some statistics about the GC as JSON - run_nix(f'store delete --recursive {" ".join(to_gc)}') - - after_gc, removed_symlinks = cleanup_symlinks(GC_ROOTS) - end = time.time() - - click.echo() - log( - f"Done. Successfully removed {len(to_gc) - len(after_gc)} symlinks in {end - start:.0f} seconds.", - level="info", - ) - - -def cleanup_symlinks(folder): - to_gc = [] - removed_symlinks = [] - for root, dirs, files in os.walk(folder): - for name in files: - full_path = os.path.join(root, name) - if os.path.islink(full_path): - if not os.path.isfile(full_path): - os.unlink(full_path) - removed_symlinks.append(full_path) - else: - to_gc.append(full_path) - return to_gc, removed_symlinks - - -def get_dev_environment(ctx, json=False, logging=True): - ctx.invoke(assemble) - if logging: - action = log_task("Building shell") - else: - action = suppress() - with action: - gc_root = DEVENV_GC / "shell" - cmd = f"print-dev-env --profile '{gc_root}'" - if json: - cmd += " --json" - env = run_nix(cmd, logging=False, use_cachix=True) - run_command( - f"nix-env -p '{gc_root}' --delete-generations old", - logging=False, - disable_stderr=True, - ) - symlink_force(gc_root, Path(f'{ctx.obj["gc_project"]}-shell')) - return env, gc_root - - -@cli.command( - help="Activate the developer environment.", - short_help="Activate the developer environment.", - context_settings=dict( - ignore_unknown_options=True, - ), -) -@click.argument("cmd", required=False) -@click.argument("extra_args", nargs=-1, type=click.UNPROCESSED) -@click.pass_context -def shell(ctx, cmd, extra_args): - env, gc_root = get_dev_environment(ctx) - if cmd: - run_nix( - f"develop '{gc_root}' -c {cmd} {' '.join(extra_args)}", replace_shell=True - ) - else: - log("Entering shell", level="info") - run_nix(f"develop '{gc_root}'", replace_shell=True) - - -def symlink_force(src, dst): - src = Path(src) - dst = Path(dst) - # locking is needed until https://github.com/python/cpython/pull/14464 - with FileLock(f"{dst}.lock", timeout=10): - dst.unlink(missing_ok=True) - dst.symlink_to(src) - - -@cli.command( - help="Starts processes in foreground. See http://devenv.sh/processes", - short_help="Starts processes in foreground. See http://devenv.sh/processes", -) -@click.argument("process", required=False) -@click.option( - "--detach", "-d", is_flag=True, help="Starts processes in the background." -) -@click.pass_context -def up(ctx, process, detach): - with log_task("Building processes"): - ctx.invoke(assemble) - procfilescript = run_nix( - "build --no-link --print-out-paths '.#procfileScript'", use_cachix=True - ) - with open(procfilescript, "r") as file: - contents = file.read().strip() - if contents == "": - log( - "No 'processes' option defined: https://devenv.sh/processes/", level="error" - ) - exit(1) - else: - env, _ = get_dev_environment(ctx) - log("Starting processes ...", level="info") - add_gc("procfilescript", procfilescript) - processes_script = os.path.join(DEVENV_DIR, "processes") - with open(processes_script, "w") as f: - f.write( - f"""#!/usr/bin/env bash -{env} -exec {procfilescript} {process or ""} - """ - ) - os.chmod(processes_script, 0o755) - - if detach: - process = subprocess.Popen( - [processes_script], - stdout=open(PROCESSES_LOG, "w"), - stderr=subprocess.STDOUT, - ) - - with open(PROCESSES_PID, "w") as file: - file.write(str(process.pid)) - log(f" PID is {process.pid}.", level="info") - log(f" See logs: $ tail -f {PROCESSES_LOG}", level="info") - log(" Stop: $ devenv processes stop", level="info") - else: - os.execv(processes_script, [processes_script]) - - -processes.add_command(up) - - -@processes.command( - help="Stops processes started with 'devenv up'.", - short_help="Stops processes started with 'devenv up'.", -) -def stop(): - with log_task("Stopping processes", newline=False): - if not os.path.exists(PROCESSES_PID): - log("No processes running.", level="error") - exit(1) - - with open(PROCESSES_PID, "r") as file: - pid = int(file.read()) - - log(f"Stopping process with PID {pid} ...", level="info") - - try: - os.kill(pid, signal.SIGTERM) - except ProcessLookupError: - log(f"Process with PID {pid} not found.", level="error") - exit(1) - - os.remove(PROCESSES_PID) - - -@cli.command() -@click.argument("name") -@click.pass_context -def search(ctx, name): - """Search packages matching NAME in nixpkgs input.""" - ctx.invoke(assemble) - options = run_nix( - "build --no-link --print-out-paths '.#optionsJSON' ", use_cachix=True - ) - search = run_nix(f"search --json nixpkgs {name}") - - with open(Path(options) / "share" / "doc" / "nixos" / "options.json") as f: - options_results = [] - for key, value in json.load(f).items(): - if name in key: - options_results.append( - ( - key, - value["type"], - value.get("default", ""), - value["description"][:80], - ) - ) - results_options_count = len(options_results) - - search_results = [] - for key, value in json.loads(search).items(): - search_results.append( - ( - "pkgs." + (".".join(key.split(".")[2:])), - value["version"], - value["description"][:80], - ) - ) - search_results_count = len(search_results) - - if search_results: - click.echo( - terminaltables.AsciiTable( - [("Package", "Version", "Description")] + search_results - ).table - ) - - if options_results: - click.echo( - terminaltables.AsciiTable( - [("Option", "Type", "Default", "Description")] + options_results - ).table - ) - - log( - f"Found {search_results_count} packages and {results_options_count} options for '{name}'.", - level="info", - ) - - -@cli.command( - help="Build, copy and run a container. See http://devenv.sh/containers", - short_help="Build, copy and run a container. See http://devenv.sh/containers", -) -@click.option( - "--registry", - default=None, - help="Registry to copy the container to.", - metavar="REGISTRY", -) -@click.option("--copy", is_flag=True, help="Copy the container to the registry.") -@click.option( - "--copy-args", - default=None, - help="Arguments passed to `skopeo copy`.", - metavar="ARGS", -) -@click.option("--docker-run", is_flag=True, help="Execute `docker run`.") -@click.argument("container_name") -@click.pass_context -def container(ctx, registry, copy, copy_args, docker_run, container_name): - os.environ["DEVENV_CONTAINER"] = container_name - - with log_task(f"Building {container_name} container"): - ctx.invoke(assemble) - # NOTE: we need --impure here to read DEVENV_CONTAINER - spec = run_nix( - f'build --impure --print-out-paths --no-link .#devenv.containers."{container_name}".derivation', - use_cachix=True, - ) - click.echo(spec) - - # copy container - if copy or docker_run: - with log_task(f"Copying {container_name} container"): - # we need --impure here for DEVENV_CONTAINER - copy_script = run_nix( - f'build --print-out-paths --no-link \ - --impure .#devenv.containers."{container_name}".copyScript', - use_cachix=True, - ) - - if docker_run: - registry = "docker-daemon:" - - cp = f"{copy_script} {spec} {registry or 'false'} {copy_args or ''}" - - log(f"Running '{cp}'", level="info") - - subprocess.run( - cp, - shell=True, - check=True, - ) - - if docker_run: - log(f"Starting {container_name} container", level="info") - # we need --impure here for DEVENV_CONTAINER - docker_script = run_nix( - f'build --print-out-paths --no-link --impure \ - .#devenv.containers."{container_name}".dockerRun', - use_cachix=True, - ) - - subprocess.run(docker_script) - - -@cli.command( - help="Print information about this developer environment.", - short_help="Print information about this developer environment.", -) -@click.pass_context -def info(ctx): - ctx.invoke(assemble) - # TODO: use --json and reconstruct input metadata - metadata = run_nix("flake metadata") - matches = re.search(r"(Inputs:.+)$", metadata, re.DOTALL) - if matches: - inputs = matches.group(1) - else: - inputs = "" - info_ = run_nix("eval --raw '.#info'") - click.echo(f"{inputs}\n{info_}") - - -@cli.command() -@click.pass_context -def version(ctx): - """Display devenv version.""" - version = get_version() - click.echo(f"devenv {version} ({ctx.obj['system']})") - - -@cli.command( - help="Scaffold devenv.yaml, devenv.nix, and .envrc.", - short_help="Scaffold devenv.yaml, devenv.nix, and .envrc.", -) -@click.argument("target", default=".") -def init(target): - os.makedirs(target, exist_ok=True) - - required_files = ["devenv.nix", "devenv.yaml", ".envrc"] - for filename in required_files: - if os.path.exists(Path(target, filename)): - log(f"Aborting since {filename} already exist.", level="error") - exit(1) - return - - example = "simple" - examples_path = Path(MODULES_DIR / ".." / ".." / "examples").resolve() - - for filename in required_files: - full_filename = Path(target, filename) - if not os.path.exists(full_filename): - log(f"Creating {full_filename}", level="info") - shutil.copyfile( - os.path.join(examples_path, example, filename), full_filename - ) - - with open(".gitignore", "a+") as gitignore_file: - if "devenv" not in gitignore_file.read(): - log("Appending defaults to .gitignore", level="info") - gitignore_file.write("\n") - gitignore_file.write("# Devenv\n") - gitignore_file.write(".devenv*\n") - gitignore_file.write("devenv.local.nix\n") - gitignore_file.write("\n") - gitignore_file.write("# direnv\n") - gitignore_file.write(".direnv\n") - gitignore_file.write("\n") - gitignore_file.write("# pre-commit\n") - gitignore_file.write(".pre-commit-config.yaml\n") - gitignore_file.write("\n") - - log("Done.", level="info") - - # Check if direnv is installed - if shutil.which("direnv"): - log("direnv is installed. Running $ direnv allow .", level="info") - subprocess.run(["direnv", "allow"]) - - -@cli.command( - help="Update devenv.lock from devenv.yaml inputs. See http://devenv.sh/inputs/", - short_help="Update devenv.lock from devenv.yaml inputs. See http://devenv.sh/inputs/", -) -@click.argument("input_name", required=False) -@click.pass_context -def update(ctx, input_name): - ctx.invoke(assemble) - - if input_name: - run_nix(f"flake lock --update-input {input_name}") - else: - run_nix("flake update") - - -@cli.command() -@click.pass_context -def ci(ctx): - """Builds your developer environment and checks if everything builds.""" - ctx.invoke(assemble) - print("running ci") - print(run_command("cat ${FLAKE_FILE}")) - output_path = run_nix("build --no-link --print-out-paths .#ci", use_cachix=True) - add_gc("ci", output_path) - - -@cli.command(hidden=True) -@click.option("--json", is_flag=True) -@click.pass_context -def print_dev_env(ctx, json): - env, _ = get_dev_environment(ctx, json=json, logging=False) - click.echo(env) - - -def get_version(): - with open(Path(MODULES_DIR, "latest-version")) as f: - return f.read().strip() - - -@cli.group( - help="Manage inputs in devenv.yaml. See http://devenv.sh/inputs/", - short_help="Manage inputs in devenv.yaml. See http://devenv.sh/inputs/", -) -def inputs(): - pass - - -@inputs.command( - help="Add a new input to the developer environment.", - short_help="Add a new input to the developer environment.", -) -@click.argument("name") -@click.argument("url") -@click.option("--follows", "-f", multiple=True, help="Add a dependency to the input.") -@click.pass_context -def add(ctx, name, url, follows): - devenv = read_yaml() - attrs = {"url": url} - - inputs = {} - for follow in follows: - if follow not in devenv["inputs"]: - log( - f"Input {follow} does not exist so it can't be followed.", level="error" - ) - exit(1) - inputs[follow] = {"follows": follow} - - if inputs: - attrs["inputs"] = inputs - devenv["inputs"][name] = attrs - - write_yaml(devenv) - - -@cli.command( - help="Run tests. See http://devenv.sh/tests/", - short_help="Run tests. See http://devenv.sh/tests/", -) -@click.argument("names", nargs=-1) -@click.option("--debug", is_flag=True, help="Run tests in debug mode.") -@click.option("--keep-going", is_flag=True, help="Continue running tests if one fails.") -@click.option( - "--exclude", - multiple=True, - help="A test name to exclude, may be specified multiple times", -) -@click.pass_context -def test(ctx, debug, keep_going, exclude, names): - ctx.invoke(assemble) - with log_task("Gathering tests", newline=False): - tests = json.loads(run_nix("eval .#devenv.tests --json")) - - if not names: - names = ["local"] - - # group tests by tags - tags = {} - for name, test in tests.items(): - for tag in test["tags"]: - if tag not in tags: - tags[tag] = [] - tags[tag].append(name) - - selected_tests = [] - for name in names: - if name in tests: - selected_tests.append(name) - tag_tests = tags.get(name, {}) - for test in tag_tests: - if not test in exclude: - selected_tests.append(test) - - log(f"Found {len(tests)} test(s), running {len(selected_tests)}:", level="info") - - pwd = os.getcwd() - failed = [] - - for name in selected_tests: - with log_task(f" Testing {name}"): - with tempfile.TemporaryDirectory(prefix=name + "_") as tmpdir: - os.chdir(tmpdir) - test = tests[name] - - if test.get("src"): - shutil.copytree( - test["src"], ".", dirs_exist_ok=True, copy_function=shutil.copy - ) - run_command("find . -type d -exec chmod +wx {} \;") - else: - write_if_defined("devenv.nix", test.get("nix")) - write_if_defined("devenv.yaml", test.get("yaml")) - write_if_defined(".test.sh", test.get("test")) - if os.path.exists(".test.sh"): - os.chmod(".test.sh", 0o755) - - # predefined utilities - write_if_defined( - "devenv.local.nix", - """ -{ pkgs, ... }: { - packages = [ pkgs.coreutils-full ]; -} - """.strip() - + "\n", - ) - - # plug in devenv input if needed - if os.path.exists(os.path.join(pwd, "src/modules/latest-version")): - log( - " Detected devenv module. Using src/modules for tests.", - level="info", - ) - - if not os.path.exists("devenv.yaml"): - write_yaml( - strictyaml.as_document({"inputs": {}}, schema=schema) - ) - os.chmod("devenv.yaml", 0o644) - yaml = read_yaml() - inputs = yaml.get("inputs", {}) - inputs["devenv"] = {"url": f"path:{pwd}?dir=src/modules"} - yaml["inputs"] = inputs - write_yaml(yaml) - - devenv = sys.argv[0] - has_processes = False - try: - log(" Running $ devenv ci ...", level="info") - run_command(f"{devenv} ci") - - has_processes = os.path.exists( - ".devenv/gc/ci" - ) and "-devenv-up" in run_command("cat .devenv/gc/ci") - - if has_processes: - log(" Starting processes ...", level="info") - run_command(f"{devenv} up -d") - # stream logs - p = subprocess.Popen( - "tail -f .devenv/processes.log", - shell=True, - ) - else: - p = None - - try: - if os.path.exists(".test.sh"): - log(" Running .test.sh ...", level="info") - run_command(f"{devenv} shell bash ./.test.sh") - finally: - if has_processes and not debug: - run_command(f"{devenv} processes stop") - if p: - p.kill() - except KeyboardInterrupt: - raise - except BaseException as e: - log_error(f"Test {name} failed.") - if keep_going: - failed.append(name) - continue - if debug: - log( - "Entering shell because of the --debug flag:", - level="warning", - ) - log(f" - devenv: {devenv}", level="warning") - log(f" - cwd: {tmpdir}", level="warning") - if has_processes: - log(" - up logs: .devenv/processes.log:", level="warning") - os.execv("/bin/sh", ["/bin/sh"]) - else: - log_warning("Pass --debug flag to enter shell.") - raise e - if keep_going and failed: - log_error(f"Failed: {', '.join(failed)}") - sys.exit(2) - - -def write_if_defined(file, content): - if content: - with open(file, "w") as f: - f.write(content) - - -@functools.cache -def get_cachix_caches(logging=True): - """Get the full list of cachix caches we need and their public keys. - - This is cached because it's expensive to run. - """ - try: - caches_raw = run_nix( - "eval .#devenv.cachix --json", - dont_exit=True, - disable_stderr=True, - logging=False, - ) - except subprocess.CalledProcessError: - return {"pull": [], "push": None}, {} - - caches = json.loads(caches_raw) - - if CACHIX_KNOWN_PUBKEYS.exists(): - known_keys = json.loads(CACHIX_KNOWN_PUBKEYS.read_text()) - else: - known_keys = {} - new_known_keys = {} - for name in caches.get("pull", []): - if name not in known_keys: - resp = requests.get(f"https://cachix.org/api/v1/cache/{name}") - if resp.status_code in [401, 404]: - log_error( - f"Cache {name} does not exist or you don't have a CACHIX_AUTH_TOKEN configured." - ) - # TODO: instruct how to best configure netrc - # log_error("To configure a token, run `cachix authtoken `.") - log_error("To create a cache, go to https://app.cachix.org/.") - exit(1) - else: - resp.raise_for_status() - pubkey = resp.json()["publicSigningKeys"][0] - new_known_keys[name] = pubkey - - if caches.get("pull"): - if logging: - log_info(f"Using Cachix: {', '.join(caches.get('pull', []))} ") - if new_known_keys: - for name, pubkey in new_known_keys.items(): - if logging: - log_info( - f" Trusting {name}.cachix.org on first use with the public key {pubkey}" - ) - known_keys.update(new_known_keys) - CACHIX_KNOWN_PUBKEYS.write_text(json.dumps(known_keys)) - return caches, known_keys - - -@cli.command() -@click.argument("attrs", nargs=-1, required=True) -@click.pass_context -def build(ctx, attrs): - """Build attributes in your devenv.nix.""" - ctx.invoke(assemble) - attrs = " ".join(map(lambda attr: f".#devenv.{attr}", attrs)) - output = run_nix( - f"build --print-out-paths --print-build-logs --no-link {attrs}", use_cachix=True - ) - log("Built:", level="info") - for path in output.splitlines(): - log(path, level="info") diff --git a/src/devenv/log.py b/src/devenv/log.py deleted file mode 100644 index 0b56f3b69..000000000 --- a/src/devenv/log.py +++ /dev/null @@ -1,56 +0,0 @@ -from typing import Literal -import time - -import click - - -class log_task: - """Context manager for logging progress of a task.""" - - def __init__(self, message, newline=True): - self.message = message - self.newline = newline - - def __enter__(self): - prefix = click.style("•", fg="blue") - self.start = time.time() - click.echo(f"{prefix} {self.message} ...", nl=self.newline) - - def __exit__(self, exc, *args): - end = time.time() - if exc: - prefix = click.style("✖", fg="red") - else: - prefix = click.style("✔", fg="green") - click.echo(f"\r{prefix} {self.message} in {end - self.start:.1f}s.") - - -LogLevel = Literal["info", "warning", "error", "debug"] - - -def log(message, level: LogLevel): - match level: - case "info": - click.echo(click.style("• ", fg="green") + message) - case "warning": - click.echo(click.style("• ", fg="yellow") + message, err=True) - case "error": - click.echo(click.style("✖ ", fg="red") + message, err=True) - case "debug": - click.echo(click.style("• ", fg="magenta") + message, err=True) - - -def log_error(message): - log(message, "error") - - -def log_warning(message): - log(message, "warning") - - -def log_info(message): - log(message, "info") - - -def log_debug(message): - log(message, "debug") diff --git a/src/devenv/yaml.py b/src/devenv/yaml.py deleted file mode 100644 index 634a20e1d..000000000 --- a/src/devenv/yaml.py +++ /dev/null @@ -1,63 +0,0 @@ -import json -import sys -import os -from pathlib import Path - -from strictyaml import Map, MapPattern, Str, Seq -from strictyaml import load, Bool, Any, Optional, YAMLError, EmptyDict - - -inputsSchema = EmptyDict() | MapPattern( - Str(), - Map( - { - "url": Str(), - Optional("flake", default=None): Bool(), - Optional("inputs", default=None): Any(), - Optional("overlays", default=None): Seq(Str()), - } - ), -) - -schema = Map( - { - Optional("inputs", default=None): inputsSchema, - Optional("allowUnfree", default=False): Bool(), - Optional("allowBroken", default=False): Bool(), - Optional("imports", default=None): Seq(Str()), - Optional("permittedInsecurePackages", default=None): Seq(Str()), - } -) - -YAML_FILE = Path("devenv.yaml") - - -def read_yaml(): - try: - with open(YAML_FILE) as f: - return load(f.read(), schema, label="devenv.yaml") - except YAMLError as error: - print("Validation error in `devenv.yaml`", error) - sys.exit(1) - - -def write_yaml(yaml): - with open(YAML_FILE, "w") as f: - f.write(yaml.as_yaml()) - - -def validate_and_parse_yaml(dot_devenv_root): - devenv = read_yaml().data - - inputs = {} - for input, attrs in devenv.get("inputs", {}).items(): - inputs[input] = {k: attrs[k] for k in ("url", "inputs", "flake") if k in attrs} - - with open(os.path.join(dot_devenv_root, "flake.json"), "w") as f: - f.write(json.dumps(inputs)) - - with open(os.path.join(dot_devenv_root, "devenv.json"), "w") as f: - f.write(json.dumps(devenv)) - - with open(os.path.join(dot_devenv_root, "imports.txt"), "w") as f: - f.write("\n".join(devenv.get("imports", []))) diff --git a/src/modules/flake.tmpl.nix b/src/modules/flake.tmpl.nix deleted file mode 100644 index 61c9b0a75..000000000 --- a/src/modules/flake.tmpl.nix +++ /dev/null @@ -1,95 +0,0 @@ -{ - inputs = { - pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; - pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs"; - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - devenv.url = "github:cachix/devenv?dir=src/modules"; - } // (if builtins.pathExists ./.devenv/flake.json - then builtins.fromJSON (builtins.readFile ./.devenv/flake.json) - else { }); - - outputs = { nixpkgs, ... }@inputs: - let - __DEVENV_VARS__ - devenv = - if builtins.pathExists ./.devenv/devenv.json - then builtins.fromJSON (builtins.readFile ./.devenv/devenv.json) - else { }; - getOverlays = inputName: inputAttrs: - map - (overlay: - let - input = inputs.${inputName} or (throw "No such input `${inputName}` while trying to configure overlays."); - in - input.overlays.${overlay} or (throw "Input `${inputName}` has no overlay called `${overlay}`. Supported overlays: ${nixpkgs.lib.concatStringsSep ", " (builtins.attrNames input.overlays)}")) - inputAttrs.overlays or [ ]; - overlays = nixpkgs.lib.flatten (nixpkgs.lib.mapAttrsToList getOverlays (devenv.inputs or { })); - pkgs = import nixpkgs { - inherit system; - config = { - allowUnfree = devenv.allowUnfree or false; - allowBroken = devenv.allowBroken or false; - permittedInsecurePackages = devenv.permittedInsecurePackages or [ ]; - }; - inherit overlays; - }; - lib = pkgs.lib; - importModule = path: - if lib.hasPrefix "./" path - then if lib.hasSuffix ".nix" path - then ./. + (builtins.substring 1 255 path) - else ./. + (builtins.substring 1 255 path) + "/devenv.nix" - else if lib.hasPrefix "../" path - then throw "devenv: ../ is not supported for imports" - else - let - paths = lib.splitString "/" path; - name = builtins.head paths; - input = inputs.${name} or (throw "Unknown input ${name}"); - subpath = "/${lib.concatStringsSep "/" (builtins.tail paths)}"; - devenvpath = "${input}" + subpath + "/devenv.nix"; - in - if builtins.pathExists devenvpath - then devenvpath - else throw (devenvpath + " file does not exist for input ${name}."); - project = pkgs.lib.evalModules { - specialArgs = inputs // { inherit inputs pkgs; }; - modules = [ - (inputs.devenv.modules + /top-level.nix) - { - devenv.cliVersion = "${version}"; - devenv.root = devenv_root; - } - ] ++ (map importModule (devenv.imports or [ ])) ++ [ - ./devenv.nix - (devenv.devenv or { }) - (if builtins.pathExists ./devenv.local.nix then ./devenv.local.nix else { }) - ]; - }; - config = project.config; - - options = pkgs.nixosOptionsDoc { - options = builtins.removeAttrs project.options [ "_module" ]; - # Unpack Nix types, e.g. literalExpression, mDoc. - transformOptions = - let isDocType = v: builtins.elem v [ "literalDocBook" "literalExpression" "literalMD" "mdDoc" ]; - in lib.attrsets.mapAttrs (_: v: - if v ? _type && isDocType v._type then - v.text - else if v ? _type && v._type == "derivation" then - v.name - else - v - ); - }; - in - { - packages."${system}" = { - optionsJSON = options.optionsJSON; - inherit (config) info procfileScript procfileEnv procfile; - ci = config.ciDerivation; - }; - devenv = config; - devShell."${system}" = config.shell; - }; -} diff --git a/src/modules/integrations/devcontainer.nix b/src/modules/integrations/devcontainer.nix index 239bc2142..38e6ce1ac 100644 --- a/src/modules/integrations/devcontainer.nix +++ b/src/modules/integrations/devcontainer.nix @@ -31,7 +31,7 @@ in options.updateContentCommand = lib.mkOption { type = lib.types.anything; - default = "devenv ci"; + default = "devenv test"; description = lib.mdDoc '' Command to run after container creation. ''; diff --git a/src/modules/integrations/dotenv.nix b/src/modules/integrations/dotenv.nix index 7142e277a..c34b1369b 100644 --- a/src/modules/integrations/dotenv.nix +++ b/src/modules/integrations/dotenv.nix @@ -58,10 +58,12 @@ in config = lib.mkMerge [ (lib.mkIf cfg.enable { env = lib.mapAttrs (name: value: lib.mkDefault value) config.dotenv.resolved; - dotenv.resolved = mergeEnvFiles dotenvPaths; - }) - (lib.mkIf (cfg.enable) { enterShell = lib.concatStringsSep "\n" (map createMissingFileMessage dotenvPaths); + dotenv.resolved = mergeEnvFiles dotenvPaths; + assertions = [{ + assertion = lib.hasPrefix ".env" cfg.filename; + message = "The dotenv filename must start with '.env'."; + }]; }) (lib.mkIf (!cfg.enable && !cfg.disableHint) { enterShell = diff --git a/src/modules/integrations/pre-commit.nix b/src/modules/integrations/pre-commit.nix index 3dcbbae06..8b6f71e6a 100644 --- a/src/modules/integrations/pre-commit.nix +++ b/src/modules/integrations/pre-commit.nix @@ -20,6 +20,9 @@ config = lib.mkIf ((lib.filterAttrs (id: value: value.enable) config.pre-commit.hooks) != { }) { ci = [ config.pre-commit.run ]; + enterTest = '' + pre-commit run -a + ''; packages = [ config.pre-commit.package ]; enterShell = config.pre-commit.installationScript; }; diff --git a/src/modules/languages/python.nix b/src/modules/languages/python.nix index e391d195b..05ff0de76 100644 --- a/src/modules/languages/python.nix +++ b/src/modules/languages/python.nix @@ -46,7 +46,7 @@ let VENV_PATH="${config.env.DEVENV_STATE}/venv" profile_python="$(${readlink} ${package.interpreter})" - devenv_interpreter_path="$(${pkgs.coreutils}/bin/cat "$VENV_PATH/.devenv_interpreter" 2> /dev/null|| false )" + devenv_interpreter_path="$(${pkgs.coreutils}/bin/cat "$VENV_PATH/.devenv_interpreter" 2> /dev/null || echo false )" venv_python="$(${readlink} "$devenv_interpreter_path")" requirements="${lib.optionalString (cfg.venv.requirements != null) ''${requirements}''}" @@ -68,7 +68,7 @@ let # reinstall requirements if necessary if [ -n "$requirements" ] then - devenv_requirements_path="$(${pkgs.coreutils}/bin/cat "$VENV_PATH/.devenv_requirements" 2> /dev/null|| false )" + devenv_requirements_path="$(${pkgs.coreutils}/bin/cat "$VENV_PATH/.devenv_requirements" 2> /dev/null|| echo false )" devenv_requirements="$(${readlink} "$devenv_requirements_path")" if [ -z $devenv_requirements ] || [ $devenv_requirements != $requirements ] then diff --git a/src/modules/processes.nix b/src/modules/processes.nix index de7a25901..dcdbc9dea 100644 --- a/src/modules/processes.nix +++ b/src/modules/processes.nix @@ -53,7 +53,7 @@ in implementation = lib.mkOption { type = types.enum [ "honcho" "overmind" "process-compose" "hivemind" ]; description = "The implementation used when performing ``devenv up``."; - default = "honcho"; + default = "process-compose"; example = "overmind"; }; diff --git a/src/modules/tests.nix b/src/modules/tests.nix index 5eba38745..856fd1a62 100644 --- a/src/modules/tests.nix +++ b/src/modules/tests.nix @@ -1,60 +1,42 @@ -{ config, lib, ... }: +{ pkgs, config, lib, ... }: -let - testType = lib.types.submodule ({ config, ... }: { - options = { - tags = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ "local" ]; - description = "Tags for this test."; - }; - - nix = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - example = "{ pkgs, ... }: {}"; - description = "devenv.nix code."; - }; - - yaml = lib.mkOption { - type = lib.types.nullOr lib.types.str; - default = null; - example = '' - inputs: - nixpkgs: - url: github:NixOS/nixpkgs/nixpkgs-unstable - ''; - description = "devenv.yaml code."; - }; +{ + options = { + enterTest = lib.mkOption { + type = lib.types.lines; + description = "Bash code to execute to run the test."; + }; - test = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "Bash to be executed."; - default = null; - }; + test = lib.mkOption { + type = lib.types.package; + internal = true; + default = pkgs.writeShellScript "devenv-test" '' + echo "• Setting up shell environment ..." + ${config.enterShell} - src = lib.mkOption { - type = lib.types.nullOr lib.types.path; - default = null; - description = "Source code with all the files."; - }; + set -euo pipefail + echo "• Testing ..." + ${config.enterTest} + ''; }; - }); -in -{ - options.tests = lib.mkOption { - type = lib.types.attrsOf testType; - default = { }; - description = "Tests for this module."; }; - config.assertions = - let - mk = name: cfg: - { - assertion = cfg.nix != null || cfg.src != null; - message = "Either tests.${name}.nix or tests.${name}.src needs to be defined."; - }; - in - lib.mapAttrsToList mk config.tests; + config = { + enterTest = '' + # Wait for the port to be open until the timeout is reached + wait_for_port() { + local port=$1 + local timeout=''${2:-15} + + timeout $timeout bash -c "until echo > /dev/tcp/localhost/$port; do sleep 0.5; done" + } + + export -f wait_for_port + + if [ -f ./.test.sh ]; then + echo "• Running .test.sh..." + ./.test.sh + fi + ''; + }; } diff --git a/src/modules/top-level.nix b/src/modules/top-level.nix index aa1ef0caa..839d44197 100644 --- a/src/modules/top-level.nix +++ b/src/modules/top-level.nix @@ -195,7 +195,6 @@ in } ]; # use builtins.toPath to normalize path if root is "/" (container) - devenv.dotfile = builtins.toPath (config.devenv.root + "/.devenv"); devenv.state = builtins.toPath (config.devenv.dotfile + "/state"); devenv.profile = profile; diff --git a/tests/clean/devenv.nix b/tests/clean/devenv.nix new file mode 100644 index 000000000..e3d2dda9e --- /dev/null +++ b/tests/clean/devenv.nix @@ -0,0 +1,14 @@ +{ + enterTest = '' + if [ -z "$DEVENV_NIX" ]; then + echo "DEVENV_NIX is not set" + exit 1 + fi + + set +u + if [ ! -z "$BROWSER" ]; then + echo "BROWSER is set" + exit 1 + fi + ''; +} diff --git a/tests/clean/devenv.yaml b/tests/clean/devenv.yaml new file mode 100644 index 000000000..1dc3c3e14 --- /dev/null +++ b/tests/clean/devenv.yaml @@ -0,0 +1,7 @@ +inputs: + devenv: + url: path:../../?dir=src/modules +clean: + enabled: true + keep: + - DEVENV_NIX diff --git a/tests/cli/.test.sh b/tests/cli/.test.sh index 769fea488..3c52a0920 100755 --- a/tests/cli/.test.sh +++ b/tests/cli/.test.sh @@ -1,4 +1,20 @@ -#!/usr/bin/env bash set -xe + +# TODO: provide devenv cli via inputs +export PATH=$(pwd)/../../result/bin:$PATH + devenv build languages.python.package -devenv shell ls -la \ No newline at end of file +devenv shell ls -- -la | grep ".test.sh" +devenv shell ls ../ | grep "cli" +devenv info | grep "python3-" +devenv show | grep "python3-" +devenv search ncdu | grep "Found 3 packages and 0 options for 'ncdu'" +# there should be no processes +devenv up && exit 1 +# containers +devenv container build shell && exit 1 +devenv inputs add mk-shell-bin github:rrbutani/nix-mk-shell-bin --follows nixpkgs +devenv inputs add nix2container github:nlewo/nix2container --follows nixpkgs +devenv container build shell | grep image-shell.json +# bw compat +devenv container shell | grep "image-shell.json" \ No newline at end of file diff --git a/tests/cli/devenv.nix b/tests/cli/devenv.nix index ecce39d5a..04d1d2c01 100644 --- a/tests/cli/devenv.nix +++ b/tests/cli/devenv.nix @@ -1,3 +1,3 @@ -{ ... }: { +{ pkgs, inputs, ... }: { languages.python.enable = true; } diff --git a/tests/cli/devenv.yaml b/tests/cli/devenv.yaml new file mode 100644 index 000000000..291d7fd61 --- /dev/null +++ b/tests/cli/devenv.yaml @@ -0,0 +1,11 @@ +inputs: + mk-shell-bin: + url: github:rrbutani/nix-mk-shell-bin + inputs: + nixpkgs: + follows: nixpkgs + nix2container: + url: github:nlewo/nix2container + inputs: + nixpkgs: + follows: nixpkgs diff --git a/tests/dotenv/.setup.sh b/tests/dotenv/.setup.sh new file mode 100755 index 000000000..39452af0f --- /dev/null +++ b/tests/dotenv/.setup.sh @@ -0,0 +1 @@ +echo "{ env.LOCAL = \"1\";}" > devenv.local.nix \ No newline at end of file diff --git a/examples/dotenv/.test.sh b/tests/dotenv/.test.sh similarity index 100% rename from examples/dotenv/.test.sh rename to tests/dotenv/.test.sh diff --git a/examples/dotenv/bar.env b/tests/dotenv/bar.env similarity index 100% rename from examples/dotenv/bar.env rename to tests/dotenv/bar.env diff --git a/examples/dotenv/devenv.nix b/tests/dotenv/devenv.nix similarity index 100% rename from examples/dotenv/devenv.nix rename to tests/dotenv/devenv.nix diff --git a/examples/dotenv/devenv.yaml b/tests/dotenv/devenv.yaml similarity index 100% rename from examples/dotenv/devenv.yaml rename to tests/dotenv/devenv.yaml diff --git a/tests/gitignore/.setup.sh b/tests/gitignore/.setup.sh new file mode 100644 index 000000000..d1bfa0b89 --- /dev/null +++ b/tests/gitignore/.setup.sh @@ -0,0 +1,2 @@ +echo "{ env.LOCAL = \"1\";}" > devenv.local.nix +echo "ENV=1" > .env diff --git a/tests/gitignore/.test.sh b/tests/gitignore/.test.sh new file mode 100755 index 000000000..a3d099347 --- /dev/null +++ b/tests/gitignore/.test.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -xe + +env | grep BAR=1 +env | grep ENV=1 +env | grep LOCAL=1 \ No newline at end of file diff --git a/tests/gitignore/devenv.nix b/tests/gitignore/devenv.nix new file mode 100644 index 000000000..4a3d67f13 --- /dev/null +++ b/tests/gitignore/devenv.nix @@ -0,0 +1,5 @@ +{ pkgs, lib, config, ... }: { + dotenv.enable = true; + + env.BAR = "1"; +} diff --git a/tests/gitignore/devenv.yaml b/tests/gitignore/devenv.yaml new file mode 100644 index 000000000..c7cb5ceda --- /dev/null +++ b/tests/gitignore/devenv.yaml @@ -0,0 +1,3 @@ +inputs: + nixpkgs: + url: github:NixOS/nixpkgs/nixpkgs-unstable diff --git a/tests/glibcLocales/devenv.lock b/tests/glibcLocales/devenv.lock new file mode 100644 index 000000000..c75382010 --- /dev/null +++ b/tests/glibcLocales/devenv.lock @@ -0,0 +1,156 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1709300857, + "owner": "cachix", + "repo": "devenv", + "rev": "f0319af4f966fb8bc25c6429f4f2e097e79116c2", + "treeHash": "a035e54b8fe8523068171e97568d4d891234ccb0", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "treeHash": "2addb7b71a20a25ea74feeaf5c2f6a6b30898ecb", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1709126324, + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "treeHash": "f52cf07f5dc7208c6379eb10b7505fda4c429b88", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "treeHash": "ca14199cabdfe1a06a7b1654c76ed49100a689f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1709386671, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fa9a51752f1b5de583ad5213eb621be071806663", + "treeHash": "2cf56c4a9c6d7667222890dd4fb45de7574483b2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1709309926, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "79baff8812a0d68e24a836df0a364c678089e2c7", + "treeHash": "0a912c9b662a028d46d4bfad6193d4379eb28ceb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1708018599, + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", + "treeHash": "6b6519c2b58ad1e106d9633f0d1b490a70fc6980", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "treeHash": "cce81f2a0f0743b2eb61bc2eb6c7adbe2f2c6beb", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/tests/glibcLocales/devenv.nix b/tests/glibcLocales/devenv.nix new file mode 100644 index 000000000..8e74deee9 --- /dev/null +++ b/tests/glibcLocales/devenv.nix @@ -0,0 +1,5 @@ +{ + enterTest = '' + locale | grep "LANG=en_US.UTF-8" + ''; +} diff --git a/tests/impure/devenv.nix b/tests/impure/devenv.nix new file mode 100644 index 000000000..9e9a2091a --- /dev/null +++ b/tests/impure/devenv.nix @@ -0,0 +1,5 @@ +{ + enterTest = '' + echo ${builtins.currentSystem}; + ''; +} diff --git a/tests/impure/devenv.yaml b/tests/impure/devenv.yaml new file mode 100644 index 000000000..eeb4d8d38 --- /dev/null +++ b/tests/impure/devenv.yaml @@ -0,0 +1 @@ +impure: true diff --git a/tests/permit-insecure/devenv.nix b/tests/permit-insecure/devenv.nix new file mode 100644 index 000000000..5505f0e00 --- /dev/null +++ b/tests/permit-insecure/devenv.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: + +{ + # https://devenv.sh/languages/ + languages.ruby = { + enable = true; + version = "2.6.5"; + }; +} diff --git a/tests/permit-insecure/devenv.yaml b/tests/permit-insecure/devenv.yaml new file mode 100644 index 000000000..50d421943 --- /dev/null +++ b/tests/permit-insecure/devenv.yaml @@ -0,0 +1,10 @@ +inputs: + nixpkgs: + url: github:NixOS/nixpkgs/nixpkgs-unstable + nixpkgs-ruby: + url: github:bobvanderlinden/nixpkgs-ruby + inputs: + nixpkgs: + follows: nixpkgs +permittedInsecurePackages: + - "openssl-1.1.1w" diff --git a/tests/python-native-libs/.test.sh b/tests/python-native-libs/.test.sh index 119fd2259..f8bcec0a7 100755 --- a/tests/python-native-libs/.test.sh +++ b/tests/python-native-libs/.test.sh @@ -1,9 +1,5 @@ -#!/usr/bin/env bash -set -ex - python -c "from PIL import Image" python -c "import grpc_tools.protoc" python -c "import transformers" -python -c "import torch" # TODO: invoke a subprocess with an old glibc and assert it doesn't crash \ No newline at end of file diff --git a/tests/python-native-libs/devenv.nix b/tests/python-native-libs/devenv.nix index 5d7bd5a29..f3fdb2f91 100644 --- a/tests/python-native-libs/devenv.nix +++ b/tests/python-native-libs/devenv.nix @@ -1,13 +1,6 @@ { pkgs, lib, ... }: { packages = [ pkgs.cairo ]; - # we must set LD_LIBRARY_PATH by hand without use of the env-venv - # version of nixpkgs, this can be removed when we switch to one - env.LD_LIBRARY_PATH = lib.makeLibraryPath [ - pkgs.pythonManylinuxPackages.manylinux2014Package - pkgs.zlib - ]; - languages.python = { enable = true; venv.enable = true; @@ -15,7 +8,6 @@ pillow grpcio-tools transformers - torch ''; }; } diff --git a/tests/python-native-libs/devenv.yaml b/tests/python-native-libs/devenv.yaml index 25b947129..777857cb4 100644 --- a/tests/python-native-libs/devenv.yaml +++ b/tests/python-native-libs/devenv.yaml @@ -1,5 +1,3 @@ inputs: - devenv: - url: path:./../../src/modules nixpkgs: - url: github:NixOS/nixpkgs/nixpkgs-unstable + url: github:cachix/nixpkgs/python-venv \ No newline at end of file diff --git a/tests/up-uses-shell/devenv.lock b/tests/up-uses-shell/devenv.lock new file mode 100644 index 000000000..c75382010 --- /dev/null +++ b/tests/up-uses-shell/devenv.lock @@ -0,0 +1,156 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1709300857, + "owner": "cachix", + "repo": "devenv", + "rev": "f0319af4f966fb8bc25c6429f4f2e097e79116c2", + "treeHash": "a035e54b8fe8523068171e97568d4d891234ccb0", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "treeHash": "2addb7b71a20a25ea74feeaf5c2f6a6b30898ecb", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1709126324, + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "treeHash": "f52cf07f5dc7208c6379eb10b7505fda4c429b88", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "treeHash": "ca14199cabdfe1a06a7b1654c76ed49100a689f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1709386671, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fa9a51752f1b5de583ad5213eb621be071806663", + "treeHash": "2cf56c4a9c6d7667222890dd4fb45de7574483b2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1709309926, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "79baff8812a0d68e24a836df0a364c678089e2c7", + "treeHash": "0a912c9b662a028d46d4bfad6193d4379eb28ceb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1708018599, + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "5df5a70ad7575f6601d91f0efec95dd9bc619431", + "treeHash": "6b6519c2b58ad1e106d9633f0d1b490a70fc6980", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "treeHash": "cce81f2a0f0743b2eb61bc2eb6c7adbe2f2c6beb", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/tests/up-uses-shell/devenv.nix b/tests/up-uses-shell/devenv.nix new file mode 100644 index 000000000..6a9fe513c --- /dev/null +++ b/tests/up-uses-shell/devenv.nix @@ -0,0 +1,14 @@ +{ + enterShell = '' + export FOO=1 + ''; + + enterTest = '' + sleep 1 + if [ $(cat foo) -ne 1 ]; then + exit 1 + fi + ''; + + processes.test.exec = "while true; do echo $FOO > foo; sleep 1; done"; +}