diff --git a/CHANGELOG.md b/CHANGELOG.md index 89802f1..c44ee6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Added + +- `walk` and `set_self_link` for `read` ([#69](https://github.com/stac-utils/stacrs/pull/69)) + ## [0.5.8] - 2025-02-27 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index b9672a6..a9476e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b964d184e89d9b6b67dd2715bc8e74cf3107fb2b529990c90cf517326150bf4" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "approx" @@ -153,6 +153,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + [[package]] name = "arrayvec" version = "0.7.6" @@ -336,7 +342,7 @@ version = "54.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85934a9d0261e0fa5d4e2a5295107d743b543a6e0484a835d4b8db2da15306f9" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -389,18 +395,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "async-trait" -version = "0.1.86" +version = "0.1.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" +checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -550,9 +556,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "bitvec" @@ -601,7 +607,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -661,9 +667,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" [[package]] name = "byteorder" @@ -685,9 +691,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.15" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" dependencies = [ "jobserver", "libc", @@ -773,7 +779,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -870,7 +876,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", "unaccent", "wkt 0.12.0", ] @@ -976,7 +982,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1007,7 +1013,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1062,7 +1068,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1252,7 +1258,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -1403,7 +1409,7 @@ dependencies = [ "log", "serde", "serde_json", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] @@ -1592,9 +1598,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -1849,7 +1855,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2183,7 +2189,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "libc", "redox_syscall", ] @@ -2436,7 +2442,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2613,7 +2619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 2.0.11", + "thiserror 2.0.12", "ucd-trie", ] @@ -2637,7 +2643,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2663,13 +2669,13 @@ dependencies = [ [[package]] name = "pgstac" version = "0.3.0" -source = "git+https://github.com/stac-utils/stac-rs#85f008ab30b4c5c402ce16382cca5abbf7770055" +source = "git+https://github.com/stac-utils/stac-rs?branch=optional-tracing-cli#d3b89daebe52fc74017f68b8ac3a6c680ac0f964" dependencies = [ "serde", "serde_json", "stac", "stac-api", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio-postgres", ] @@ -2713,7 +2719,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2739,9 +2745,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" @@ -2815,9 +2821,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] @@ -2914,6 +2920,17 @@ dependencies = [ "pyo3-build-config", ] +[[package]] +name = "pyo3-log" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5bb22b77965a7b5394e9aae9897a0607b51df5167561ffc3b02643b4200bc7" +dependencies = [ + "arc-swap", + "log", + "pyo3", +] + [[package]] name = "pyo3-macros" version = "0.23.5" @@ -2923,7 +2940,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2936,7 +2953,7 @@ dependencies = [ "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -2972,7 +2989,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", ] @@ -2991,7 +3008,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.11", + "thiserror 2.0.12", "tinyvec", "tracing", "web-time", @@ -3013,9 +3030,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" dependencies = [ "proc-macro2", ] @@ -3044,8 +3061,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.2", - "zerocopy 0.8.20", + "rand_core 0.9.3", + "zerocopy 0.8.21", ] [[package]] @@ -3065,7 +3082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.2", + "rand_core 0.9.3", ] [[package]] @@ -3079,12 +3096,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a509b1a2ffbe92afab0e55c8fd99dea1c280e8171bd2d88682bb20bc41cbc2c" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.1", - "zerocopy 0.8.20", ] [[package]] @@ -3115,31 +3131,31 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" +checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] name = "ref-cast" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3360,7 +3376,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "errno", "libc", "linux-raw-sys", @@ -3476,7 +3492,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "core-foundation", "core-foundation-sys", "libc", @@ -3522,14 +3538,14 @@ checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "serde_json" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "indexmap", "itoa", @@ -3540,9 +3556,9 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" dependencies = [ "itoa", "serde", @@ -3641,7 +3657,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3691,7 +3707,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stac" version = "0.12.0" -source = "git+https://github.com/stac-utils/stac-rs#85f008ab30b4c5c402ce16382cca5abbf7770055" +source = "git+https://github.com/stac-utils/stac-rs?branch=optional-tracing-cli#d3b89daebe52fc74017f68b8ac3a6c680ac0f964" dependencies = [ "arrow-array", "arrow-cast", @@ -3713,7 +3729,7 @@ dependencies = [ "serde", "serde_json", "stac-derive", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", "url", @@ -3722,7 +3738,7 @@ dependencies = [ [[package]] name = "stac-api" version = "0.7.1" -source = "git+https://github.com/stac-utils/stac-rs#85f008ab30b4c5c402ce16382cca5abbf7770055" +source = "git+https://github.com/stac-utils/stac-rs?branch=optional-tracing-cli#d3b89daebe52fc74017f68b8ac3a6c680ac0f964" dependencies = [ "async-stream", "chrono", @@ -3739,7 +3755,7 @@ dependencies = [ "serde_urlencoded", "stac", "stac-derive", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", "tracing", "url", @@ -3748,7 +3764,7 @@ dependencies = [ [[package]] name = "stac-cli" version = "0.5.3" -source = "git+https://github.com/stac-utils/stac-rs#85f008ab30b4c5c402ce16382cca5abbf7770055" +source = "git+https://github.com/stac-utils/stac-rs?branch=optional-tracing-cli#d3b89daebe52fc74017f68b8ac3a6c680ac0f964" dependencies = [ "anyhow", "axum", @@ -3766,16 +3782,16 @@ dependencies = [ [[package]] name = "stac-derive" version = "0.2.0" -source = "git+https://github.com/stac-utils/stac-rs#85f008ab30b4c5c402ce16382cca5abbf7770055" +source = "git+https://github.com/stac-utils/stac-rs?branch=optional-tracing-cli#d3b89daebe52fc74017f68b8ac3a6c680ac0f964" dependencies = [ "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "stac-duckdb" version = "0.1.1" -source = "git+https://github.com/stac-utils/stac-rs#85f008ab30b4c5c402ce16382cca5abbf7770055" +source = "git+https://github.com/stac-utils/stac-rs?branch=optional-tracing-cli#d3b89daebe52fc74017f68b8ac3a6c680ac0f964" dependencies = [ "arrow", "chrono", @@ -3787,13 +3803,13 @@ dependencies = [ "serde_json", "stac", "stac-api", - "thiserror 2.0.11", + "thiserror 2.0.12", ] [[package]] name = "stac-server" version = "0.3.4" -source = "git+https://github.com/stac-utils/stac-rs#85f008ab30b4c5c402ce16382cca5abbf7770055" +source = "git+https://github.com/stac-utils/stac-rs?branch=optional-tracing-cli#d3b89daebe52fc74017f68b8ac3a6c680ac0f964" dependencies = [ "axum", "bb8", @@ -3809,7 +3825,7 @@ dependencies = [ "stac", "stac-api", "stac-duckdb", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio-postgres", "tokio-postgres-rustls", "tower-http", @@ -3827,6 +3843,7 @@ dependencies = [ "pyo3", "pyo3-arrow", "pyo3-async-runtimes", + "pyo3-log", "pythonize", "serde", "serde_json", @@ -3834,7 +3851,7 @@ dependencies = [ "stac-api", "stac-cli", "stac-duckdb", - "thiserror 2.0.11", + "thiserror 2.0.12", "tokio", ] @@ -3880,7 +3897,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3902,9 +3919,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.98" +version = "2.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" dependencies = [ "proc-macro2", "quote", @@ -3928,7 +3945,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -3965,11 +3982,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ - "thiserror-impl 2.0.11", + "thiserror-impl 2.0.12", ] [[package]] @@ -3980,18 +3997,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "thiserror-impl" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -4055,9 +4072,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] @@ -4086,7 +4103,7 @@ checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -4114,7 +4131,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -4160,9 +4177,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls", "tokio", @@ -4220,7 +4237,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", "bytes", "http", "http-body", @@ -4262,7 +4279,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -4525,7 +4542,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "wasm-bindgen-shared", ] @@ -4560,7 +4577,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4794,7 +4811,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.8.0", + "bitflags 2.9.0", ] [[package]] @@ -4898,7 +4915,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -4914,11 +4931,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde3bb8c68a8f3f1ed4ac9221aad6b10cece3e60a8e2ea54a6a2dec806d0084c" +checksum = "dcf01143b2dd5d134f11f545cf9f1431b13b749695cb33bcce051e7568f99478" dependencies = [ - "zerocopy-derive 0.8.20", + "zerocopy-derive 0.8.21", ] [[package]] @@ -4929,18 +4946,18 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] name = "zerocopy-derive" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea57037071898bf96a6da35fd626f4f27e9cee3ead2a6c703cf09d472b2e700" +checksum = "712c8386f4f4299382c9abee219bee7084f78fb939d88b6840fcc1320d5f6da2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -4960,7 +4977,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", "synstructure", ] @@ -4981,7 +4998,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] @@ -5003,7 +5020,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.98", + "syn 2.0.99", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index bf50926..fd0fa5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,18 +27,19 @@ serde_json = "1.0.138" stac = { features = [ "geoparquet-compression", "object-store-all", -], git = "https://github.com/stac-utils/stac-rs" } +], git = "https://github.com/stac-utils/stac-rs", branch = "optional-tracing-cli" } stac-api = { features = [ "client", "python", -], git = "https://github.com/stac-utils/stac-rs" } +], git = "https://github.com/stac-utils/stac-rs", branch = "optional-tracing-cli" } stac-cli = { git = "https://github.com/stac-utils/stac-rs", features = [ "pgstac", "duckdb", -] } -stac-duckdb = { git = "https://github.com/stac-utils/stac-rs" } +], branch = "optional-tracing-cli" } +stac-duckdb = { git = "https://github.com/stac-utils/stac-rs", branch = "optional-tracing-cli" } thiserror = "2.0.11" tokio = { version = "1.43.0", features = ["rt-multi-thread"] } +pyo3-log = "0.12.1" [patch.crates-io] duckdb = { git = "https://github.com/duckdb/duckdb-rs", rev = "5eeb1f01c278790ce1e2d24045f0096e9e2528e4" } diff --git a/src/cli.rs b/src/cli.rs index c18825f..8cea8b9 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -15,7 +15,7 @@ pub fn main(py: Python<'_>) -> PyResult { .build() .unwrap() .block_on(async { - match args.run().await { + match args.run(false).await { Ok(()) => 0, Err(err) => { eprintln!("ERROR: {}", err); diff --git a/src/lib.rs b/src/lib.rs index f491d5d..5fd505a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![deny(unused_crate_dependencies)] +#![warn(unused_crate_dependencies)] mod arrow; mod cli; @@ -8,6 +8,7 @@ mod migrate; mod read; mod search; mod version; +mod walk; mod write; use error::Error; @@ -17,6 +18,8 @@ type Result = std::result::Result; #[pymodule] fn stacrs(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { + pyo3_log::init(); + m.add("StacrsError", py.get_type::())?; m.add_class::()?; @@ -30,6 +33,7 @@ fn stacrs(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(search::search, m)?)?; m.add_function(wrap_pyfunction!(search::search_to, m)?)?; m.add_function(wrap_pyfunction!(version::version, m)?)?; + m.add_function(wrap_pyfunction!(walk::walk, m)?)?; m.add_function(wrap_pyfunction!(write::write, m)?)?; Ok(()) diff --git a/src/read.rs b/src/read.rs index 86f7b21..c6bce66 100644 --- a/src/read.rs +++ b/src/read.rs @@ -1,14 +1,15 @@ use crate::{Error, Json}; use pyo3::{pyfunction, types::PyAny, Bound, PyResult, Python}; -use stac::{Format, Value}; +use stac::{Format, Link, Links, SelfHref, Value}; #[pyfunction] -#[pyo3(signature = (href, *, format=None, options=None))] +#[pyo3(signature = (href, *, format=None, options=None, set_self_link=true))] pub fn read( py: Python<'_>, href: String, format: Option, options: Option>, + set_self_link: bool, ) -> PyResult> { let format = format .and_then(|f| f.parse::().ok()) @@ -16,10 +17,15 @@ pub fn read( .unwrap_or_default(); let options = options.unwrap_or_default(); pyo3_async_runtimes::tokio::future_into_py(py, async move { - let value = format + let mut value = format .get_opts::(href, options) .await .map_err(Error::from)?; + if set_self_link { + if let Some(href) = value.self_href().cloned() { + value.set_link(Link::self_(href)); + } + } Ok(Json(value)) }) } diff --git a/src/walk.rs b/src/walk.rs new file mode 100644 index 0000000..04e0bf3 --- /dev/null +++ b/src/walk.rs @@ -0,0 +1,55 @@ +use crate::{Error, Json, Result}; +use pyo3::{ + exceptions::PyStopAsyncIteration, pyclass, pyfunction, pymethods, types::PyDict, Bound, Py, + PyAny, PyResult, Python, +}; +use stac::{Container, Item, Links, Node, SelfHref, Value}; +use std::collections::VecDeque; +use std::sync::Arc; +use tokio::sync::Mutex; + +#[pyfunction] +pub fn walk(container: Bound<'_, PyDict>) -> Result { + let mut value: Value = pythonize::depythonize(&container)?; + if let Some(link) = value.link("self").cloned() { + *value.self_href_mut() = Some(link.href); + } + let container: Container = value.try_into()?; + let node = Node::from(container); + let mut walks = VecDeque::new(); + walks.push_back(node); + Ok(Walk(Arc::new(Mutex::new(walks)))) +} + +#[pyclass] +pub struct Walk(Arc>>); + +#[pymethods] +impl Walk { + fn __aiter__(slf: Py) -> Py { + slf + } + + fn __anext__<'py>(&self, py: Python<'py>) -> PyResult> { + let nodes = self.0.clone(); + pyo3_async_runtimes::tokio::future_into_py(py, async move { next_walk(nodes).await }) + } +} + +type WalkStep = (Value, Vec, VecDeque); + +async fn next_walk(nodes: Arc>>) -> PyResult> { + let mut nodes = nodes.lock().await; + if let Some(node) = nodes.pop_front() { + let mut node = node.resolve().await.map_err(Error::from)?; + let items = std::mem::take(&mut node.items); + let mut children = Vec::with_capacity(node.children.len()); + for child in node.children { + children.push(child.value.clone()); + nodes.push_back(child); + } + Ok(Json((node.value.into(), children, items))) + } else { + Err(PyStopAsyncIteration::new_err("done walking")) + } +} diff --git a/stacrs.pyi b/stacrs.pyi index 139a5af..c04f81b 100644 --- a/stacrs.pyi +++ b/stacrs.pyi @@ -1,4 +1,4 @@ -from typing import Any, Optional, Tuple +from typing import Any, AsyncIterator, Optional, Tuple import arro3.core @@ -198,16 +198,18 @@ async def read( *, format: str | None = None, options: list[tuple[str, str]] | None = None, + set_self_link: bool = True, ) -> dict[str, Any]: """ Reads STAC from a href. Args: - href (str): The href to write to - format (str | None): The input format. If not provided, will be inferred + href: The href to write to + format: The input format. If not provided, will be inferred from the href's extension. - options (list[tuple[str, str]] | None): Options for configuring an + options: Options for configuring an object store, e.g. your AWS credentials. + set_self_link: If True, set the `self` link to the value of `href`. Returns: The STAC value @@ -388,6 +390,22 @@ async def search_to( ... ) """ +def walk( + container: dict[str, Any], +) -> AsyncIterator[tuple[dict[str, Any], list[dict[str, Any]], list[dict[str, Any]]]]: + """Recursively walks a STAC catalog or collection breadth-first. + + Args: + container: A STAC catalog or collection. + + Yields: + A three-tuple of the container, its children, and its items. + + Examples: + >>> async for container, children, items in stacrs.walk(catalog): + ... ... + """ + async def write( href: str, value: dict[str, Any] | list[dict[str, Any]], diff --git a/tests/test_walk.py b/tests/test_walk.py new file mode 100644 index 0000000..efbe7e6 --- /dev/null +++ b/tests/test_walk.py @@ -0,0 +1,15 @@ +from pathlib import Path + +import stacrs + + +async def test_walk(examples: Path) -> None: + all_children = [] + all_items = [] + catalog = await stacrs.read(str(examples / "catalog.json")) + async for _, children, items in stacrs.walk(catalog): + all_children.extend(children) + all_items.extend(items) + + assert len(all_children) == 3 + assert len(all_items) == 2