From 1a23f7c5f248e8160a3840d2911aee479c2bce68 Mon Sep 17 00:00:00 2001 From: squidfunk Date: Sat, 15 Nov 2025 12:06:33 +0100 Subject: [PATCH] zensical:fix - allow to set dev_addr in configuration Signed-off-by: squidfunk --- Cargo.lock | 554 ++++++++++++++++++++++++++- Cargo.toml | 1 + crates/zensical/Cargo.toml | 1 + crates/zensical/src/lib.rs | 27 +- crates/zensical/src/server.rs | 31 +- crates/zensical/src/server/client.rs | 17 +- python/zensical/main.py | 26 +- 7 files changed, 601 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acd4ba3..bf19011 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,18 +64,56 @@ dependencies = [ "serde", ] +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + [[package]] name = "bytes" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "crossbeam" version = "0.8.4" @@ -132,6 +170,17 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "file-id" version = "0.2.3" @@ -151,6 +200,15 @@ dependencies = [ "ref-cast", ] +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -203,6 +261,108 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "indoc" version = "2.0.7" @@ -238,6 +398,38 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "kqueue" version = "1.1.1" @@ -344,6 +536,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "notify" version = "8.2.0" @@ -377,6 +575,31 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.10.0", + "objc2", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -401,6 +624,15 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -658,6 +890,12 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "syn" version = "2.0.101" @@ -669,19 +907,50 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "target-lexicon" version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -704,6 +973,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tracing" version = "0.1.41" @@ -781,7 +1060,7 @@ dependencies = [ "bytes", "log", "rand", - "thiserror", + "thiserror 2.0.17", "utf-8", ] @@ -797,12 +1076,30 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + [[package]] name = "utf-8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "valuable" version = "0.1.1" @@ -840,6 +1137,77 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webbrowser" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" +dependencies = [ + "core-foundation", + "jni", + "log", + "ndk-context", + "objc2", + "objc2-foundation", + "url", + "web-sys", +] + [[package]] name = "winapi-util" version = "0.1.11" @@ -855,13 +1223,22 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets", + "windows-targets 0.53.5", ] [[package]] @@ -873,6 +1250,21 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-targets" version = "0.53.5" @@ -880,28 +1272,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.53.1" @@ -914,24 +1324,48 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.53.1" @@ -944,6 +1378,35 @@ version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zensical" version = "0.0.7" @@ -957,10 +1420,11 @@ dependencies = [ "pyo3", "serde", "serde_json", - "thiserror", + "thiserror 2.0.17", "tracing", "tracing-chrome", "tracing-subscriber", + "webbrowser", "zensical-serve", "zensical-watch", "zrx", @@ -979,7 +1443,7 @@ dependencies = [ "percent-encoding", "sha1_smol", "slab", - "thiserror", + "thiserror 2.0.17", "tungstenite", ] @@ -992,7 +1456,7 @@ dependencies = [ "file-id", "notify", "pyo3", - "thiserror", + "thiserror 2.0.17", "tracing", "walkdir", "zrx", @@ -1018,6 +1482,60 @@ dependencies = [ "syn", ] +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zrx" version = "0.0.3" @@ -1047,7 +1565,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c0ace038e234e564aa9a352419b7eb8ea64996351affbfb8f2b1a593c3b24d4" dependencies = [ "crossbeam", - "thiserror", + "thiserror 2.0.17", ] [[package]] @@ -1057,7 +1575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8deb42a334884f7d30d4ceba77db865fe22ae0db9a2678e90d1449527c935ad" dependencies = [ "ahash", - "thiserror", + "thiserror 2.0.17", ] [[package]] @@ -1068,7 +1586,7 @@ checksum = "53ca8d5b09df525295bcfc45a5fd35e16e9f47c16a07283a071d4518dc76befa" dependencies = [ "globset", "percent-encoding", - "thiserror", + "thiserror 2.0.17", "zrx-path", ] @@ -1087,7 +1605,7 @@ dependencies = [ "ahash", "crossbeam", "slab", - "thiserror", + "thiserror 2.0.17", "tracing", "zrx-diagnostic", "zrx-executor", @@ -1114,7 +1632,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7c6087ba332dd45fc7a6f364e99f30d28405374ffabe7ac6787fc402ba86473" dependencies = [ "ahash", - "thiserror", + "thiserror 2.0.17", "tracing", "zrx-graph", "zrx-id", diff --git a/Cargo.toml b/Cargo.toml index 460b702..ab3bedf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,6 +67,7 @@ tracing = { version = "0.1.41" } tracing-chrome = "0.7.2" tracing-subscriber = "0.3.20" walkdir = "2.5.0" +webbrowser = "1.0.6" zrx = "0.0.3" [workspace.dependencies.pyo3] diff --git a/crates/zensical/Cargo.toml b/crates/zensical/Cargo.toml index 7f4c01c..2140542 100644 --- a/crates/zensical/Cargo.toml +++ b/crates/zensical/Cargo.toml @@ -63,6 +63,7 @@ tracing = { workspace = true, optional = true, features = [ ] } tracing-chrome = { workspace = true, optional = true } tracing-subscriber = { workspace = true, optional = true } +webbrowser.workspace = true zrx.workspace = true [features] diff --git a/crates/zensical/src/lib.rs b/crates/zensical/src/lib.rs index 439635b..1ad87be 100644 --- a/crates/zensical/src/lib.rs +++ b/crates/zensical/src/lib.rs @@ -45,7 +45,7 @@ mod watcher; mod workflow; use config::Config; -use server::create_server; +use server::{create_server, ServeOptions}; use watcher::Watcher; use workflow::create_workspace; @@ -59,7 +59,7 @@ pub enum Mode { /// Build the project once. Build(bool), /// Build the project continuously. - Serve(String, u64), + Serve(ServeOptions, u64), } // ---------------------------------------------------------------------------- @@ -139,13 +139,20 @@ fn run(config_file: &PathBuf, mode: Mode) -> PyResult { // the scheduler with the agent. let waker = match &mode { Mode::Build(_) => None, - Mode::Serve(addr, seq) => { + Mode::Serve(options, seq) => { if *seq == 0 { - println!("Serving {} on http://{addr}", site_dir.display()); + println!( + "Serving {} on http://{}", + site_dir.display(), + options + .dev_addr + .as_ref() + .unwrap_or_else(|| &config.project.dev_addr) + ); } else { println!("Reloading..."); } - Some(create_server(&config, receiver, Some(addr.clone()))) + Some(create_server(&config, receiver, options.clone())) } }; let watcher = Watcher::new(&config, session, sender, waker.clone())?; @@ -157,7 +164,7 @@ fn run(config_file: &PathBuf, mode: Mode) -> PyResult { loop { match mode { // Build mode - just exit when we're done - Mode::Build(_) => { + Mode::Build(..) => { handle(scheduler.tick()); // @todo this is a hack to ensure we don't exit too early, as // we need to improve the interop between scheduler and agent @@ -171,7 +178,7 @@ fn run(config_file: &PathBuf, mode: Mode) -> PyResult { // happens if the configuration file changed. After we've integrated // the scheduler with the agent, we can remove this temporary hack // and have immediate reloading. - Mode::Serve(_, _) => { + Mode::Serve(..) => { handle(scheduler.tick_timeout(Duration::from_millis(100))); if watcher.is_terminated() { // Wake the server @@ -207,10 +214,12 @@ fn build(py: Python, config_file: PathBuf, clean: bool) -> PyResult<()> { /// Builds and serves the project. #[pyfunction] -fn serve(py: Python, config_file: PathBuf, dev_addr: String) -> PyResult<()> { +fn serve( + py: Python, config_file: PathBuf, options: ServeOptions, +) -> PyResult<()> { let mut seq = 0; py.detach(|| loop { - match run(&config_file, Mode::Serve(dev_addr.clone(), seq)) { + match run(&config_file, Mode::Serve(options.clone(), seq)) { Ok(true) => { seq += 1; } diff --git a/crates/zensical/src/server.rs b/crates/zensical/src/server.rs index 578b95f..16b1b05 100644 --- a/crates/zensical/src/server.rs +++ b/crates/zensical/src/server.rs @@ -27,6 +27,7 @@ use crossbeam::channel::{unbounded, Receiver}; use mio::Waker; +use pyo3::FromPyObject; use std::sync::Arc; use std::{fs, thread}; use zensical_serve::handler::Stack; @@ -39,13 +40,27 @@ mod client; use client::Client; +// ---------------------------------------------------------------------------- +// Structs +// ---------------------------------------------------------------------------- + +/// Serve options. +#[derive(Clone, Debug, FromPyObject, PartialEq, Eq)] +#[pyo3(from_item_all)] +pub struct ServeOptions { + /// Address to bind to. + pub dev_addr: Option, + /// Whether to open the browser automatically. + pub open: bool, +} + // ---------------------------------------------------------------------------- // Functions // ---------------------------------------------------------------------------- /// Creates an HTTP server to serve the site. pub fn create_server( - config: &Config, receiver: Receiver, addr: Option, + config: &Config, receiver: Receiver, options: ServeOptions, ) -> Arc { let site_dir = config.get_site_dir(); fs::create_dir_all(&site_dir).expect("site directory could not be created"); @@ -53,10 +68,12 @@ pub fn create_server( // Create a one shot channel to extract waker - this is currently necessary, // so that the server wakes up when the file watcher emits new events let (tx, rx) = unbounded(); + let addr = options + .dev_addr + .unwrap_or_else(|| config.project.dev_addr.clone()); // Create new thread to run the server let base = config.get_base_path(); - let addr = addr.unwrap_or_else(|| config.project.dev_addr.clone()); thread::spawn({ let tx = tx.clone(); move || -> Result { @@ -72,13 +89,21 @@ pub fn create_server( ); // Start server and extract waker for interaction with event loop - let mut server = match Server::new(stack, addr) { + let mut server = match Server::new(stack, &addr) { Ok(server) => server, Err(err) => { let _ = tx.send(Err(err)); return Ok(()); } }; + + // Open browser, if desired + if options.open { + let url = format!("http://{addr}"); + let _ = webbrowser::open(&url); + } + + // Send waker back to main thread let _ = tx.send(Ok(server.waker())); loop { server.poll(Some(&receiver))?; diff --git a/crates/zensical/src/server/client.rs b/crates/zensical/src/server/client.rs index 0bba6ac..24f57dc 100644 --- a/crates/zensical/src/server/client.rs +++ b/crates/zensical/src/server/client.rs @@ -26,7 +26,7 @@ //! Middleware for livereload client. use zensical_serve::handler::Handler; -use zensical_serve::http::{Header, Request, Response}; +use zensical_serve::http::{Header, Request, Response, Status}; use zensical_serve::middleware::Middleware; // ---------------------------------------------------------------------------- @@ -121,6 +121,21 @@ impl Middleware for Client { res.headers.insert(Header::CacheControl, "no-cache"); } + // In case of a 404 on "/", we attach the WebSocket script, so it will + // automatically reload once the build has finished. This is temporary, + // since we're working on properly integrating all moving parts of + // the system into a coherent flow. + if res.status == Status::NotFound { + res.body.clear(); + res.body.extend(b""); + + // Update content length + res.headers.insert(Header::ContentType, "text/html"); + res.headers.insert(Header::ContentLength, res.body.len()); + } + // Return response res } diff --git a/python/zensical/main.py b/python/zensical/main.py index 50bb130..a05da2b 100644 --- a/python/zensical/main.py +++ b/python/zensical/main.py @@ -26,10 +26,6 @@ from __future__ import annotations import click import os import shutil -import threading -import time -import webbrowser -import urllib.request from click import ClickException from zensical import build, serve, version @@ -40,21 +36,6 @@ from zensical import build, serve, version # ---------------------------------------------------------------------------- -# Wait for the server to be available before opening the browser - we'll remove -# this hack once the server can signal that it's ready for serving. -def open_browser(url): - def _open_browser(url): - while True: - try: - with urllib.request.urlopen(url): - webbrowser.open(url) - break - except Exception: - time.sleep(1) - - threading.Thread(target=_open_browser, args=(url,), daemon=True).start() - - @click.version_option(version=version(), message="%(version)s") @click.group() def cli(): @@ -141,17 +122,12 @@ def execute_serve(config_file: str | None, **kwargs): break else: raise ClickException("No config file found in the current folder.") - - # Obtain development server address and open in browser, if desired - dev_addr = kwargs.get("dev_addr") or "localhost:8000" - if kwargs.get("open", False): - open_browser(f"http://{dev_addr}") if kwargs.get("strict", False): print("Warning: Strict mode is currently unsupported.") # Build project in Rust runtime, calling back into Python when necessary, # e.g., to parse MkDocs configuration format or render Markdown - serve(os.path.abspath(config_file), dev_addr) + serve(os.path.abspath(config_file), kwargs) @cli.command(name="new")