diff --git a/CHANGELOG.md b/CHANGELOG.md index 6008882..163fa33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 0.27.0 - 2025-01-21 + +### Breaking changes +- Updated enumerations for unreleased US equities datasets and publishers + +### Enhancements +- Added new venue `EQUS` for consolidated US equities +- Added new dataset `EQUS.MINI` and new publishers `EQUS.MINI.EQUS` and `XNYS.TRADES.EQUS` +- Upgraded `pyo3` version to 0.23.4 with improved support for Python 3.13 + +### Bug fixes +- Fixed export of `InstrumentDefMsgV3` to Python + ## 0.26.0 - 2025-01-07 ### Enhancements diff --git a/Cargo.lock b/Cargo.lock index 8531424..6edb6d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,19 +67,20 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys", ] [[package]] name = "anyhow" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "assert_cmd" @@ -134,15 +135,15 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "bstr" -version = "1.11.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "regex-automata", @@ -168,16 +169,16 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.90", + "syn 2.0.96", "tempfile", "toml", ] [[package]] name = "cc" -version = "1.2.3" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b" dependencies = [ "jobserver", "libc", @@ -192,9 +193,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -202,9 +203,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -215,14 +216,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -260,7 +261,7 @@ dependencies = [ [[package]] name = "databento-dbn" -version = "0.26.0" +version = "0.27.0" dependencies = [ "dbn", "pyo3", @@ -271,7 +272,7 @@ dependencies = [ [[package]] name = "dbn" -version = "0.26.0" +version = "0.27.0" dependencies = [ "async-compression", "csv", @@ -293,7 +294,7 @@ dependencies = [ [[package]] name = "dbn-c" -version = "0.26.0" +version = "0.27.0" dependencies = [ "anyhow", "cbindgen", @@ -303,7 +304,7 @@ dependencies = [ [[package]] name = "dbn-cli" -version = "0.26.0" +version = "0.27.0" dependencies = [ "anyhow", "assert_cmd", @@ -318,14 +319,14 @@ dependencies = [ [[package]] name = "dbn-macros" -version = "0.26.0" +version = "0.27.0" dependencies = [ "csv", "dbn", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", "trybuild", ] @@ -381,9 +382,9 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "float-cmp" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" dependencies = [ "num-traits", ] @@ -444,7 +445,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -483,6 +484,17 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.31.1" @@ -491,9 +503,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" @@ -562,21 +574,21 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" @@ -604,9 +616,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -650,14 +662,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -670,9 +682,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -700,9 +712,9 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "predicates" -version = "3.1.2" +version = "3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" dependencies = [ "anstyle", "difflib", @@ -714,15 +726,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" [[package]] name = "predicates-tree" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" dependencies = [ "predicates-core", "termtree", @@ -739,18 +751,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" -version = "0.22.6" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f402062616ab18202ae8319da13fa4279883a2b8a9d9f83f20dbade813ce1884" +checksum = "57fe09249128b3173d092de9523eaa75136bf7ba85e0d69eca241c7939c933cc" dependencies = [ "cfg-if", "indoc", @@ -766,9 +778,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.22.6" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b14b5775b5ff446dd1056212d778012cbe8a0fbffd368029fd9e25b514479c38" +checksum = "1cd3927b5a78757a0d71aa9dff669f903b1eb64b54142a9bd9f757f8fde65fd7" dependencies = [ "once_cell", "target-lexicon", @@ -776,9 +788,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.22.6" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab5bcf04a2cdcbb50c7d6105de943f543f9ed92af55818fd17b660390fc8636" +checksum = "dab6bb2102bd8f991e7749f130a70d05dd557613e39ed2deeee8e9ca0c4d548d" dependencies = [ "libc", "pyo3-build-config", @@ -786,34 +798,34 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.22.6" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fd24d897903a9e6d80b968368a34e1525aeb719d568dba8b3d4bfa5dc67d453" +checksum = "91871864b353fd5ffcb3f91f2f703a22a9797c91b9ab497b1acac7b07ae509c7" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "pyo3-macros-backend" -version = "0.22.6" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c011a03ba1e50152b4b394b479826cad97e7a21eb52df179cd91ac411cbfbe" +checksum = "43abc3b80bc20f3facd86cd3c60beed58c3e2aa26213f3cda368de39c60a27e4" dependencies = [ "heck 0.5.0", "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -879,7 +891,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.90", + "syn 2.0.96", "unicode-ident", ] @@ -900,9 +912,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags", "errno", @@ -913,9 +925,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -925,35 +937,35 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -1010,7 +1022,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1026,9 +1038,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -1049,12 +1061,13 @@ checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", "windows-sys", @@ -1081,28 +1094,28 @@ dependencies = [ [[package]] name = "termtree" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" [[package]] name = "thiserror" -version = "2.0.6" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec2a1820ebd077e2b90c4df007bebf344cd394098a13c563957d0afc83ea47" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.6" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65750cab40f4ff1929fb1ba509e9914eb756131cef4210da8d5d700d26f6312" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1138,9 +1151,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -1150,13 +1163,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.96", ] [[package]] @@ -1256,6 +1269,12 @@ dependencies = [ "libc", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "winapi-util" version = "0.1.9" @@ -1340,9 +1359,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 5120564..18a4358 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ resolver = "2" [workspace.package] authors = ["Databento "] edition = "2021" -version = "0.26.0" +version = "0.27.0" documentation = "https://databento.com/docs" repository = "https://github.com/databento/dbn" license = "Apache-2.0" @@ -19,8 +19,8 @@ license = "Apache-2.0" [workspace.dependencies] anyhow = "1.0.94" csv = "1.3" -pyo3 = "0.22.6" -pyo3-build-config = "0.22.6" +pyo3 = "0.23.4" +pyo3-build-config = "0.23.4" rstest = "0.23.0" serde = { version = "1.0", features = ["derive"] } time = ">=0.3.35" diff --git a/python/pyproject.toml b/python/pyproject.toml index 85db92d..caa557f 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "databento-dbn" -version = "0.26.0" +version = "0.27.0" description = "Python bindings for encoding and decoding Databento Binary Encoding (DBN)" authors = ["Databento "] license = "Apache-2.0" @@ -17,7 +17,7 @@ build-backend = "maturin" [project] name = "databento-dbn" -version = "0.26.0" +version = "0.27.0" authors = [ { name = "Databento", email = "support@databento.com" } ] diff --git a/python/src/dbn_decoder.rs b/python/src/dbn_decoder.rs index 4b728c5..f23d687 100644 --- a/python/src/dbn_decoder.rs +++ b/python/src/dbn_decoder.rs @@ -1,6 +1,6 @@ use std::io::{self, Write}; -use pyo3::prelude::*; +use pyo3::{prelude::*, IntoPyObjectExt}; use dbn::{ decode::dbn::{MetadataDecoder, RecordDecoder}, @@ -59,7 +59,10 @@ impl DbnDecoder { self.input_version = metadata.version; self.ts_out = metadata.ts_out; metadata.upgrade(self.upgrade_policy); - Python::with_gil(|py| recs.push(metadata.into_py(py))); + Python::with_gil(|py| -> PyResult<()> { + recs.push(metadata.into_py_any(py)?); + Ok(()) + })?; self.has_decoded_metadata = true; } Err(err) => { @@ -84,12 +87,11 @@ impl DbnDecoder { while let Some(rec) = decoder.decode_ref()? { // Bug in clippy generates an error here. trivial_copy feature isn't enabled, // but clippy thinks these records are `Copy` - fn push_rec>>( - rec: &R, - py: Python, - recs: &mut Vec>, - ) { - recs.push(rec.clone().into_py(py)) + fn push_rec<'py, R>(rec: &R, py: Python<'py>, recs: &mut Vec) + where + R: Clone + HasRType + IntoPyObject<'py>, + { + recs.push(rec.clone().into_py_any(py).unwrap()); } // Safety: It's safe to cast to `WithTsOut` because we're passing in the `ts_out` @@ -232,7 +234,7 @@ mod tests { fn test_dbn_decoder() { setup(); Python::with_gil(|py| { - let path = PyString::new_bound( + let path = PyString::new( py, concat!( env!("CARGO_MANIFEST_DIR"), diff --git a/python/src/encode.rs b/python/src/encode.rs index b1caa0d..2b4cc69 100644 --- a/python/src/encode.rs +++ b/python/src/encode.rs @@ -1,10 +1,11 @@ use std::{ io::{self, Read, Seek}, num::NonZeroU64, + sync::Mutex, }; use dbn::encode::dbn::MetadataEncoder; -use pyo3::{exceptions::PyTypeError, intern, prelude::*, types::PyBytes}; +use pyo3::{exceptions::PyTypeError, intern, prelude::*, types::PyBytes, IntoPyObjectExt}; /// Updates existing fields that have already been written to the given file. #[pyfunction] @@ -30,7 +31,7 @@ pub fn update_encoded_metadata( /// A Python object that implements the Python file interface. pub struct PyFileLike { - inner: PyObject, + inner: Mutex, } impl<'py> FromPyObject<'py> for PyFileLike { @@ -52,7 +53,9 @@ impl<'py> FromPyObject<'py> for PyFileLike { "object is missing a `seek()` method".to_owned(), )); } - Ok(PyFileLike { inner: obj }) + Ok(PyFileLike { + inner: Mutex::new(obj), + }) }) } } @@ -62,7 +65,9 @@ impl io::Read for PyFileLike { Python::with_gil(|py| { let bytes: Vec = self .inner - .call_method_bound(py, intern!(py, "read"), (buf.len(),), None) + .lock() + .unwrap() + .call_method(py, intern!(py, "read"), (buf.len(),), None) .map_err(py_to_rs_io_err)? .extract(py)?; buf[..bytes.len()].clone_from_slice(&bytes); @@ -74,10 +79,12 @@ impl io::Read for PyFileLike { impl io::Write for PyFileLike { fn write(&mut self, buf: &[u8]) -> Result { Python::with_gil(|py| { - let bytes = PyBytes::new_bound(py, buf).to_object(py); + let bytes = PyBytes::new(py, buf); let number_bytes_written = self .inner - .call_method_bound(py, intern!(py, "write"), (bytes,), None) + .lock() + .unwrap() + .call_method(py, intern!(py, "write"), (bytes,), None) .map_err(py_to_rs_io_err)?; number_bytes_written.extract(py).map_err(py_to_rs_io_err) @@ -87,7 +94,9 @@ impl io::Write for PyFileLike { fn flush(&mut self) -> Result<(), io::Error> { Python::with_gil(|py| { self.inner - .call_method_bound(py, intern!(py, "flush"), (), None) + .lock() + .unwrap() + .call_method(py, intern!(py, "flush"), (), None) .map_err(py_to_rs_io_err)?; Ok(()) @@ -106,7 +115,9 @@ impl io::Seek for PyFileLike { let new_position = self .inner - .call_method_bound(py, intern!(py, "seek"), (offset, whence), None) + .lock() + .unwrap() + .call_method(py, intern!(py, "seek"), (offset, whence), None) .map_err(py_to_rs_io_err)?; new_position.extract(py).map_err(py_to_rs_io_err) @@ -116,10 +127,10 @@ impl io::Seek for PyFileLike { fn py_to_rs_io_err(e: PyErr) -> io::Error { Python::with_gil(|py| { - let e_as_object: PyObject = e.into_py(py); + let e_as_object = e.into_bound_py_any(py).unwrap(); - match e_as_object.call_method_bound(py, intern!(py, "__str__"), (), None) { - Ok(repr) => match repr.extract::(py) { + match e_as_object.call_method(intern!(py, "__str__"), (), None) { + Ok(repr) => match repr.extract::() { Ok(s) => io::Error::new(io::ErrorKind::Other, s), Err(_e) => io::Error::new(io::ErrorKind::Other, "An unknown error has occurred"), }, diff --git a/python/src/lib.rs b/python/src/lib.rs index d778ea7..926001a 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -3,7 +3,7 @@ use pyo3::{prelude::*, wrap_pyfunction, PyClass}; use dbn::{ - compat::{ErrorMsgV1, InstrumentDefMsgV1, SymbolMappingMsgV1, SystemMsgV1}, + compat::{ErrorMsgV1, InstrumentDefMsgV1, InstrumentDefMsgV3, SymbolMappingMsgV1, SystemMsgV1}, flags, python::{DBNError, EnumIterator}, Action, BboMsg, BidAskPair, CbboMsg, Cmbp1Msg, Compression, ConsolidatedBidAskPair, Encoding, @@ -30,7 +30,7 @@ fn databento_dbn(_py: Python<'_>, m: &Bound) -> PyResult<()> { } // all functions exposed to Python need to be added here m.add_wrapped(wrap_pyfunction!(encode::update_encoded_metadata))?; - m.add("DBNError", m.py().get_type_bound::())?; + m.add("DBNError", m.py().get_type::())?; checked_add_class::(m)?; checked_add_class::(m)?; checked_add_class::(m)?; @@ -48,6 +48,7 @@ fn databento_dbn(_py: Python<'_>, m: &Bound) -> PyResult<()> { checked_add_class::(m)?; checked_add_class::(m)?; checked_add_class::(m)?; + checked_add_class::(m)?; checked_add_class::(m)?; checked_add_class::(m)?; checked_add_class::(m)?; @@ -98,6 +99,7 @@ mod tests { use std::sync::Once; use dbn::enums::SType; + use pyo3::ffi::c_str; use super::*; @@ -156,8 +158,9 @@ assert metadata.ts_out is False"# fn test_dbn_decoder_metadata_error() { setup(); Python::with_gil(|py| { - py.run_bound( - r#"from _lib import DBNDecoder + py.run( + c_str!( + r#"from _lib import DBNDecoder decoder = DBNDecoder() try: @@ -166,7 +169,8 @@ try: assert False except Exception: pass -"#, +"# + ), None, None, ) diff --git a/python/src/transcoder.rs b/python/src/transcoder.rs index 00a77a7..b89bf7f 100644 --- a/python/src/transcoder.rs +++ b/python/src/transcoder.rs @@ -3,7 +3,7 @@ use std::{ collections::HashMap, io::{self, BufWriter, Write}, - sync::Arc, + sync::{Arc, Mutex}, }; use dbn::{ @@ -16,12 +16,16 @@ use dbn::{ Compression, Encoding, PitSymbolMap, RType, Record, RecordRef, Schema, SymbolIndex, TsSymbolMap, VersionUpgradePolicy, }; -use pyo3::{exceptions::PyValueError, prelude::*, types::PyDate}; +use pyo3::{ + exceptions::PyValueError, + prelude::*, + types::{PyBytes, PyDate}, +}; use crate::encode::PyFileLike; #[pyclass(module = "databento_dbn")] -pub struct Transcoder(Box); +pub struct Transcoder(Mutex>); pub type PySymbolIntervalMap<'py> = HashMap, Bound<'py, PyDate>, String)>>; @@ -73,7 +77,7 @@ impl Transcoder { } else { None }; - Ok(Self(match encoding { + Ok(Self(Mutex::new(match encoding { Encoding::Dbn => Box::new(Inner::<{ Encoding::Dbn as u8 }>::new( file, compression, @@ -113,19 +117,19 @@ impl Transcoder { input_version, upgrade_policy, )?), - })) + }))) } fn write(&mut self, bytes: &[u8]) -> PyResult<()> { - self.0.write(bytes) + self.0.lock().unwrap().write(bytes) } fn flush(&mut self) -> PyResult<()> { - self.0.flush() + self.0.lock().unwrap().flush() } - fn buffer(&self) -> &[u8] { - self.0.buffer() + fn buffer<'py>(&self, py: Python<'py>) -> Bound<'py, PyBytes> { + PyBytes::new(py, self.0.lock().unwrap().buffer()) } } @@ -471,7 +475,7 @@ mod tests { impl Transcoder { fn downcast_unchecked(&self) -> &Inner { unsafe { - let ptr = &*self.0 as *const (dyn Transcode + Send); + let ptr = self.0.lock().unwrap().as_ref() as *const (dyn Transcode + Send); ptr.cast::>().as_ref().unwrap() } } @@ -531,7 +535,9 @@ mod tests { let metadata_pos = encoder.get_ref().len(); let rec = ErrorMsg::new(1680708278000000000, "This is a test", true); encoder.encode_record(&rec).unwrap(); - assert!(target.buffer().is_empty()); + Python::with_gil(|py| { + assert!(target.buffer(py).is_empty().unwrap()); + }); let record_pos = encoder.get_ref().len(); // write record byte by byte for i in metadata_pos..record_pos { @@ -540,11 +546,15 @@ mod tests { if i == record_pos - 1 { break; } - assert_eq!(target.buffer().len(), i + 1 - metadata_pos); + Python::with_gil(|py| { + assert_eq!(target.buffer(py).len().unwrap(), i + 1 - metadata_pos); + }); } // writing the remainder of the record should have the transcoder // transcode the record to the output file - assert!(target.buffer().is_empty()); + Python::with_gil(|py| { + assert!(target.buffer(py).is_empty().unwrap()); + }); assert_eq!(record_pos - metadata_pos, std::mem::size_of_val(&rec)); target.flush().unwrap(); let output = output_buf.lock().unwrap(); @@ -605,7 +615,9 @@ mod tests { encoder.encode_record(&rec1).unwrap(); let rec1_pos = encoder.get_ref().len(); encoder.encode_record(&rec2).unwrap(); - assert!(transcoder.buffer().is_empty()); + Python::with_gil(|py| { + assert!(transcoder.buffer(py).is_empty().unwrap()); + }); // Write first record and part of second transcoder .write(&encoder.get_ref()[metadata_pos..rec1_pos + 4]) @@ -720,7 +732,9 @@ mod tests { ); encoder.encode_record(&rec1).unwrap(); encoder.encode_record(&rec2).unwrap(); - assert!(transcoder.buffer().is_empty()); + Python::with_gil(|py| { + assert!(transcoder.buffer(py).is_empty().unwrap()); + }); // Write first record and part of second transcoder.write(encoder.get_ref()).unwrap(); transcoder.flush().unwrap(); @@ -849,7 +863,9 @@ mod tests { .unwrap(); encoder.encode_record(&rec1).unwrap(); encoder.encode_record(&rec2).unwrap(); - assert!(transcoder.buffer().is_empty()); + Python::with_gil(|py| { + assert!(transcoder.buffer(py).is_empty().unwrap()); + }); // Write first record and part of second transcoder.write(encoder.get_ref()).unwrap(); transcoder.flush().unwrap(); diff --git a/rust/dbn-cli/Cargo.toml b/rust/dbn-cli/Cargo.toml index 4dffa8a..a66c28c 100644 --- a/rust/dbn-cli/Cargo.toml +++ b/rust/dbn-cli/Cargo.toml @@ -16,7 +16,7 @@ name = "dbn" path = "src/main.rs" [dependencies] -dbn = { path = "../dbn", version = "=0.26.0", default-features = false } +dbn = { path = "../dbn", version = "=0.27.0", default-features = false } anyhow = { workspace = true } clap = { version = "4.5", features = ["derive", "wrap_help"] } diff --git a/rust/dbn/Cargo.toml b/rust/dbn/Cargo.toml index d36ddb1..589475f 100644 --- a/rust/dbn/Cargo.toml +++ b/rust/dbn/Cargo.toml @@ -25,7 +25,7 @@ serde = ["dep:serde", "time/parsing", "time/serde"] trivial_copy = [] [dependencies] -dbn-macros = { version = "=0.26.0", path = "../dbn-macros" } +dbn-macros = { version = "=0.27.0", path = "../dbn-macros" } async-compression = { version = "0.4.18", features = ["tokio", "zstd"], optional = true } csv = { workspace = true } diff --git a/rust/dbn/src/metadata.rs b/rust/dbn/src/metadata.rs index 019f002..d192279 100644 --- a/rust/dbn/src/metadata.rs +++ b/rust/dbn/src/metadata.rs @@ -22,7 +22,7 @@ use crate::{ /// Information about the data contained in a DBN file or stream. DBN requires the /// Metadata to be included at the start of the encoded data. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "python", pyo3::pyclass(module = "databento_dbn"))] +#[cfg_attr(feature = "python", pyo3::pyclass(eq, module = "databento_dbn"))] #[cfg_attr(not(feature = "python"), derive(MockPyo3))] // bring `pyo3` attribute into scope pub struct Metadata { /// The DBN schema version number. Newly-encoded DBN files will use diff --git a/rust/dbn/src/publishers.rs b/rust/dbn/src/publishers.rs index 8288bdc..e354679 100644 --- a/rust/dbn/src/publishers.rs +++ b/rust/dbn/src/publishers.rs @@ -89,7 +89,7 @@ pub enum Venue { Ifeu = 38, /// ICE Endex Ndex = 39, - /// Databento Equities - Consolidated + /// Databento US Equities - Consolidated Dbeq = 40, /// MIAX Sapphire Sphr = 41, @@ -103,10 +103,12 @@ pub enum Venue { Asmt = 45, /// IntelligentCross ASPEN Inverted Aspi = 46, + /// Databento US Equities - Consolidated + Equs = 47, } /// The number of Venue variants. -pub const VENUE_COUNT: usize = 46; +pub const VENUE_COUNT: usize = 47; impl Venue { /// Convert a Venue to its `str` representation. @@ -158,6 +160,7 @@ impl Venue { Self::Aspn => "ASPN", Self::Asmt => "ASMT", Self::Aspi => "ASPI", + Self::Equs => "EQUS", } } } @@ -225,6 +228,7 @@ impl std::str::FromStr for Venue { "ASPN" => Ok(Self::Aspn), "ASMT" => Ok(Self::Asmt), "ASPI" => Ok(Self::Aspi), + "EQUS" => Ok(Self::Equs), _ => Err(Error::conversion::(s)), } } @@ -275,14 +279,14 @@ pub enum Dataset { FinyTrades = 18, /// OPRA Binary OpraPillar = 19, - /// Databento Equities Basic + /// Databento US Equities Basic DbeqBasic = 20, /// NYSE Arca Integrated ArcxPillar = 21, /// IEX TOPS IexgTops = 22, - /// Databento Equities Plus - DbeqPlus = 23, + /// Databento US Equities Plus + EqusPlus = 23, /// NYSE BBO XnysBbo = 24, /// NYSE Trades @@ -295,20 +299,22 @@ pub enum Dataset { IfeuImpact = 28, /// ICE Endex iMpact NdexImpact = 29, - /// Databento Equities Max - DbeqMax = 30, + /// Databento US Equities (All Feeds) + EqusAll = 30, /// Nasdaq Basic (NLS and QBBO) XnasBasic = 31, - /// Databento Equities Summary - DbeqSummary = 32, - /// NYSE National BBO and Trades - XcisBbotrades = 33, - /// NYSE BBO and Trades - XnysBbotrades = 34, + /// Databento US Equities Summary + EqusSummary = 32, + /// NYSE National Trades and BBO + XcisTradesbbo = 33, + /// NYSE Trades and BBO + XnysTradesbbo = 34, + /// Databento US Equities Mini + EqusMini = 35, } /// The number of Dataset variants. -pub const DATASET_COUNT: usize = 34; +pub const DATASET_COUNT: usize = 35; impl Dataset { /// Convert a Dataset to its `str` representation. @@ -338,18 +344,19 @@ impl Dataset { Self::DbeqBasic => "DBEQ.BASIC", Self::ArcxPillar => "ARCX.PILLAR", Self::IexgTops => "IEXG.TOPS", - Self::DbeqPlus => "DBEQ.PLUS", + Self::EqusPlus => "EQUS.PLUS", Self::XnysBbo => "XNYS.BBO", Self::XnysTrades => "XNYS.TRADES", Self::XnasQbbo => "XNAS.QBBO", Self::XnasNls => "XNAS.NLS", Self::IfeuImpact => "IFEU.IMPACT", Self::NdexImpact => "NDEX.IMPACT", - Self::DbeqMax => "DBEQ.MAX", + Self::EqusAll => "EQUS.ALL", Self::XnasBasic => "XNAS.BASIC", - Self::DbeqSummary => "DBEQ.SUMMARY", - Self::XcisBbotrades => "XCIS.BBOTRADES", - Self::XnysBbotrades => "XNYS.BBOTRADES", + Self::EqusSummary => "EQUS.SUMMARY", + Self::XcisTradesbbo => "XCIS.TRADESBBO", + Self::XnysTradesbbo => "XNYS.TRADESBBO", + Self::EqusMini => "EQUS.MINI", } } } @@ -395,18 +402,19 @@ impl std::str::FromStr for Dataset { "DBEQ.BASIC" => Ok(Self::DbeqBasic), "ARCX.PILLAR" => Ok(Self::ArcxPillar), "IEXG.TOPS" => Ok(Self::IexgTops), - "DBEQ.PLUS" => Ok(Self::DbeqPlus), + "EQUS.PLUS" => Ok(Self::EqusPlus), "XNYS.BBO" => Ok(Self::XnysBbo), "XNYS.TRADES" => Ok(Self::XnysTrades), "XNAS.QBBO" => Ok(Self::XnasQbbo), "XNAS.NLS" => Ok(Self::XnasNls), "IFEU.IMPACT" => Ok(Self::IfeuImpact), "NDEX.IMPACT" => Ok(Self::NdexImpact), - "DBEQ.MAX" => Ok(Self::DbeqMax), + "EQUS.ALL" => Ok(Self::EqusAll), "XNAS.BASIC" => Ok(Self::XnasBasic), - "DBEQ.SUMMARY" => Ok(Self::DbeqSummary), - "XCIS.BBOTRADES" => Ok(Self::XcisBbotrades), - "XNYS.BBOTRADES" => Ok(Self::XnysBbotrades), + "EQUS.SUMMARY" => Ok(Self::EqusSummary), + "XCIS.TRADESBBO" => Ok(Self::XcisTradesbbo), + "XNYS.TRADESBBO" => Ok(Self::XnysTradesbbo), + "EQUS.MINI" => Ok(Self::EqusMini), _ => Err(Error::conversion::(s)), } } @@ -511,72 +519,72 @@ pub enum Publisher { XnasQbboXnas = 46, /// Nasdaq Trades XnasNlsXnas = 47, - /// DBEQ Plus - NYSE Chicago - DbeqPlusXchi = 48, - /// DBEQ Plus - NYSE National - DbeqPlusXcis = 49, - /// DBEQ Plus - IEX - DbeqPlusIexg = 50, - /// DBEQ Plus - MIAX Pearl - DbeqPlusEprl = 51, - /// DBEQ Plus - Nasdaq - DbeqPlusXnas = 52, - /// DBEQ Plus - NYSE - DbeqPlusXnys = 53, - /// DBEQ Plus - FINRA/Nasdaq TRF Carteret - DbeqPlusFinn = 54, - /// DBEQ Plus - FINRA/NYSE TRF - DbeqPlusFiny = 55, - /// DBEQ Plus - FINRA/Nasdaq TRF Chicago - DbeqPlusFinc = 56, + /// Databento US Equities Plus - NYSE Chicago + EqusPlusXchi = 48, + /// Databento US Equities Plus - NYSE National + EqusPlusXcis = 49, + /// Databento US Equities Plus - IEX + EqusPlusIexg = 50, + /// Databento US Equities Plus - MIAX Pearl + EqusPlusEprl = 51, + /// Databento US Equities Plus - Nasdaq + EqusPlusXnas = 52, + /// Databento US Equities Plus - NYSE + EqusPlusXnys = 53, + /// Databento US Equities Plus - FINRA/Nasdaq TRF Carteret + EqusPlusFinn = 54, + /// Databento US Equities Plus - FINRA/NYSE TRF + EqusPlusFiny = 55, + /// Databento US Equities Plus - FINRA/Nasdaq TRF Chicago + EqusPlusFinc = 56, /// ICE Futures Europe (Commodities) IfeuImpactIfeu = 57, /// ICE Endex NdexImpactNdex = 58, - /// DBEQ Basic - Consolidated + /// Databento US Equities Basic - Consolidated DbeqBasicDbeq = 59, - /// DBEQ Plus - Consolidated - DbeqPlusDbeq = 60, + /// EQUS Plus - Consolidated + EqusPlusEqus = 60, /// OPRA - MIAX Sapphire OpraPillarSphr = 61, - /// DBEQ Max - NYSE Chicago - DbeqMaxXchi = 62, - /// DBEQ Max - NYSE National - DbeqMaxXcis = 63, - /// DBEQ Max - IEX - DbeqMaxIexg = 64, - /// DBEQ Max - MIAX Pearl - DbeqMaxEprl = 65, - /// DBEQ Max - Nasdaq - DbeqMaxXnas = 66, - /// DBEQ Max - NYSE - DbeqMaxXnys = 67, - /// DBEQ Max - FINRA/Nasdaq TRF Carteret - DbeqMaxFinn = 68, - /// DBEQ Max - FINRA/NYSE TRF - DbeqMaxFiny = 69, - /// DBEQ Max - FINRA/Nasdaq TRF Chicago - DbeqMaxFinc = 70, - /// DBEQ Max - CBOE BZX - DbeqMaxBats = 71, - /// DBEQ Max - CBOE BYX - DbeqMaxBaty = 72, - /// DBEQ Max - CBOE EDGA - DbeqMaxEdga = 73, - /// DBEQ Max - CBOE EDGX - DbeqMaxEdgx = 74, - /// DBEQ Max - Nasdaq BX - DbeqMaxXbos = 75, - /// DBEQ Max - Nasdaq PSX - DbeqMaxXpsx = 76, - /// DBEQ Max - MEMX - DbeqMaxMemx = 77, - /// DBEQ Max - NYSE American - DbeqMaxXase = 78, - /// DBEQ Max - NYSE Arca - DbeqMaxArcx = 79, - /// DBEQ Max - Long-Term Stock Exchange - DbeqMaxLtse = 80, + /// Databento US Equities (All Feeds) - NYSE Chicago + EqusAllXchi = 62, + /// Databento US Equities (All Feeds) - NYSE National + EqusAllXcis = 63, + /// Databento US Equities (All Feeds) - IEX + EqusAllIexg = 64, + /// Databento US Equities (All Feeds) - MIAX Pearl + EqusAllEprl = 65, + /// Databento US Equities (All Feeds) - Nasdaq + EqusAllXnas = 66, + /// Databento US Equities (All Feeds) - NYSE + EqusAllXnys = 67, + /// Databento US Equities (All Feeds) - FINRA/Nasdaq TRF Carteret + EqusAllFinn = 68, + /// Databento US Equities (All Feeds) - FINRA/NYSE TRF + EqusAllFiny = 69, + /// Databento US Equities (All Feeds) - FINRA/Nasdaq TRF Chicago + EqusAllFinc = 70, + /// Databento US Equities (All Feeds) - CBOE BZX + EqusAllBats = 71, + /// Databento US Equities (All Feeds) - CBOE BYX + EqusAllBaty = 72, + /// Databento US Equities (All Feeds) - CBOE EDGA + EqusAllEdga = 73, + /// Databento US Equities (All Feeds) - CBOE EDGX + EqusAllEdgx = 74, + /// Databento US Equities (All Feeds) - Nasdaq BX + EqusAllXbos = 75, + /// Databento US Equities (All Feeds) - Nasdaq PSX + EqusAllXpsx = 76, + /// Databento US Equities (All Feeds) - MEMX + EqusAllMemx = 77, + /// Databento US Equities (All Feeds) - NYSE American + EqusAllXase = 78, + /// Databento US Equities (All Feeds) - NYSE Arca + EqusAllArcx = 79, + /// Databento US Equities (All Feeds) - Long-Term Stock Exchange + EqusAllLtse = 80, /// Nasdaq Basic - Nasdaq XnasBasicXnas = 81, /// Nasdaq Basic - FINRA/Nasdaq TRF Carteret @@ -596,19 +604,23 @@ pub enum Publisher { /// Nasdaq Basic - Nasdaq PSX XnasBasicXpsx = 89, /// Databento Equities Summary - DbeqSummaryDbeq = 90, - /// NYSE National BBO and Trades - XcisBbotradesXcis = 91, - /// NYSE BBO and Trades - XnysBbotradesXnys = 92, + EqusSummaryEqus = 90, + /// NYSE National Trades and BBO + XcisTradesbboXcis = 91, + /// NYSE Trades and BBO + XnysTradesbboXnys = 92, /// Nasdaq Basic - Consolidated - XnasBasicDbeq = 93, - /// DBEQ Max - Consolidated - DbeqMaxDbeq = 94, + XnasBasicEqus = 93, + /// Databento US Equities (All Feeds) - Consolidated + EqusAllEqus = 94, + /// Databento US Equities Mini + EqusMiniEqus = 95, + /// NYSE Trades - Consolidated + XnysTradesEqus = 96, } /// The number of Publisher variants. -pub const PUBLISHER_COUNT: usize = 94; +pub const PUBLISHER_COUNT: usize = 96; impl Publisher { /// Convert a Publisher to its `str` representation. @@ -661,39 +673,39 @@ impl Publisher { Self::XnysTradesXnys => "XNYS.TRADES.XNYS", Self::XnasQbboXnas => "XNAS.QBBO.XNAS", Self::XnasNlsXnas => "XNAS.NLS.XNAS", - Self::DbeqPlusXchi => "DBEQ.PLUS.XCHI", - Self::DbeqPlusXcis => "DBEQ.PLUS.XCIS", - Self::DbeqPlusIexg => "DBEQ.PLUS.IEXG", - Self::DbeqPlusEprl => "DBEQ.PLUS.EPRL", - Self::DbeqPlusXnas => "DBEQ.PLUS.XNAS", - Self::DbeqPlusXnys => "DBEQ.PLUS.XNYS", - Self::DbeqPlusFinn => "DBEQ.PLUS.FINN", - Self::DbeqPlusFiny => "DBEQ.PLUS.FINY", - Self::DbeqPlusFinc => "DBEQ.PLUS.FINC", + Self::EqusPlusXchi => "EQUS.PLUS.XCHI", + Self::EqusPlusXcis => "EQUS.PLUS.XCIS", + Self::EqusPlusIexg => "EQUS.PLUS.IEXG", + Self::EqusPlusEprl => "EQUS.PLUS.EPRL", + Self::EqusPlusXnas => "EQUS.PLUS.XNAS", + Self::EqusPlusXnys => "EQUS.PLUS.XNYS", + Self::EqusPlusFinn => "EQUS.PLUS.FINN", + Self::EqusPlusFiny => "EQUS.PLUS.FINY", + Self::EqusPlusFinc => "EQUS.PLUS.FINC", Self::IfeuImpactIfeu => "IFEU.IMPACT.IFEU", Self::NdexImpactNdex => "NDEX.IMPACT.NDEX", Self::DbeqBasicDbeq => "DBEQ.BASIC.DBEQ", - Self::DbeqPlusDbeq => "DBEQ.PLUS.DBEQ", + Self::EqusPlusEqus => "EQUS.PLUS.EQUS", Self::OpraPillarSphr => "OPRA.PILLAR.SPHR", - Self::DbeqMaxXchi => "DBEQ.MAX.XCHI", - Self::DbeqMaxXcis => "DBEQ.MAX.XCIS", - Self::DbeqMaxIexg => "DBEQ.MAX.IEXG", - Self::DbeqMaxEprl => "DBEQ.MAX.EPRL", - Self::DbeqMaxXnas => "DBEQ.MAX.XNAS", - Self::DbeqMaxXnys => "DBEQ.MAX.XNYS", - Self::DbeqMaxFinn => "DBEQ.MAX.FINN", - Self::DbeqMaxFiny => "DBEQ.MAX.FINY", - Self::DbeqMaxFinc => "DBEQ.MAX.FINC", - Self::DbeqMaxBats => "DBEQ.MAX.BATS", - Self::DbeqMaxBaty => "DBEQ.MAX.BATY", - Self::DbeqMaxEdga => "DBEQ.MAX.EDGA", - Self::DbeqMaxEdgx => "DBEQ.MAX.EDGX", - Self::DbeqMaxXbos => "DBEQ.MAX.XBOS", - Self::DbeqMaxXpsx => "DBEQ.MAX.XPSX", - Self::DbeqMaxMemx => "DBEQ.MAX.MEMX", - Self::DbeqMaxXase => "DBEQ.MAX.XASE", - Self::DbeqMaxArcx => "DBEQ.MAX.ARCX", - Self::DbeqMaxLtse => "DBEQ.MAX.LTSE", + Self::EqusAllXchi => "EQUS.ALL.XCHI", + Self::EqusAllXcis => "EQUS.ALL.XCIS", + Self::EqusAllIexg => "EQUS.ALL.IEXG", + Self::EqusAllEprl => "EQUS.ALL.EPRL", + Self::EqusAllXnas => "EQUS.ALL.XNAS", + Self::EqusAllXnys => "EQUS.ALL.XNYS", + Self::EqusAllFinn => "EQUS.ALL.FINN", + Self::EqusAllFiny => "EQUS.ALL.FINY", + Self::EqusAllFinc => "EQUS.ALL.FINC", + Self::EqusAllBats => "EQUS.ALL.BATS", + Self::EqusAllBaty => "EQUS.ALL.BATY", + Self::EqusAllEdga => "EQUS.ALL.EDGA", + Self::EqusAllEdgx => "EQUS.ALL.EDGX", + Self::EqusAllXbos => "EQUS.ALL.XBOS", + Self::EqusAllXpsx => "EQUS.ALL.XPSX", + Self::EqusAllMemx => "EQUS.ALL.MEMX", + Self::EqusAllXase => "EQUS.ALL.XASE", + Self::EqusAllArcx => "EQUS.ALL.ARCX", + Self::EqusAllLtse => "EQUS.ALL.LTSE", Self::XnasBasicXnas => "XNAS.BASIC.XNAS", Self::XnasBasicFinn => "XNAS.BASIC.FINN", Self::XnasBasicFinc => "XNAS.BASIC.FINC", @@ -703,11 +715,13 @@ impl Publisher { Self::XnasNlsXpsx => "XNAS.NLS.XPSX", Self::XnasBasicXbos => "XNAS.BASIC.XBOS", Self::XnasBasicXpsx => "XNAS.BASIC.XPSX", - Self::DbeqSummaryDbeq => "DBEQ.SUMMARY.DBEQ", - Self::XcisBbotradesXcis => "XCIS.BBOTRADES.XCIS", - Self::XnysBbotradesXnys => "XNYS.BBOTRADES.XNYS", - Self::XnasBasicDbeq => "XNAS.BASIC.DBEQ", - Self::DbeqMaxDbeq => "DBEQ.MAX.DBEQ", + Self::EqusSummaryEqus => "EQUS.SUMMARY.EQUS", + Self::XcisTradesbboXcis => "XCIS.TRADESBBO.XCIS", + Self::XnysTradesbboXnys => "XNYS.TRADESBBO.XNYS", + Self::XnasBasicEqus => "XNAS.BASIC.EQUS", + Self::EqusAllEqus => "EQUS.ALL.EQUS", + Self::EqusMiniEqus => "EQUS.MINI.EQUS", + Self::XnysTradesEqus => "XNYS.TRADES.EQUS", } } @@ -761,39 +775,39 @@ impl Publisher { Self::XnysTradesXnys => Venue::Xnys, Self::XnasQbboXnas => Venue::Xnas, Self::XnasNlsXnas => Venue::Xnas, - Self::DbeqPlusXchi => Venue::Xchi, - Self::DbeqPlusXcis => Venue::Xcis, - Self::DbeqPlusIexg => Venue::Iexg, - Self::DbeqPlusEprl => Venue::Eprl, - Self::DbeqPlusXnas => Venue::Xnas, - Self::DbeqPlusXnys => Venue::Xnys, - Self::DbeqPlusFinn => Venue::Finn, - Self::DbeqPlusFiny => Venue::Finy, - Self::DbeqPlusFinc => Venue::Finc, + Self::EqusPlusXchi => Venue::Xchi, + Self::EqusPlusXcis => Venue::Xcis, + Self::EqusPlusIexg => Venue::Iexg, + Self::EqusPlusEprl => Venue::Eprl, + Self::EqusPlusXnas => Venue::Xnas, + Self::EqusPlusXnys => Venue::Xnys, + Self::EqusPlusFinn => Venue::Finn, + Self::EqusPlusFiny => Venue::Finy, + Self::EqusPlusFinc => Venue::Finc, Self::IfeuImpactIfeu => Venue::Ifeu, Self::NdexImpactNdex => Venue::Ndex, Self::DbeqBasicDbeq => Venue::Dbeq, - Self::DbeqPlusDbeq => Venue::Dbeq, + Self::EqusPlusEqus => Venue::Equs, Self::OpraPillarSphr => Venue::Sphr, - Self::DbeqMaxXchi => Venue::Xchi, - Self::DbeqMaxXcis => Venue::Xcis, - Self::DbeqMaxIexg => Venue::Iexg, - Self::DbeqMaxEprl => Venue::Eprl, - Self::DbeqMaxXnas => Venue::Xnas, - Self::DbeqMaxXnys => Venue::Xnys, - Self::DbeqMaxFinn => Venue::Finn, - Self::DbeqMaxFiny => Venue::Finy, - Self::DbeqMaxFinc => Venue::Finc, - Self::DbeqMaxBats => Venue::Bats, - Self::DbeqMaxBaty => Venue::Baty, - Self::DbeqMaxEdga => Venue::Edga, - Self::DbeqMaxEdgx => Venue::Edgx, - Self::DbeqMaxXbos => Venue::Xbos, - Self::DbeqMaxXpsx => Venue::Xpsx, - Self::DbeqMaxMemx => Venue::Memx, - Self::DbeqMaxXase => Venue::Xase, - Self::DbeqMaxArcx => Venue::Arcx, - Self::DbeqMaxLtse => Venue::Ltse, + Self::EqusAllXchi => Venue::Xchi, + Self::EqusAllXcis => Venue::Xcis, + Self::EqusAllIexg => Venue::Iexg, + Self::EqusAllEprl => Venue::Eprl, + Self::EqusAllXnas => Venue::Xnas, + Self::EqusAllXnys => Venue::Xnys, + Self::EqusAllFinn => Venue::Finn, + Self::EqusAllFiny => Venue::Finy, + Self::EqusAllFinc => Venue::Finc, + Self::EqusAllBats => Venue::Bats, + Self::EqusAllBaty => Venue::Baty, + Self::EqusAllEdga => Venue::Edga, + Self::EqusAllEdgx => Venue::Edgx, + Self::EqusAllXbos => Venue::Xbos, + Self::EqusAllXpsx => Venue::Xpsx, + Self::EqusAllMemx => Venue::Memx, + Self::EqusAllXase => Venue::Xase, + Self::EqusAllArcx => Venue::Arcx, + Self::EqusAllLtse => Venue::Ltse, Self::XnasBasicXnas => Venue::Xnas, Self::XnasBasicFinn => Venue::Finn, Self::XnasBasicFinc => Venue::Finc, @@ -803,11 +817,13 @@ impl Publisher { Self::XnasNlsXpsx => Venue::Xpsx, Self::XnasBasicXbos => Venue::Xbos, Self::XnasBasicXpsx => Venue::Xpsx, - Self::DbeqSummaryDbeq => Venue::Dbeq, - Self::XcisBbotradesXcis => Venue::Xcis, - Self::XnysBbotradesXnys => Venue::Xnys, - Self::XnasBasicDbeq => Venue::Dbeq, - Self::DbeqMaxDbeq => Venue::Dbeq, + Self::EqusSummaryEqus => Venue::Equs, + Self::XcisTradesbboXcis => Venue::Xcis, + Self::XnysTradesbboXnys => Venue::Xnys, + Self::XnasBasicEqus => Venue::Equs, + Self::EqusAllEqus => Venue::Equs, + Self::EqusMiniEqus => Venue::Equs, + Self::XnysTradesEqus => Venue::Equs, } } @@ -861,39 +877,39 @@ impl Publisher { Self::XnysTradesXnys => Dataset::XnysTrades, Self::XnasQbboXnas => Dataset::XnasQbbo, Self::XnasNlsXnas => Dataset::XnasNls, - Self::DbeqPlusXchi => Dataset::DbeqPlus, - Self::DbeqPlusXcis => Dataset::DbeqPlus, - Self::DbeqPlusIexg => Dataset::DbeqPlus, - Self::DbeqPlusEprl => Dataset::DbeqPlus, - Self::DbeqPlusXnas => Dataset::DbeqPlus, - Self::DbeqPlusXnys => Dataset::DbeqPlus, - Self::DbeqPlusFinn => Dataset::DbeqPlus, - Self::DbeqPlusFiny => Dataset::DbeqPlus, - Self::DbeqPlusFinc => Dataset::DbeqPlus, + Self::EqusPlusXchi => Dataset::EqusPlus, + Self::EqusPlusXcis => Dataset::EqusPlus, + Self::EqusPlusIexg => Dataset::EqusPlus, + Self::EqusPlusEprl => Dataset::EqusPlus, + Self::EqusPlusXnas => Dataset::EqusPlus, + Self::EqusPlusXnys => Dataset::EqusPlus, + Self::EqusPlusFinn => Dataset::EqusPlus, + Self::EqusPlusFiny => Dataset::EqusPlus, + Self::EqusPlusFinc => Dataset::EqusPlus, Self::IfeuImpactIfeu => Dataset::IfeuImpact, Self::NdexImpactNdex => Dataset::NdexImpact, Self::DbeqBasicDbeq => Dataset::DbeqBasic, - Self::DbeqPlusDbeq => Dataset::DbeqPlus, + Self::EqusPlusEqus => Dataset::EqusPlus, Self::OpraPillarSphr => Dataset::OpraPillar, - Self::DbeqMaxXchi => Dataset::DbeqMax, - Self::DbeqMaxXcis => Dataset::DbeqMax, - Self::DbeqMaxIexg => Dataset::DbeqMax, - Self::DbeqMaxEprl => Dataset::DbeqMax, - Self::DbeqMaxXnas => Dataset::DbeqMax, - Self::DbeqMaxXnys => Dataset::DbeqMax, - Self::DbeqMaxFinn => Dataset::DbeqMax, - Self::DbeqMaxFiny => Dataset::DbeqMax, - Self::DbeqMaxFinc => Dataset::DbeqMax, - Self::DbeqMaxBats => Dataset::DbeqMax, - Self::DbeqMaxBaty => Dataset::DbeqMax, - Self::DbeqMaxEdga => Dataset::DbeqMax, - Self::DbeqMaxEdgx => Dataset::DbeqMax, - Self::DbeqMaxXbos => Dataset::DbeqMax, - Self::DbeqMaxXpsx => Dataset::DbeqMax, - Self::DbeqMaxMemx => Dataset::DbeqMax, - Self::DbeqMaxXase => Dataset::DbeqMax, - Self::DbeqMaxArcx => Dataset::DbeqMax, - Self::DbeqMaxLtse => Dataset::DbeqMax, + Self::EqusAllXchi => Dataset::EqusAll, + Self::EqusAllXcis => Dataset::EqusAll, + Self::EqusAllIexg => Dataset::EqusAll, + Self::EqusAllEprl => Dataset::EqusAll, + Self::EqusAllXnas => Dataset::EqusAll, + Self::EqusAllXnys => Dataset::EqusAll, + Self::EqusAllFinn => Dataset::EqusAll, + Self::EqusAllFiny => Dataset::EqusAll, + Self::EqusAllFinc => Dataset::EqusAll, + Self::EqusAllBats => Dataset::EqusAll, + Self::EqusAllBaty => Dataset::EqusAll, + Self::EqusAllEdga => Dataset::EqusAll, + Self::EqusAllEdgx => Dataset::EqusAll, + Self::EqusAllXbos => Dataset::EqusAll, + Self::EqusAllXpsx => Dataset::EqusAll, + Self::EqusAllMemx => Dataset::EqusAll, + Self::EqusAllXase => Dataset::EqusAll, + Self::EqusAllArcx => Dataset::EqusAll, + Self::EqusAllLtse => Dataset::EqusAll, Self::XnasBasicXnas => Dataset::XnasBasic, Self::XnasBasicFinn => Dataset::XnasBasic, Self::XnasBasicFinc => Dataset::XnasBasic, @@ -903,11 +919,13 @@ impl Publisher { Self::XnasNlsXpsx => Dataset::XnasNls, Self::XnasBasicXbos => Dataset::XnasBasic, Self::XnasBasicXpsx => Dataset::XnasBasic, - Self::DbeqSummaryDbeq => Dataset::DbeqSummary, - Self::XcisBbotradesXcis => Dataset::XcisBbotrades, - Self::XnysBbotradesXnys => Dataset::XnysBbotrades, - Self::XnasBasicDbeq => Dataset::XnasBasic, - Self::DbeqMaxDbeq => Dataset::DbeqMax, + Self::EqusSummaryEqus => Dataset::EqusSummary, + Self::XcisTradesbboXcis => Dataset::XcisTradesbbo, + Self::XnysTradesbboXnys => Dataset::XnysTradesbbo, + Self::XnasBasicEqus => Dataset::XnasBasic, + Self::EqusAllEqus => Dataset::EqusAll, + Self::EqusMiniEqus => Dataset::EqusMini, + Self::XnysTradesEqus => Dataset::XnysTrades, } } @@ -963,39 +981,39 @@ impl Publisher { (Dataset::XnysTrades, Venue::Xnys) => Ok(Self::XnysTradesXnys), (Dataset::XnasQbbo, Venue::Xnas) => Ok(Self::XnasQbboXnas), (Dataset::XnasNls, Venue::Xnas) => Ok(Self::XnasNlsXnas), - (Dataset::DbeqPlus, Venue::Xchi) => Ok(Self::DbeqPlusXchi), - (Dataset::DbeqPlus, Venue::Xcis) => Ok(Self::DbeqPlusXcis), - (Dataset::DbeqPlus, Venue::Iexg) => Ok(Self::DbeqPlusIexg), - (Dataset::DbeqPlus, Venue::Eprl) => Ok(Self::DbeqPlusEprl), - (Dataset::DbeqPlus, Venue::Xnas) => Ok(Self::DbeqPlusXnas), - (Dataset::DbeqPlus, Venue::Xnys) => Ok(Self::DbeqPlusXnys), - (Dataset::DbeqPlus, Venue::Finn) => Ok(Self::DbeqPlusFinn), - (Dataset::DbeqPlus, Venue::Finy) => Ok(Self::DbeqPlusFiny), - (Dataset::DbeqPlus, Venue::Finc) => Ok(Self::DbeqPlusFinc), + (Dataset::EqusPlus, Venue::Xchi) => Ok(Self::EqusPlusXchi), + (Dataset::EqusPlus, Venue::Xcis) => Ok(Self::EqusPlusXcis), + (Dataset::EqusPlus, Venue::Iexg) => Ok(Self::EqusPlusIexg), + (Dataset::EqusPlus, Venue::Eprl) => Ok(Self::EqusPlusEprl), + (Dataset::EqusPlus, Venue::Xnas) => Ok(Self::EqusPlusXnas), + (Dataset::EqusPlus, Venue::Xnys) => Ok(Self::EqusPlusXnys), + (Dataset::EqusPlus, Venue::Finn) => Ok(Self::EqusPlusFinn), + (Dataset::EqusPlus, Venue::Finy) => Ok(Self::EqusPlusFiny), + (Dataset::EqusPlus, Venue::Finc) => Ok(Self::EqusPlusFinc), (Dataset::IfeuImpact, Venue::Ifeu) => Ok(Self::IfeuImpactIfeu), (Dataset::NdexImpact, Venue::Ndex) => Ok(Self::NdexImpactNdex), (Dataset::DbeqBasic, Venue::Dbeq) => Ok(Self::DbeqBasicDbeq), - (Dataset::DbeqPlus, Venue::Dbeq) => Ok(Self::DbeqPlusDbeq), + (Dataset::EqusPlus, Venue::Equs) => Ok(Self::EqusPlusEqus), (Dataset::OpraPillar, Venue::Sphr) => Ok(Self::OpraPillarSphr), - (Dataset::DbeqMax, Venue::Xchi) => Ok(Self::DbeqMaxXchi), - (Dataset::DbeqMax, Venue::Xcis) => Ok(Self::DbeqMaxXcis), - (Dataset::DbeqMax, Venue::Iexg) => Ok(Self::DbeqMaxIexg), - (Dataset::DbeqMax, Venue::Eprl) => Ok(Self::DbeqMaxEprl), - (Dataset::DbeqMax, Venue::Xnas) => Ok(Self::DbeqMaxXnas), - (Dataset::DbeqMax, Venue::Xnys) => Ok(Self::DbeqMaxXnys), - (Dataset::DbeqMax, Venue::Finn) => Ok(Self::DbeqMaxFinn), - (Dataset::DbeqMax, Venue::Finy) => Ok(Self::DbeqMaxFiny), - (Dataset::DbeqMax, Venue::Finc) => Ok(Self::DbeqMaxFinc), - (Dataset::DbeqMax, Venue::Bats) => Ok(Self::DbeqMaxBats), - (Dataset::DbeqMax, Venue::Baty) => Ok(Self::DbeqMaxBaty), - (Dataset::DbeqMax, Venue::Edga) => Ok(Self::DbeqMaxEdga), - (Dataset::DbeqMax, Venue::Edgx) => Ok(Self::DbeqMaxEdgx), - (Dataset::DbeqMax, Venue::Xbos) => Ok(Self::DbeqMaxXbos), - (Dataset::DbeqMax, Venue::Xpsx) => Ok(Self::DbeqMaxXpsx), - (Dataset::DbeqMax, Venue::Memx) => Ok(Self::DbeqMaxMemx), - (Dataset::DbeqMax, Venue::Xase) => Ok(Self::DbeqMaxXase), - (Dataset::DbeqMax, Venue::Arcx) => Ok(Self::DbeqMaxArcx), - (Dataset::DbeqMax, Venue::Ltse) => Ok(Self::DbeqMaxLtse), + (Dataset::EqusAll, Venue::Xchi) => Ok(Self::EqusAllXchi), + (Dataset::EqusAll, Venue::Xcis) => Ok(Self::EqusAllXcis), + (Dataset::EqusAll, Venue::Iexg) => Ok(Self::EqusAllIexg), + (Dataset::EqusAll, Venue::Eprl) => Ok(Self::EqusAllEprl), + (Dataset::EqusAll, Venue::Xnas) => Ok(Self::EqusAllXnas), + (Dataset::EqusAll, Venue::Xnys) => Ok(Self::EqusAllXnys), + (Dataset::EqusAll, Venue::Finn) => Ok(Self::EqusAllFinn), + (Dataset::EqusAll, Venue::Finy) => Ok(Self::EqusAllFiny), + (Dataset::EqusAll, Venue::Finc) => Ok(Self::EqusAllFinc), + (Dataset::EqusAll, Venue::Bats) => Ok(Self::EqusAllBats), + (Dataset::EqusAll, Venue::Baty) => Ok(Self::EqusAllBaty), + (Dataset::EqusAll, Venue::Edga) => Ok(Self::EqusAllEdga), + (Dataset::EqusAll, Venue::Edgx) => Ok(Self::EqusAllEdgx), + (Dataset::EqusAll, Venue::Xbos) => Ok(Self::EqusAllXbos), + (Dataset::EqusAll, Venue::Xpsx) => Ok(Self::EqusAllXpsx), + (Dataset::EqusAll, Venue::Memx) => Ok(Self::EqusAllMemx), + (Dataset::EqusAll, Venue::Xase) => Ok(Self::EqusAllXase), + (Dataset::EqusAll, Venue::Arcx) => Ok(Self::EqusAllArcx), + (Dataset::EqusAll, Venue::Ltse) => Ok(Self::EqusAllLtse), (Dataset::XnasBasic, Venue::Xnas) => Ok(Self::XnasBasicXnas), (Dataset::XnasBasic, Venue::Finn) => Ok(Self::XnasBasicFinn), (Dataset::XnasBasic, Venue::Finc) => Ok(Self::XnasBasicFinc), @@ -1005,11 +1023,13 @@ impl Publisher { (Dataset::XnasNls, Venue::Xpsx) => Ok(Self::XnasNlsXpsx), (Dataset::XnasBasic, Venue::Xbos) => Ok(Self::XnasBasicXbos), (Dataset::XnasBasic, Venue::Xpsx) => Ok(Self::XnasBasicXpsx), - (Dataset::DbeqSummary, Venue::Dbeq) => Ok(Self::DbeqSummaryDbeq), - (Dataset::XcisBbotrades, Venue::Xcis) => Ok(Self::XcisBbotradesXcis), - (Dataset::XnysBbotrades, Venue::Xnys) => Ok(Self::XnysBbotradesXnys), - (Dataset::XnasBasic, Venue::Dbeq) => Ok(Self::XnasBasicDbeq), - (Dataset::DbeqMax, Venue::Dbeq) => Ok(Self::DbeqMaxDbeq), + (Dataset::EqusSummary, Venue::Equs) => Ok(Self::EqusSummaryEqus), + (Dataset::XcisTradesbbo, Venue::Xcis) => Ok(Self::XcisTradesbboXcis), + (Dataset::XnysTradesbbo, Venue::Xnys) => Ok(Self::XnysTradesbboXnys), + (Dataset::XnasBasic, Venue::Equs) => Ok(Self::XnasBasicEqus), + (Dataset::EqusAll, Venue::Equs) => Ok(Self::EqusAllEqus), + (Dataset::EqusMini, Venue::Equs) => Ok(Self::EqusMiniEqus), + (Dataset::XnysTrades, Venue::Equs) => Ok(Self::XnysTradesEqus), _ => Err(Error::conversion::(format!("({dataset}, {venue})"))), } } @@ -1079,39 +1099,39 @@ impl std::str::FromStr for Publisher { "XNYS.TRADES.XNYS" => Ok(Self::XnysTradesXnys), "XNAS.QBBO.XNAS" => Ok(Self::XnasQbboXnas), "XNAS.NLS.XNAS" => Ok(Self::XnasNlsXnas), - "DBEQ.PLUS.XCHI" => Ok(Self::DbeqPlusXchi), - "DBEQ.PLUS.XCIS" => Ok(Self::DbeqPlusXcis), - "DBEQ.PLUS.IEXG" => Ok(Self::DbeqPlusIexg), - "DBEQ.PLUS.EPRL" => Ok(Self::DbeqPlusEprl), - "DBEQ.PLUS.XNAS" => Ok(Self::DbeqPlusXnas), - "DBEQ.PLUS.XNYS" => Ok(Self::DbeqPlusXnys), - "DBEQ.PLUS.FINN" => Ok(Self::DbeqPlusFinn), - "DBEQ.PLUS.FINY" => Ok(Self::DbeqPlusFiny), - "DBEQ.PLUS.FINC" => Ok(Self::DbeqPlusFinc), + "EQUS.PLUS.XCHI" => Ok(Self::EqusPlusXchi), + "EQUS.PLUS.XCIS" => Ok(Self::EqusPlusXcis), + "EQUS.PLUS.IEXG" => Ok(Self::EqusPlusIexg), + "EQUS.PLUS.EPRL" => Ok(Self::EqusPlusEprl), + "EQUS.PLUS.XNAS" => Ok(Self::EqusPlusXnas), + "EQUS.PLUS.XNYS" => Ok(Self::EqusPlusXnys), + "EQUS.PLUS.FINN" => Ok(Self::EqusPlusFinn), + "EQUS.PLUS.FINY" => Ok(Self::EqusPlusFiny), + "EQUS.PLUS.FINC" => Ok(Self::EqusPlusFinc), "IFEU.IMPACT.IFEU" => Ok(Self::IfeuImpactIfeu), "NDEX.IMPACT.NDEX" => Ok(Self::NdexImpactNdex), "DBEQ.BASIC.DBEQ" => Ok(Self::DbeqBasicDbeq), - "DBEQ.PLUS.DBEQ" => Ok(Self::DbeqPlusDbeq), + "EQUS.PLUS.EQUS" => Ok(Self::EqusPlusEqus), "OPRA.PILLAR.SPHR" => Ok(Self::OpraPillarSphr), - "DBEQ.MAX.XCHI" => Ok(Self::DbeqMaxXchi), - "DBEQ.MAX.XCIS" => Ok(Self::DbeqMaxXcis), - "DBEQ.MAX.IEXG" => Ok(Self::DbeqMaxIexg), - "DBEQ.MAX.EPRL" => Ok(Self::DbeqMaxEprl), - "DBEQ.MAX.XNAS" => Ok(Self::DbeqMaxXnas), - "DBEQ.MAX.XNYS" => Ok(Self::DbeqMaxXnys), - "DBEQ.MAX.FINN" => Ok(Self::DbeqMaxFinn), - "DBEQ.MAX.FINY" => Ok(Self::DbeqMaxFiny), - "DBEQ.MAX.FINC" => Ok(Self::DbeqMaxFinc), - "DBEQ.MAX.BATS" => Ok(Self::DbeqMaxBats), - "DBEQ.MAX.BATY" => Ok(Self::DbeqMaxBaty), - "DBEQ.MAX.EDGA" => Ok(Self::DbeqMaxEdga), - "DBEQ.MAX.EDGX" => Ok(Self::DbeqMaxEdgx), - "DBEQ.MAX.XBOS" => Ok(Self::DbeqMaxXbos), - "DBEQ.MAX.XPSX" => Ok(Self::DbeqMaxXpsx), - "DBEQ.MAX.MEMX" => Ok(Self::DbeqMaxMemx), - "DBEQ.MAX.XASE" => Ok(Self::DbeqMaxXase), - "DBEQ.MAX.ARCX" => Ok(Self::DbeqMaxArcx), - "DBEQ.MAX.LTSE" => Ok(Self::DbeqMaxLtse), + "EQUS.ALL.XCHI" => Ok(Self::EqusAllXchi), + "EQUS.ALL.XCIS" => Ok(Self::EqusAllXcis), + "EQUS.ALL.IEXG" => Ok(Self::EqusAllIexg), + "EQUS.ALL.EPRL" => Ok(Self::EqusAllEprl), + "EQUS.ALL.XNAS" => Ok(Self::EqusAllXnas), + "EQUS.ALL.XNYS" => Ok(Self::EqusAllXnys), + "EQUS.ALL.FINN" => Ok(Self::EqusAllFinn), + "EQUS.ALL.FINY" => Ok(Self::EqusAllFiny), + "EQUS.ALL.FINC" => Ok(Self::EqusAllFinc), + "EQUS.ALL.BATS" => Ok(Self::EqusAllBats), + "EQUS.ALL.BATY" => Ok(Self::EqusAllBaty), + "EQUS.ALL.EDGA" => Ok(Self::EqusAllEdga), + "EQUS.ALL.EDGX" => Ok(Self::EqusAllEdgx), + "EQUS.ALL.XBOS" => Ok(Self::EqusAllXbos), + "EQUS.ALL.XPSX" => Ok(Self::EqusAllXpsx), + "EQUS.ALL.MEMX" => Ok(Self::EqusAllMemx), + "EQUS.ALL.XASE" => Ok(Self::EqusAllXase), + "EQUS.ALL.ARCX" => Ok(Self::EqusAllArcx), + "EQUS.ALL.LTSE" => Ok(Self::EqusAllLtse), "XNAS.BASIC.XNAS" => Ok(Self::XnasBasicXnas), "XNAS.BASIC.FINN" => Ok(Self::XnasBasicFinn), "XNAS.BASIC.FINC" => Ok(Self::XnasBasicFinc), @@ -1121,11 +1141,13 @@ impl std::str::FromStr for Publisher { "XNAS.NLS.XPSX" => Ok(Self::XnasNlsXpsx), "XNAS.BASIC.XBOS" => Ok(Self::XnasBasicXbos), "XNAS.BASIC.XPSX" => Ok(Self::XnasBasicXpsx), - "DBEQ.SUMMARY.DBEQ" => Ok(Self::DbeqSummaryDbeq), - "XCIS.BBOTRADES.XCIS" => Ok(Self::XcisBbotradesXcis), - "XNYS.BBOTRADES.XNYS" => Ok(Self::XnysBbotradesXnys), - "XNAS.BASIC.DBEQ" => Ok(Self::XnasBasicDbeq), - "DBEQ.MAX.DBEQ" => Ok(Self::DbeqMaxDbeq), + "EQUS.SUMMARY.EQUS" => Ok(Self::EqusSummaryEqus), + "XCIS.TRADESBBO.XCIS" => Ok(Self::XcisTradesbboXcis), + "XNYS.TRADESBBO.XNYS" => Ok(Self::XnysTradesbboXnys), + "XNAS.BASIC.EQUS" => Ok(Self::XnasBasicEqus), + "EQUS.ALL.EQUS" => Ok(Self::EqusAllEqus), + "EQUS.MINI.EQUS" => Ok(Self::EqusMiniEqus), + "XNYS.TRADES.EQUS" => Ok(Self::XnysTradesEqus), _ => Err(Error::conversion::(s)), } } diff --git a/rust/dbn/src/python.rs b/rust/dbn/src/python.rs index c934cce..8a751f2 100644 --- a/rust/dbn/src/python.rs +++ b/rust/dbn/src/python.rs @@ -2,13 +2,14 @@ //! to be able to implement [`pyo3`] traits for DBN types. #![allow(clippy::too_many_arguments)] -use std::fmt; +use std::{convert::Infallible, fmt}; use pyo3::{ create_exception, exceptions::PyException, prelude::*, - types::{PyDate, PyDateAccess}, + types::{PyDate, PyDateAccess, PyInt}, + IntoPyObjectExt, }; use strum::IntoEnumIterator; @@ -41,7 +42,7 @@ impl From for PyErr { #[pyclass(module = "databento_dbn")] pub struct EnumIterator { // Type erasure for code reuse. Generic types can't be exposed to Python. - iter: Box + Send>, + iter: Box + Send + Sync>, } #[pymethods] @@ -56,26 +57,30 @@ impl EnumIterator { } impl EnumIterator { - fn new(py: Python<'_>) -> Self + fn new<'py, E>(py: Python<'py>) -> PyResult where - E: strum::IntoEnumIterator + IntoPy>, - ::Iterator: Send, + E: strum::IntoEnumIterator + IntoPyObject<'py>, + ::Iterator: Send + Sync, { - Self { + Ok(Self { iter: Box::new( E::iter() - .map(|var| var.into_py(py)) + .map(|var| var.into_py_any(py)) // force eager evaluation because `py` isn't `Send` - .collect::>() + .collect::>>()? .into_iter(), ), - } + }) } } -impl IntoPy for FlagSet { - fn into_py(self, py: Python<'_>) -> PyObject { - self.raw().into_py(py) +impl<'py> IntoPyObject<'py> for FlagSet { + type Target = PyInt; + type Output = Bound<'py, Self::Target>; + type Error = Infallible; + + fn into_pyobject(self, py: Python<'py>) -> Result { + self.raw().into_pyobject(py) } } diff --git a/rust/dbn/src/python/enums.rs b/rust/dbn/src/python/enums.rs index 1ca8a83..234fbb2 100644 --- a/rust/dbn/src/python/enums.rs +++ b/rust/dbn/src/python/enums.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use pyo3::{prelude::*, pyclass::CompareOp, type_object::PyTypeInfo, types::PyType, Bound}; +use pyo3::{prelude::*, type_object::PyTypeInfo, types::PyType, Bound}; use crate::{ enums::{Compression, Encoding, SType, Schema, SecurityUpdateAction, UserDefinedInstrument}, @@ -15,7 +15,7 @@ impl Side { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { let Ok(i) = value.extract::() else { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); let c = value.extract::().map_err(to_py_err)?; return Self::py_from_str(&t, c); }; @@ -34,29 +34,25 @@ impl Side { format!("", self.name(), self.value()) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_ref().to_ascii_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> String { self.__str__() } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -72,7 +68,7 @@ impl Action { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { let Ok(i) = value.extract::() else { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); let c = value.extract::().map_err(to_py_err)?; return Self::py_from_str(&t, c); }; @@ -91,29 +87,25 @@ impl Action { format!("", self.name(), self.value()) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_ref().to_ascii_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> String { self.__str__() } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -129,7 +121,7 @@ impl InstrumentClass { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { let Ok(i) = value.extract::() else { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); let c = value.extract::().map_err(to_py_err)?; return Self::py_from_str(&t, c); }; @@ -144,15 +136,11 @@ impl InstrumentClass { format!("{}", *self as u8 as char) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { - return py.NotImplemented(); + return false; }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } + self.eq(&other_enum) } #[getter] @@ -161,7 +149,7 @@ impl InstrumentClass { } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -177,7 +165,7 @@ impl MatchAlgorithm { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { let Ok(i) = value.extract::() else { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); let c = value.extract::().map_err(to_py_err)?; return Self::py_from_str(&t, c); }; @@ -192,15 +180,11 @@ impl MatchAlgorithm { format!("{}", *self as u8 as char) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { - return py.NotImplemented(); + return false; }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } + self.eq(&other_enum) } #[getter] @@ -209,7 +193,7 @@ impl MatchAlgorithm { } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -225,7 +209,7 @@ impl UserDefinedInstrument { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { let Ok(i) = value.extract::() else { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); let c = value.extract::().map_err(to_py_err)?; return Self::py_from_str(&t, c); }; @@ -248,29 +232,25 @@ impl UserDefinedInstrument { ) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_ref().to_ascii_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> String { self.__str__() } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -285,7 +265,7 @@ impl UserDefinedInstrument { impl SType { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); Self::py_from_str(&t, value) } @@ -301,29 +281,25 @@ impl SType { format!("", self.name(), self.value(),) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = Self::py_from_str(&Self::type_object_bound(py), other) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_str().to_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> &'static str { self.as_str() } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -340,7 +316,7 @@ impl SType { impl RType { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); Self::py_from_str(&t, value).or_else(|_| Self::py_from_int(&t, value)) } @@ -356,32 +332,25 @@ impl RType { format!("", self.name(), self.value(),) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - if let Ok(other_enum) = Self::py_from_str(&Self::type_object_bound(py), other) - .or_else(|_| Self::py_from_int(&Self::type_object_bound(py), other)) - { - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } else { - py.NotImplemented() - } - } - #[getter] fn name(&self) -> String { self.as_str().to_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> u8 { *self as u8 } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -405,7 +374,7 @@ impl RType { fn py_from_schema(pytype: &Bound, value: &Bound) -> PyResult { let schema: Schema = value .extract() - .or_else(|_| Schema::py_from_str(&Schema::type_object_bound(pytype.py()), value)) + .or_else(|_| Schema::py_from_str(&Schema::type_object(pytype.py()), value)) .map_err(to_py_err)?; Ok(Self::from(schema)) } @@ -415,7 +384,7 @@ impl RType { impl Schema { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); Self::py_from_str(&t, value) } @@ -431,29 +400,25 @@ impl Schema { format!("", self.name(), self.value(),) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = Self::py_from_str(&Self::type_object_bound(py), other) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_str().to_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> &'static str { self.as_str() } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -470,7 +435,7 @@ impl Schema { impl Encoding { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); Self::py_from_str(&t, value) } @@ -486,29 +451,25 @@ impl Encoding { format!("", self.name(), self.value(),) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = Self::py_from_str(&Self::type_object_bound(py), other) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_str().to_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> &'static str { self.as_str() } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -525,7 +486,7 @@ impl Encoding { impl Compression { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); Self::py_from_str(&t, value) } @@ -541,22 +502,18 @@ impl Compression { format!("", self.name(), self.value(),) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = Self::py_from_str(&Self::type_object_bound(py), other) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_str().to_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> &'static str { self.as_str() @@ -564,7 +521,7 @@ impl Compression { // No metaclass support with pyo3, so `for c in Compression: ...` isn't possible #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -582,7 +539,7 @@ impl SecurityUpdateAction { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { let Ok(i) = value.extract::() else { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); let c = value.extract::().map_err(to_py_err)?; return Self::py_from_str(&t, c); }; @@ -597,29 +554,25 @@ impl SecurityUpdateAction { format!("", self.name(), self.value()) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[getter] fn name(&self) -> String { self.as_ref().to_ascii_uppercase() } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> u16 { *self as u16 } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -642,15 +595,11 @@ impl StatType { *self as isize } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { + fn __eq__(&self, other: &Bound) -> bool { let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(other)) else { - return py.NotImplemented(); + return false; }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } + self.eq(&other_enum) } #[getter] @@ -659,7 +608,7 @@ impl StatType { } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } } @@ -676,15 +625,11 @@ impl StatusAction { *self as isize } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { + fn __eq__(&self, other: &Bound) -> bool { let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(other)) else { - return py.NotImplemented(); + return false; }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } + self.eq(&other_enum) } #[getter] @@ -693,7 +638,7 @@ impl StatusAction { } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } } @@ -710,15 +655,11 @@ impl StatusReason { *self as isize } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { + fn __eq__(&self, other: &Bound) -> bool { let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(other)) else { - return py.NotImplemented(); + return false; }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } + self.eq(&other_enum) } #[getter] @@ -727,7 +668,7 @@ impl StatusReason { } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } } @@ -744,15 +685,11 @@ impl TradingEvent { *self as isize } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { + fn __eq__(&self, other: &Bound) -> bool { let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(other)) else { - return py.NotImplemented(); + return false; }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } + self.eq(&other_enum) } #[getter] @@ -761,7 +698,7 @@ impl TradingEvent { } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } } @@ -771,7 +708,7 @@ impl TriState { #[new] fn py_new(py: Python<'_>, value: &Bound) -> PyResult { let Ok(i) = value.extract::() else { - let t = Self::type_object_bound(py); + let t = Self::type_object(py); let c = value.extract::().map_err(to_py_err)?; return Self::py_from_str(&t, c); }; @@ -786,28 +723,24 @@ impl TriState { format!("{}", *self as u8 as char) } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - fn opt_bool(&self) -> Option { Option::from(*self) } + fn __eq__(&self, other: &Bound, py: Python<'_>) -> bool { + let Ok(other_enum) = other.extract::().or_else(|_| Self::py_new(py, other)) else { + return false; + }; + self.eq(&other_enum) + } + #[getter] fn value(&self) -> String { self.__str__() } #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } @@ -824,19 +757,8 @@ impl VersionUpgradePolicy { *self as isize } - fn __richcmp__(&self, other: &Bound, op: CompareOp, py: Python<'_>) -> Py { - let Ok(other_enum) = other.extract::() else { - return py.NotImplemented(); - }; - match op { - CompareOp::Eq => self.eq(&other_enum).into_py(py), - CompareOp::Ne => self.ne(&other_enum).into_py(py), - _ => py.NotImplemented(), - } - } - #[classmethod] - fn variants(_: &Bound, py: Python<'_>) -> EnumIterator { + fn variants(_: &Bound, py: Python<'_>) -> PyResult { EnumIterator::new::(py) } } diff --git a/rust/dbn/src/python/metadata.rs b/rust/dbn/src/python/metadata.rs index 50dea84..d5e1229 100644 --- a/rust/dbn/src/python/metadata.rs +++ b/rust/dbn/src/python/metadata.rs @@ -3,7 +3,6 @@ use std::{collections::HashMap, io, num::NonZeroU64}; use pyo3::{ intern, prelude::*, - pyclass::CompareOp, types::{PyBytes, PyDate, PyDict, PyType}, Bound, }; @@ -67,30 +66,25 @@ impl Metadata { .build() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } /// Encodes Metadata back into DBN format. - fn __bytes__(&self, py: Python<'_>) -> PyResult> { + fn __bytes__<'py>(&self, py: Python<'py>) -> PyResult> { self.py_encode(py) } #[getter] - fn get_mappings(&self) -> HashMap> { + fn get_mappings<'py>(&self, py: Python<'py>) -> PyResult>> { let mut res = HashMap::new(); for mapping in self.mappings.iter() { - res.insert(mapping.raw_symbol.clone(), mapping.intervals.clone()); + res.insert( + mapping.raw_symbol.clone(), + mapping.intervals.into_pyobject(py)?, + ); } - res + Ok(res) } #[pyo3(name = "decode", signature = (data, upgrade_policy = VersionUpgradePolicy::default()))] @@ -109,29 +103,24 @@ impl Metadata { } #[pyo3(name = "encode")] - fn py_encode(&self, py: Python<'_>) -> PyResult> { + fn py_encode<'py>(&self, py: Python<'py>) -> PyResult> { let mut buffer = Vec::new(); let mut encoder = MetadataEncoder::new(&mut buffer); encoder.encode(self)?; - Ok(PyBytes::new_bound(py, buffer.as_slice()).into()) + Ok(PyBytes::new(py, buffer.as_slice())) } } -impl IntoPy for SymbolMapping { - fn into_py(self, py: Python<'_>) -> PyObject { - self.to_object(py) - } -} +impl<'py> IntoPyObject<'py> for SymbolMapping { + type Target = PyDict; + type Output = Bound<'py, PyDict>; + type Error = PyErr; -// `ToPyObject` is about copying and is required for `PyDict::set_item` -impl ToPyObject for SymbolMapping { - fn to_object(&self, py: Python<'_>) -> PyObject { - let dict = PyDict::new_bound(py); - dict.set_item(intern!(py, "raw_symbol"), &self.raw_symbol) - .unwrap(); - dict.set_item(intern!(py, "intervals"), &self.intervals) - .unwrap(); - dict.into_py(py) + fn into_pyobject(self, py: Python<'py>) -> Result { + let dict = PyDict::new(py); + dict.set_item(intern!(py, "raw_symbol"), &self.raw_symbol)?; + dict.set_item(intern!(py, "intervals"), &self.intervals)?; + Ok(dict) } } @@ -157,39 +146,33 @@ impl<'py> FromPyObject<'py> for MappingInterval { } } -impl ToPyObject for MappingInterval { - fn to_object(&self, py: Python<'_>) -> PyObject { - let dict = PyDict::new_bound(py); +impl<'py> IntoPyObject<'py> for &MappingInterval { + type Target = PyDict; + type Output = Bound<'py, PyDict>; + type Error = PyErr; + + fn into_pyobject(self, py: Python<'py>) -> Result { + let dict = PyDict::new(py); dict.set_item( intern!(py, "start_date"), - PyDate::new_bound( + PyDate::new( py, self.start_date.year(), self.start_date.month() as u8, self.start_date.day(), - ) - .unwrap(), - ) - .unwrap(); + )?, + )?; dict.set_item( intern!(py, "end_date"), - PyDate::new_bound( + PyDate::new( py, self.end_date.year(), self.end_date.month() as u8, self.end_date.day(), - ) - .unwrap(), - ) - .unwrap(); - dict.set_item(intern!(py, "symbol"), &self.symbol).unwrap(); - dict.into_py(py) - } -} - -impl IntoPy for MappingInterval { - fn into_py(self, py: Python<'_>) -> PyObject { - self.to_object(py) + )?, + )?; + dict.set_item(intern!(py, "symbol"), &self.symbol)?; + Ok(dict) } } diff --git a/rust/dbn/src/python/record.rs b/rust/dbn/src/python/record.rs index 3656d8f..7509c7f 100644 --- a/rust/dbn/src/python/record.rs +++ b/rust/dbn/src/python/record.rs @@ -1,10 +1,10 @@ use std::{ffi::c_char, mem}; use pyo3::{ + conversion::IntoPyObjectExt, intern, prelude::*, - pyclass::CompareOp, - types::{timezone_utc_bound, PyDateTime, PyDict}, + types::{timezone_utc, PyDateTime, PyDict}, }; use crate::{ @@ -83,14 +83,6 @@ impl MboMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -126,12 +118,12 @@ impl MboMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -235,14 +227,6 @@ impl BidAskPair { self.bid_px_f64() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -296,14 +280,6 @@ impl BboMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -339,12 +315,12 @@ impl BboMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -444,14 +420,6 @@ impl Cmbp1Msg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -486,12 +454,12 @@ impl Cmbp1Msg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -601,14 +569,6 @@ impl CbboMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -643,12 +603,12 @@ impl CbboMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -749,14 +709,6 @@ impl ConsolidatedBidAskPair { self.bid_pb().map(|pb| pb.to_string()).ok() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -811,14 +763,6 @@ impl TradeMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -854,12 +798,12 @@ impl TradeMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -976,14 +920,6 @@ impl Mbp1Msg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -1019,12 +955,12 @@ impl Mbp1Msg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -1153,14 +1089,6 @@ impl Mbp10Msg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -1196,12 +1124,12 @@ impl Mbp10Msg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -1294,14 +1222,6 @@ impl OhlcvMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -1352,7 +1272,7 @@ impl OhlcvMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -1441,14 +1361,6 @@ impl StatusMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -1479,12 +1391,12 @@ impl StatusMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -1789,14 +1701,6 @@ impl InstrumentDefMsgV3 { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -1862,22 +1766,22 @@ impl InstrumentDefMsgV3 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } #[getter] - fn get_pretty_activation(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_activation<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.activation) } #[getter] - fn get_pretty_expiration(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_expiration<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.expiration) } @@ -2265,14 +2169,6 @@ impl InstrumentDefMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -2343,22 +2239,22 @@ impl InstrumentDefMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } #[getter] - fn get_pretty_activation(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_activation<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.activation) } #[getter] - fn get_pretty_expiration(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_expiration<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.expiration) } @@ -2710,14 +2606,6 @@ impl InstrumentDefMsgV1 { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -2788,22 +2676,22 @@ impl InstrumentDefMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } #[getter] - fn get_pretty_activation(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_activation<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.activation) } #[getter] - fn get_pretty_expiration(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_expiration<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.expiration) } @@ -2985,14 +2873,6 @@ impl ImbalanceMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3043,12 +2923,12 @@ impl ImbalanceMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } @@ -3181,14 +3061,6 @@ impl StatMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3223,17 +3095,17 @@ impl StatMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_ts_recv(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_recv<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_recv) } #[getter] - fn get_pretty_ts_ref(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_ref<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_ref) } @@ -3290,14 +3162,6 @@ impl ErrorMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3328,7 +3192,7 @@ impl ErrorMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -3389,14 +3253,6 @@ impl ErrorMsgV1 { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3427,7 +3283,7 @@ impl ErrorMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -3511,14 +3367,6 @@ impl SymbolMappingMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3549,17 +3397,17 @@ impl SymbolMappingMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_end_ts(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_end_ts<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.end_ts) } #[getter] - fn get_pretty_start_ts(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_start_ts<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.start_ts) } @@ -3655,14 +3503,6 @@ impl SymbolMappingMsgV1 { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3693,17 +3533,17 @@ impl SymbolMappingMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } #[getter] - fn get_pretty_end_ts(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_end_ts<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.end_ts) } #[getter] - fn get_pretty_start_ts(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_start_ts<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.start_ts) } @@ -3769,14 +3609,6 @@ impl SystemMsg { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3807,7 +3639,7 @@ impl SystemMsg { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -3873,14 +3705,6 @@ impl SystemMsgV1 { self.as_ref() } - fn __richcmp__(&self, other: &Self, op: CompareOp, py: Python<'_>) -> Py { - match op { - CompareOp::Eq => self.eq(other).into_py(py), - CompareOp::Ne => self.ne(other).into_py(py), - _ => py.NotImplemented(), - } - } - fn __repr__(&self) -> String { format!("{self:?}") } @@ -3911,7 +3735,7 @@ impl SystemMsgV1 { } #[getter] - fn get_pretty_ts_event(&self, py: Python<'_>) -> PyResult> { + fn get_pretty_ts_event<'py>(&self, py: Python<'py>) -> PyResult>> { new_py_timestamp_or_datetime(py, self.ts_event()) } @@ -4056,21 +3880,31 @@ impl PyFieldDesc for [ConsolidatedBidAskPair; N] { } } -// `WithTsOut` is converted to a 2-tuple in Python -impl>> IntoPy for WithTsOut { - fn into_py(self, py: Python<'_>) -> PyObject { - let obj = self.rec.into_py(py); - obj.setattr(py, intern!(py, "ts_out"), self.ts_out).unwrap(); - obj +/// `WithTsOut` adds a `ts_out` field to the main record when converted to Python. +impl<'py, R> IntoPyObject<'py> for WithTsOut +where + R: HasRType + IntoPyObject<'py>, +{ + type Target = PyAny; + type Output = Bound<'py, PyAny>; + type Error = PyErr; + + fn into_pyobject(self, py: Python<'py>) -> Result { + let obj = self.rec.into_bound_py_any(py)?; + obj.setattr(intern!(py, "ts_out"), self.ts_out).unwrap(); + Ok(obj) } } -fn new_py_timestamp_or_datetime(py: Python<'_>, timestamp: u64) -> PyResult> { +fn new_py_timestamp_or_datetime( + py: Python<'_>, + timestamp: u64, +) -> PyResult>> { if timestamp == UNDEF_TIMESTAMP { return Ok(None); } - if let Ok(pandas) = PyModule::import_bound(py, intern!(py, "pandas")) { - let kwargs = PyDict::new_bound(py); + if let Ok(pandas) = PyModule::import(py, intern!(py, "pandas")) { + let kwargs = PyDict::new(py); if kwargs.set_item(intern!(py, "utc"), true).is_ok() && kwargs .set_item(intern!(py, "errors"), intern!(py, "coerce")) @@ -4081,10 +3915,11 @@ fn new_py_timestamp_or_datetime(py: Python<'_>, timestamp: u64) -> PyResult= end) { + if date < metadata.start().date() || metadata.end().is_some_and(|end| datetime >= end) { return Err(crate::Error::BadArgument { param_name: "date".to_owned(), desc: "Outside the query range".to_owned(),