Skip to content

Commit

Permalink
reset to: Fix: MacOS14 CIBW bug (won't move wheel after test) (#50)
Browse files Browse the repository at this point in the history
This commit resets the branch to: a0c6073
  • Loading branch information
MusicalNinjaDad committed Jun 5, 2024
1 parent 1b981de commit 7c031d4
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 173 deletions.
28 changes: 8 additions & 20 deletions python/fizzbuzz/fizzbuzzo3.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,7 @@ Usage:
```
"""

from typing import overload

@overload
def fizzbuzz(n: int) -> str:
...

@overload
def fizzbuzz(n: list[int] | slice) -> list[str]:
...

def fizzbuzz(n):
def fizzbuzz(n: int | list[int] | slice) -> str:
"""
Returns the correct fizzbuzz answer for any number or list/range of numbers.
Expand All @@ -31,8 +21,8 @@ def fizzbuzz(n):
n: the number(s) to fizzbuzz
Returns:
In the case of a sinlge number: a `str` with the correct fizzbuzz answer.
In the case of a list or range of inputs: a `list` of `str` with the correct fizzbuzz answers.
A `str` with the correct fizzbuzz answer(s).
In the case of a list or range of inputs the answers will be separated by `, `
Examples:
a single `int`:
Expand All @@ -47,20 +37,18 @@ def fizzbuzz(n):
```
from fizzbuzz.fizzbuzzo3 import fizzbuzz
>>> fizzbuzz([1,3])
['1', 'fizz']
'1, fizz'
```
a `slice` representing a range:
```
from fizzbuzz.fizzbuzzo3 import fizzbuzz
>>> fizzbuzz(slice(1,4,2))
['1', 'fizz']
'1, fizz'
>>> fizzbuzz(slice(1,4))
['1', '2', 'fizz']
'1, 2, fizz'
>>> fizzbuzz(slice(4,1,-1))
['4', 'fizz', '2']
>>> fizzbuzz(slice(1,5,-1))
[]
'4, fizz, 2'
```
Note: Slices are inclusive on the left, exclusive on the right and can contain an optional step.
Negative steps require start > stop, positive stop > start or else will return an empty list.
Negative steps require start > stop.
"""
107 changes: 26 additions & 81 deletions rust/fizzbuzzo3/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use std::ops::Neg;

use fizzbuzz::{FizzBuzz, FizzBuzzAnswer, MultiFizzBuzz};
use pyo3::{
exceptions::PyValueError,
prelude::*,
types::PySlice,
};
use fizzbuzz::{FizzBuzz, MultiFizzBuzz};
use pyo3::{exceptions::PyValueError, prelude::*, types::PySlice};
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};

#[derive(FromPyObject)]
Expand All @@ -29,23 +25,6 @@ impl IntoPy<Py<PyAny>> for MySlice {
}
}

struct FizzBuzzReturn(FizzBuzzAnswer);

impl From<FizzBuzzAnswer> for FizzBuzzReturn {
fn from(value: FizzBuzzAnswer) -> Self {
FizzBuzzReturn(value)
}
}

impl IntoPy<Py<PyAny>> for FizzBuzzReturn {
fn into_py(self, py: Python<'_>) -> Py<PyAny> {
match self.0 {
FizzBuzzAnswer::One(string) => string.into_py(py),
FizzBuzzAnswer::Many(list) => list.into_py(py),
}
}
}

/// Returns the correct fizzbuzz answer for any number or list/range of numbers.
///
/// This is an optimised algorithm compiled in rust. Large lists will utilise multiple CPU cores for processing.
Expand All @@ -55,8 +34,8 @@ impl IntoPy<Py<PyAny>> for FizzBuzzReturn {
/// n: the number(s) to fizzbuzz
///
/// Returns:
/// In the case of a sinlge number: a `str` with the correct fizzbuzz answer.
/// In the case of a list or range of inputs: a `list` of `str` with the correct fizzbuzz answers.
/// A `str` with the correct fizzbuzz answer(s).
/// In the case of a list or range of inputs the answers will be separated by `, `
///
/// Examples:
/// a single `int`:
Expand All @@ -71,25 +50,23 @@ impl IntoPy<Py<PyAny>> for FizzBuzzReturn {
/// ```
/// from fizzbuzz.fizzbuzzo3 import fizzbuzz
/// >>> fizzbuzz([1,3])
/// ['1', 'fizz']
/// '1, fizz'
/// ```
/// a `slice` representing a range:
/// ```
/// from fizzbuzz.fizzbuzzo3 import fizzbuzz
/// >>> fizzbuzz(slice(1,4,2))
/// ['1', 'fizz']
/// '1, fizz'
/// >>> fizzbuzz(slice(1,4))
/// ['1', '2', 'fizz']
/// '1, 2, fizz'
/// >>> fizzbuzz(slice(4,1,-1))
/// ['4', 'fizz', '2']
/// >>> fizzbuzz(slice(1,5,-1))
/// []
/// '4, fizz, 2'
/// ```
/// Note: Slices are inclusive on the left, exclusive on the right and can contain an optional step.
/// Negative steps require start > stop, positive stop > start or else will return an empty list.
/// Negative steps require start > stop.
#[pyfunction]
#[pyo3(name = "fizzbuzz", text_signature = "(n)")]
fn py_fizzbuzz(num: FizzBuzzable) -> PyResult<FizzBuzzReturn> {
fn py_fizzbuzz(num: FizzBuzzable) -> PyResult<String> {
match num {
FizzBuzzable::Int(n) => Ok(n.fizzbuzz().into()),
FizzBuzzable::Float(n) => Ok(n.fizzbuzz().into()),
Expand Down Expand Up @@ -164,15 +141,8 @@ mod tests {
#[pyo3import(py_fizzbuzzo3: from fizzbuzzo3 import fizzbuzz)]
fn test_fizzbuzz_vec() {
let input = vec![1, 2, 3, 4, 5];
let expected = vec![
"1".to_string(),
"2".to_string(),
"fizz".to_string(),
"4".to_string(),
"buzz".to_string(),
];
let result: Vec<String> = fizzbuzz!(input);
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "1, 2, fizz, 4, buzz");
}

#[pyo3test]
Expand All @@ -190,15 +160,8 @@ mod tests {
stop: 6,
step: Some(1),
};
let expected = vec![
"1".to_string(),
"2".to_string(),
"fizz".to_string(),
"4".to_string(),
"buzz".to_string(),
];
let result: Vec<String> = fizzbuzz!(input);
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "1, 2, fizz, 4, buzz");
}

#[pyo3test]
Expand All @@ -209,15 +172,8 @@ mod tests {
stop: 6,
step: None,
};
let expected = vec![
"1".to_string(),
"2".to_string(),
"fizz".to_string(),
"4".to_string(),
"buzz".to_string(),
];
let result: Vec<String> = fizzbuzz!(input);
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "1, 2, fizz, 4, buzz");
}

#[pyo3test]
Expand All @@ -228,9 +184,8 @@ mod tests {
stop: 6,
step: Some(2),
};
let expected = vec!["1".to_string(), "fizz".to_string(), "buzz".to_string()];
let result: Vec<String> = fizzbuzz!(input);
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "1, fizz, buzz");
}

#[pyo3test]
Expand All @@ -241,9 +196,8 @@ mod tests {
stop: 0,
step: Some(1),
};
let result: Vec<String> = fizzbuzz!(input);
let expected: Vec<String> = vec![];
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "");
}

#[pyo3test]
Expand All @@ -254,9 +208,8 @@ mod tests {
stop: 0,
step: Some(-2),
};
let expected = vec!["buzz".to_string(), "fizz".to_string(), "1".to_string()];
let result: Vec<String> = fizzbuzz!(input);
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "buzz, fizz, 1");
}

#[pyo3test]
Expand All @@ -267,14 +220,8 @@ mod tests {
stop: 1,
step: Some(-1),
};
let expected = vec![
"buzz".to_string(),
"4".to_string(),
"fizz".to_string(),
"2".to_string(),
];
let result: Vec<String> = fizzbuzz!(input);
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "buzz, 4, fizz, 2");
}

#[pyo3test]
Expand All @@ -285,10 +232,8 @@ mod tests {
stop: 0,
step: Some(-2),
};

let expected = vec!["fizz".to_string(), "4".to_string(), "2".to_string()];
let result: Vec<String> = fizzbuzz!(input);
assert_eq!(result, expected);
let result: String = fizzbuzz!(input);
assert_eq!(result, "fizz, 4, 2");
}
#[pyo3test]
#[allow(unused_macros)]
Expand Down
49 changes: 0 additions & 49 deletions tests/perf_results.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,52 +92,3 @@ Rust vector, with python list overhead: [1 calls of 10 runs creating and fizzbuz
Rust range: [1 calls of 10 runs fizzbuzzing a range of numbers up to 1000000]
[0.5420241989995702]
```

## Comparing return types (-> str | list[str] vs. -> str)

```text
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ echo "No LTO, Union"
No LTO, Union
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ /workspaces/FizzBuzz/.venv/bin/python /workspaces/FizzBuzz/tests/perftest.py
Rust: [1 calls of 10 runs fizzbuzzing up to 1000000]
[2.7247621990100015]
Rust vector: [1 calls of 10 runs fizzbuzzing a list of numbers up to 1000000]
[1.4409539260086603]
Rust vector, with python list overhead: [1 calls of 10 runs creating and fizzbuzzing a list of numbers up to 1000000]
[1.748141026997473]
Rust range: [1 calls of 10 runs fizzbuzzing a range of numbers up to 1000000]
[1.140464444004465]
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ echo "thin LTO, Union"
thin LTO, Union
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ /workspaces/FizzBuzz/.venv/bin/python /workspaces/FizzBuzz/tests/perftest.py
Rust: [1 calls of 10 runs fizzbuzzing up to 1000000]
[2.573878561001038]
Rust vector: [1 calls of 10 runs fizzbuzzing a list of numbers up to 1000000]
[1.5258527039986802]
Rust vector, with python list overhead: [1 calls of 10 runs creating and fizzbuzzing a list of numbers up to 1000000]
[1.7503311760083307]
Rust range: [1 calls of 10 runs fizzbuzzing a range of numbers up to 1000000]
[1.1543225019995589]
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ echo "fat LTO, Union"
fat LTO, Union
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ /workspaces/FizzBuzz/.venv/bin/python /workspaces/FizzBuzz/tests/perftest.py
Rust: [1 calls of 10 runs fizzbuzzing up to 1000000]
[2.659256437997101]
Rust vector: [1 calls of 10 runs fizzbuzzing a list of numbers up to 1000000]
[1.4467686470015906]
Rust vector, with python list overhead: [1 calls of 10 runs creating and fizzbuzzing a list of numbers up to 1000000]
[1.6921475639974233]
Rust range: [1 calls of 10 runs fizzbuzzing a range of numbers up to 1000000]
[1.1023815070075216]
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ echo "no LTO, String"
no LTO, String
(.venv) pyo3@6195c4a7706f:/workspaces/FizzBuzz$ /workspaces/FizzBuzz/.venv/bin/python /workspaces/FizzBuzz/tests/perftest.py
Rust: [1 calls of 10 runs fizzbuzzing up to 1000000]
[2.6100861899903975]
Rust vector: [1 calls of 10 runs fizzbuzzing a list of numbers up to 1000000]
[0.8597368839982664]
Rust vector, with python list overhead: [1 calls of 10 runs creating and fizzbuzzing a list of numbers up to 1000000]
[1.1903306849999353]
Rust range: [1 calls of 10 runs fizzbuzzing a range of numbers up to 1000000]
[0.6246530729986262]
```
8 changes: 4 additions & 4 deletions tests/perftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ def main():
fbo3times = fbo3timer.repeat(repeat=REPEAT, number=NUMBER)
print(fbo3times)

# print(f"Python: [{REPEAT} calls of {NUMBER} runs fizzbuzzing up to {FIZZBUZZES}]")
# fbpytimer = timeit.Timer(stmt="[fbpy(i) for i in range(1,FIZZBUZZES)]", globals=globals())
# fbpytimes = fbpytimer.repeat(repeat=REPEAT, number=NUMBER)
# print(fbpytimes)
print(f"Python: [{REPEAT} calls of {NUMBER} runs fizzbuzzing up to {FIZZBUZZES}]")
fbpytimer = timeit.Timer(stmt="[fbpy(i) for i in range(1,FIZZBUZZES)]", globals=globals())
fbpytimes = fbpytimer.repeat(repeat=REPEAT, number=NUMBER)
print(fbpytimes)

print(f"Rust vector: [{REPEAT} calls of {NUMBER} runs fizzbuzzing a list of numbers up to {FIZZBUZZES}]")
fbo3vectimer = timeit.Timer(stmt="[fbo3(LISTOFNUMBERS)]", globals=globals())
Expand Down
24 changes: 5 additions & 19 deletions tests/test_fizzbuzzo3.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,17 @@ def test_lazy():
assert fizzbuzz(6) == "fizz"
assert fizzbuzz(15) == "fizzbuzz"


def test_float():
assert fizzbuzz(1.0) == "1"
assert fizzbuzz(3.0) == "fizz"


def test_list():
assert fizzbuzz(
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15],
) == "1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, fizzbuzz".split(", ")

assert fizzbuzz([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15]) == "1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, fizzbuzz"

def test_string():
with pytest.raises(TypeError):
fizzbuzz("1")


def test_1_to_100():
results = [fizzbuzz(i) for i in range(1, 101)]
every_3rd_has_fizz = all("fizz" in r for r in results[2::3])
Expand All @@ -45,24 +39,16 @@ def test_1_to_100():
all_numbers_correct = all(r == str(i + 1) for i, r in enumerate(results) if r not in ("fizz", "buzz", "fizzbuzz"))
assert all_numbers_correct


def test_slice():
assert fizzbuzz(
slice(1, 16, 1),
) == "1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz".split(", ")

assert fizzbuzz(slice(1,16,1)) == "1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz"

# This case is REALLY IMPORTANT as it cannot be tested via rust unit tests...
def test_slice_no_step():
assert fizzbuzz(
slice(1, 16),
) == "1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz".split(", ")

assert fizzbuzz(slice(1,16)) == "1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz"

def test_slice_negative_step():
assert fizzbuzz(slice(15, 0, -3)) == "fizzbuzz, fizz, fizz, fizz, fizz".split(", ")

assert fizzbuzz(slice(15,0,-3)) == "fizzbuzz, fizz, fizz, fizz, fizz"

def test_slice_zero_step():
with pytest.raises(ValueError, match="step cannot be zero"):
fizzbuzz(slice(1, 16, 0))
fizzbuzz(slice(1,16,0))

0 comments on commit 7c031d4

Please sign in to comment.