From 93d11c8da61a792766994754e75b08c5a22b7d04 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 10 Oct 2021 16:45:48 +0800 Subject: [PATCH 01/11] draft --- ulist/Cargo.lock | 255 +++++++++++++++++++++++++++++++++++++++++++++++ ulist/Cargo.toml | 18 ++++ ulist/src/lib.rs | 39 ++++++++ 3 files changed, 312 insertions(+) create mode 100644 ulist/Cargo.lock create mode 100644 ulist/Cargo.toml create mode 100644 ulist/src/lib.rs diff --git a/ulist/Cargo.lock b/ulist/Cargo.lock new file mode 100644 index 0000000..d6cfd1d --- /dev/null +++ b/ulist/Cargo.lock @@ -0,0 +1,255 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "indoc" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" +dependencies = [ + "indoc-impl", + "proc-macro-hack", +] + +[[package]] +name = "indoc-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", + "syn", + "unindent", +] + +[[package]] +name = "instant" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "libc" +version = "0.2.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "once_cell" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "paste" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" +dependencies = [ + "paste-impl", + "proc-macro-hack", +] + +[[package]] +name = "paste-impl" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" +dependencies = [ + "proc-macro-hack", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro2" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "pyo3" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35100f9347670a566a67aa623369293703322bb9db77d99d7df7313b575ae0c8" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "parking_lot", + "paste", + "pyo3-build-config", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d12961738cacbd7f91b7c43bc25cfeeaa2698ad07a04b3be0aa88b950865738f" +dependencies = [ + "once_cell", +] + +[[package]] +name = "pyo3-macros" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0bc5215d704824dfddddc03f93cb572e1155c68b6761c37005e1c288808ea8" +dependencies = [ + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71623fc593224afaab918aa3afcaf86ed2f43d34f6afde7f3922608f253240df" +dependencies = [ + "proc-macro2", + "pyo3-build-config", + "quote", + "syn", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "syn" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "ulist" +version = "0.1.0" +dependencies = [ + "pyo3", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "unindent" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/ulist/Cargo.toml b/ulist/Cargo.toml new file mode 100644 index 0000000..7999a9a --- /dev/null +++ b/ulist/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "ulist" +version = "0.1.0" +authors = ["tushushu"] +edition = "2018" + +[lib] +name = "ulist" +# "cdylib" is necessary to produce a shared library for Python to import from. +# +# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able +# to `use ulist;` unless the "rlib" or "lib" crate type is also included, e.g.: +# crate-type = ["cdylib", "rlib"] +crate-type = ["cdylib"] + +[dependencies.pyo3] +version = "0.14.5" +features = ["extension-module"] \ No newline at end of file diff --git a/ulist/src/lib.rs b/ulist/src/lib.rs new file mode 100644 index 0000000..b3066f4 --- /dev/null +++ b/ulist/src/lib.rs @@ -0,0 +1,39 @@ +use pyo3::prelude::*; + +/// A class to bind Rust Vector. +#[pyclass] +struct List { + values: Vec, + dtype: String, +} + +#[pymethods] +impl List { + #[new] + fn new(values: Vec, dtype: String) -> Self { + List { values, dtype } + } + + pub fn sum(&self) -> i32 { + self.values.iter().sum() + } + + pub fn min(&self) -> i32 { + *self.values.iter().min().unwrap() + } + + pub fn max(&self) -> i32 { + *self.values.iter().max().unwrap() + } + +} + +/// A Python module implemented in Rust. The name of this function must match +/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to +/// import the module. +#[pymodule] +fn ulist(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + + Ok(()) +} From cdc4ec73217663a5facfe394837b197b9385fde4 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 7 Nov 2021 11:13:09 +0800 Subject: [PATCH 02/11] size and mean methods. --- ulist/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ulist/src/lib.rs b/ulist/src/lib.rs index b3066f4..3fc7dcf 100644 --- a/ulist/src/lib.rs +++ b/ulist/src/lib.rs @@ -18,6 +18,14 @@ impl List { self.values.iter().sum() } + pub fn mean(&self) -> f32 { + self.sum() as f32 / self.values.len() as f32 + } + + pub fn size(&self) -> i32 { + self.values.len() as i32 + } + pub fn min(&self) -> i32 { *self.values.iter().min().unwrap() } @@ -25,7 +33,6 @@ impl List { pub fn max(&self) -> i32 { *self.values.iter().max().unwrap() } - } /// A Python module implemented in Rust. The name of this function must match From 82fc39049d26af38fb7aa37cb0f74b2705ce7a1d Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 7 Nov 2021 11:13:21 +0800 Subject: [PATCH 03/11] Maturin --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 7c76f91..0aa56c5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # ulist Ultra fast list - Python bindings to Rust Vector. + + +### Maturin +Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages. +* `maturin publish` builds the crate into python packages and publishes them to pypi. +* `maturin build` builds the wheels and stores them in a folder (target/wheels by default), but doesn't upload them. It's possible to upload those with twine. +* `maturin develop` builds the crate and installs it as a python module directly in the current virtualenv. Note that while maturin develop is faster, it doesn't support all the feature that running pip install after `maturin build` supports. \ No newline at end of file From 5d13949e654004ba73b5327406eddd59aed3328a Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 7 Nov 2021 14:02:51 +0800 Subject: [PATCH 04/11] add len method. --- ulist/src/lib.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/ulist/src/lib.rs b/ulist/src/lib.rs index 3fc7dcf..c3d0b0b 100644 --- a/ulist/src/lib.rs +++ b/ulist/src/lib.rs @@ -1,3 +1,4 @@ +use pyo3::class::sequence::PySequenceProtocol; use pyo3::prelude::*; /// A class to bind Rust Vector. @@ -14,24 +15,31 @@ impl List { List { values, dtype } } - pub fn sum(&self) -> i32 { - self.values.iter().sum() + // Arrange the following methods in alphabetical order. + pub fn max(&self) -> i32 { + *self.values.iter().max().unwrap() } - pub fn mean(&self) -> f32 { self.sum() as f32 / self.values.len() as f32 } - pub fn size(&self) -> i32 { - self.values.len() as i32 - } - pub fn min(&self) -> i32 { *self.values.iter().min().unwrap() } - pub fn max(&self) -> i32 { - *self.values.iter().max().unwrap() + pub fn size(&self) -> usize { + self.values.len() + } + + pub fn sum(&self) -> i32 { + self.values.iter().sum() + } +} + +#[pyproto] +impl PySequenceProtocol for List { + fn __len__(&self) -> usize { + self.values.len() } } From d9786739ac629b5852d35ccfc0078fee97efe0cf Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 7 Nov 2021 14:02:57 +0800 Subject: [PATCH 05/11] release mode --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0aa56c5..9c6178f 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,5 @@ Ultra fast list - Python bindings to Rust Vector. Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages. * `maturin publish` builds the crate into python packages and publishes them to pypi. * `maturin build` builds the wheels and stores them in a folder (target/wheels by default), but doesn't upload them. It's possible to upload those with twine. -* `maturin develop` builds the crate and installs it as a python module directly in the current virtualenv. Note that while maturin develop is faster, it doesn't support all the feature that running pip install after `maturin build` supports. \ No newline at end of file +* `maturin develop` builds the crate and installs it as a python module directly in the current virtualenv. Note that while maturin develop is faster, it doesn't support all the feature that running pip install after `maturin build` supports. +* `marturin build --release` If we want to benchmark the package. From fee4769d0270759aa5763fd550551040abe677c9 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sat, 13 Nov 2021 12:40:10 +0800 Subject: [PATCH 06/11] Polymorphism for List --- ulist/Cargo.lock | 83 ++++++++++++++++++++++++++++++++++++++ ulist/Cargo.toml | 3 ++ ulist/src/lib.rs | 102 +++++++++++++++++++++++++++++++++++++---------- 3 files changed, 167 insertions(+), 21 deletions(-) diff --git a/ulist/Cargo.lock b/ulist/Cargo.lock index d6cfd1d..a4d475b 100644 --- a/ulist/Cargo.lock +++ b/ulist/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "bitflags" version = "1.3.2" @@ -59,6 +65,82 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "num" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -217,6 +299,7 @@ dependencies = [ name = "ulist" version = "0.1.0" dependencies = [ + "num", "pyo3", ] diff --git a/ulist/Cargo.toml b/ulist/Cargo.toml index 7999a9a..28e8615 100644 --- a/ulist/Cargo.toml +++ b/ulist/Cargo.toml @@ -13,6 +13,9 @@ name = "ulist" # crate-type = ["cdylib", "rlib"] crate-type = ["cdylib"] +[dependencies] +num = "0.4.0" + [dependencies.pyo3] version = "0.14.5" features = ["extension-module"] \ No newline at end of file diff --git a/ulist/src/lib.rs b/ulist/src/lib.rs index c3d0b0b..f1d8963 100644 --- a/ulist/src/lib.rs +++ b/ulist/src/lib.rs @@ -1,45 +1,104 @@ +use num::traits::AsPrimitive; use pyo3::class::sequence::PySequenceProtocol; use pyo3::prelude::*; +use std::iter::Sum; -/// A class to bind Rust Vector. +/// An abstract List. +trait List<'a, T> +where + T: AsPrimitive + Sum<&'a T>, +{ + fn values(&'a self) -> &'a Vec; + + // Arrange the following methods in alphabetical order. + fn max(&'a self) -> T; + + fn mean(&'a self) -> f32 { + let numeritor: f32 = self.sum().as_(); + let denominator: f32 = self.size().as_(); + numeritor / denominator + } + + fn min(&'a self) -> T; + + fn size(&'a self) -> usize { + self.values().len() + } + + fn sum(&'a self) -> T { + self.values().iter().sum() + } +} + +/// List for f32. #[pyclass] -struct List { - values: Vec, - dtype: String, +struct FloatList { + list: Vec, +} + +impl<'a> List<'a, f32> for FloatList { + fn values(&'a self) -> &'a Vec { + &self.list + } + + fn max(&'a self) -> f32 { + self.values() + .iter() + .fold(f32::NEG_INFINITY, |x, &y| x.max(y)) + } + + fn min(&'a self) -> f32 { + self.values().iter().fold(f32::INFINITY, |x, &y| x.min(y)) + } } #[pymethods] -impl List { +impl FloatList { #[new] - fn new(values: Vec, dtype: String) -> Self { - List { values, dtype } + fn new(list: Vec) -> Self { + FloatList { list } } +} - // Arrange the following methods in alphabetical order. - pub fn max(&self) -> i32 { - *self.values.iter().max().unwrap() +#[pyproto] +impl PySequenceProtocol for FloatList { + fn __len__(&self) -> usize { + self.size() } - pub fn mean(&self) -> f32 { - self.sum() as f32 / self.values.len() as f32 +} + +/// List for i32. +#[pyclass] +struct IntegerList { + list: Vec, +} + +impl<'a> List<'a, i32> for IntegerList { + fn values(&'a self) -> &'a Vec { + &self.list } - pub fn min(&self) -> i32 { - *self.values.iter().min().unwrap() + fn max(&'a self) -> i32 { + *self.values().iter().max().unwrap() } - pub fn size(&self) -> usize { - self.values.len() + fn min(&'a self) -> i32 { + *self.values().iter().min().unwrap() } +} - pub fn sum(&self) -> i32 { - self.values.iter().sum() +#[pymethods] +impl IntegerList { + #[new] + fn new(list: Vec) -> Self { + IntegerList { list } } } #[pyproto] -impl PySequenceProtocol for List { +impl PySequenceProtocol for IntegerList { fn __len__(&self) -> usize { - self.values.len() + self.size() } } @@ -48,7 +107,8 @@ impl PySequenceProtocol for List { /// import the module. #[pymodule] fn ulist(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_class::()?; + m.add_class::()?; + m.add_class::()?; Ok(()) } From c46984cf2b93cddfbf54eff1f2c10c86bc51a895 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 14 Nov 2021 15:34:41 +0800 Subject: [PATCH 07/11] fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c6178f..b25e5c9 100644 --- a/README.md +++ b/README.md @@ -7,4 +7,4 @@ Build and publish crates with pyo3, rust-cpython and cffi bindings as well as ru * `maturin publish` builds the crate into python packages and publishes them to pypi. * `maturin build` builds the wheels and stores them in a folder (target/wheels by default), but doesn't upload them. It's possible to upload those with twine. * `maturin develop` builds the crate and installs it as a python module directly in the current virtualenv. Note that while maturin develop is faster, it doesn't support all the feature that running pip install after `maturin build` supports. -* `marturin build --release` If we want to benchmark the package. +* `maturin build --release` If we want to benchmark the package. From b737252154299660e6164c8e6bea1f47c224fa49 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 14 Nov 2021 16:48:03 +0800 Subject: [PATCH 08/11] add unit tests. --- test.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 test.py diff --git a/test.py b/test.py new file mode 100644 index 0000000..e752afb --- /dev/null +++ b/test.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +""" +@Author: tushushu +@Date: 2021-11-14 16:02:00 +""" +import pytest +from ulist import FloatList, IntegerList +from typing import Union, List, Optional + +LIST_TYPE = Union[FloatList, IntegerList] +NUM_TYPE = Union[float, int] + + +@pytest.mark.parametrize( + "test_class, nums", + [(FloatList, [1.0, 2.0, 3.0, 4.0, 5.0]), (IntegerList, [1, 2, 3, 4, 5])], +) +@pytest.mark.parametrize( + "test_method, expected_value, expected_type", + [ + ("max", 5.0, None), + ("mean", 3.0, float), + ("min", 1.0, None), + ("size", 5, int), + ("sum", 15.0, None), + ], +) +def test( + test_class: LIST_TYPE, + nums: List[NUM_TYPE], + test_method: str, + expected_value: NUM_TYPE, + expected_type: Optional[NUM_TYPE], +) -> None: + arr = test_class(nums) + result = getattr(arr, test_method)() + msg = ( + f"test_class - {test_class}" + + f" test_method - {test_method}" + + f" result - {result}" + + f" expected - {expected_value}" + ) + assert result == expected_value, msg + + if expected_type is None: + if test_class is FloatList: + expected_type = float + elif test_class is IntegerList: + expected_type = int + assert type(result) == expected_type, msg From 11eded990578304c81ad8db04ec850bd885f8367 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 14 Nov 2021 16:48:33 +0800 Subject: [PATCH 09/11] gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index b6e4761..46147bb 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,6 @@ dmypy.json # Pyre type checker .pyre/ + +# VS Code +.vscode From 48debe4f23f3be5fea600e8d6d86ba127566d27a Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 14 Nov 2021 16:48:51 +0800 Subject: [PATCH 10/11] expose rust methods to python. --- ulist/src/lib.rs | 72 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 16 deletions(-) diff --git a/ulist/src/lib.rs b/ulist/src/lib.rs index f1d8963..db3c8e0 100644 --- a/ulist/src/lib.rs +++ b/ulist/src/lib.rs @@ -36,6 +36,34 @@ struct FloatList { list: Vec, } +#[pymethods] +impl FloatList { + #[new] + fn new(list: Vec) -> Self { + FloatList { list } + } + + pub fn max(&self) -> f32 { + List::max(self) + } + + pub fn mean(&self) -> f32 { + List::mean(self) + } + + pub fn min(&self) -> f32 { + List::min(self) + } + + pub fn size(&self) -> usize { + List::size(self) + } + + pub fn sum(&self) -> f32 { + List::sum(self) + } +} + impl<'a> List<'a, f32> for FloatList { fn values(&'a self) -> &'a Vec { &self.list @@ -52,14 +80,6 @@ impl<'a> List<'a, f32> for FloatList { } } -#[pymethods] -impl FloatList { - #[new] - fn new(list: Vec) -> Self { - FloatList { list } - } -} - #[pyproto] impl PySequenceProtocol for FloatList { fn __len__(&self) -> usize { @@ -73,6 +93,34 @@ struct IntegerList { list: Vec, } +#[pymethods] +impl IntegerList { + #[new] + fn new(list: Vec) -> Self { + IntegerList { list } + } + + pub fn max(&self) -> i32 { + List::max(self) + } + + pub fn mean(&self) -> f32 { + List::mean(self) + } + + pub fn min(&self) -> i32 { + List::min(self) + } + + pub fn size(&self) -> usize { + List::size(self) + } + + pub fn sum(&self) -> i32 { + List::sum(self) + } +} + impl<'a> List<'a, i32> for IntegerList { fn values(&'a self) -> &'a Vec { &self.list @@ -87,14 +135,6 @@ impl<'a> List<'a, i32> for IntegerList { } } -#[pymethods] -impl IntegerList { - #[new] - fn new(list: Vec) -> Self { - IntegerList { list } - } -} - #[pyproto] impl PySequenceProtocol for IntegerList { fn __len__(&self) -> usize { From 4b787e0d8c737031d27483ca74a8fc507c7b8d22 Mon Sep 17 00:00:00 2001 From: tushushu Date: Sun, 14 Nov 2021 16:50:46 +0800 Subject: [PATCH 11/11] test len method. --- test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test.py b/test.py index e752afb..c9bbe80 100644 --- a/test.py +++ b/test.py @@ -48,3 +48,5 @@ def test( elif test_class is IntegerList: expected_type = int assert type(result) == expected_type, msg + + assert len(arr) == arr.size()