[20/11/23] Merge dev changes to main

This commit is contained in:
Andrew Conlin 2023-11-20 11:02:04 +00:00 committed by GitHub
commit e38bbac712
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 200 additions and 11 deletions

35
.github/workflows/python.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Python
on:
push:
branches: [ "dev" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.11.2
uses: actions/setup-python@v3
with:
python-version: "3.11.2"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest -v tests

23
.github/workflows/rust.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: Rust
on:
push:
branches: [ "dev" ]
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose

2
.gitignore vendored
View File

@ -72,7 +72,7 @@ docs/_build/
.python-version .python-version
# GitHub Actions # GitHub Actions
.github/ #.github/
# pyenv # pyenv
.env/ .env/

View File

@ -3,8 +3,11 @@
# Fast, simple and accurate Python timing. Written in Rust. # Fast, simple and accurate Python timing. Written in Rust.
![badge](https://github.com/andrwcnln/tictoc-py/actions/workflows/python.yml/badge.svg)
![badge](https://github.com/andrwcnln/tictoc-py/actions/workflows/rust.yml/badge.svg)
## Installation ## Installation
Install with [pip](https://pypi.org/project/pip): Install with [pip](https://pypi.org/project/pip).
```bash ```bash
$ python -m pip install tictoc $ python -m pip install tictoc
``` ```

View File

@ -1,6 +1,11 @@
certifi==2023.7.22 certifi==2023.7.22
charset-normalizer==3.3.2 charset-normalizer==3.3.2
coverage==7.3.2
idna==3.4 idna==3.4
iniconfig==2.0.0
maturin==1.3.1 maturin==1.3.1
packaging==23.2
pluggy==1.3.0
pytest==7.4.3
requests==2.31.0 requests==2.31.0
urllib3==2.0.7 urllib3==2.0.7

View File

@ -1,5 +1,6 @@
use pyo3::prelude::*; use pyo3::prelude::*;
use std::time::Instant; use std::time::Instant;
use pyo3::exceptions::PyException;
#[pyclass] #[pyclass]
#[derive(Clone)] #[derive(Clone)]
@ -19,6 +20,7 @@ struct Init {
time: Instant, time: Instant,
#[pyo3(get)] #[pyo3(get)]
results: Results, results: Results,
status: bool,
} }
#[pymethods] #[pymethods]
@ -34,21 +36,28 @@ impl Init {
Init { Init {
time: Instant::now(), time: Instant::now(),
results: res, results: res,
status: false,
} }
} }
fn tic(&mut self) { fn tic(&mut self) {
self.time = Instant::now() self.time = Instant::now();
self.status = true;
} }
fn toc(&mut self) { fn toc(&mut self) -> PyResult<()> {
let elapsed_time = self.time.elapsed(); if self.status == false {
self.results = Results { Err(PyException::new_err("tic() must be called before toc()"))
nanos: elapsed_time.as_nanos(), } else {
micros: elapsed_time.as_micros(), let elapsed_time = self.time.elapsed();
millis: elapsed_time.as_millis(), self.results = Results {
seconds: elapsed_time.as_secs_f64(), nanos: elapsed_time.as_nanos(),
}; micros: elapsed_time.as_micros(),
millis: elapsed_time.as_millis(),
seconds: elapsed_time.as_secs_f64(),
};
Ok(())
}
} }
} }
@ -57,3 +66,27 @@ fn tictoc(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<Init>()?; m.add_class::<Init>()?;
Ok(()) Ok(())
} }
#[test]
fn test_new() {
let init = Init::new();
assert_eq!(init.results.nanos,0);
}
#[test]
fn test_tic() {
let mut init = Init::new();
let time1 = init.time;
init.tic();
let time2 = init.time;
assert!(time2 > time1)
}
#[test]
fn test_toc() {
let mut init = Init::new();
init.tic();
println!("{}","test");
let _ = init.toc();
assert!(init.results.nanos > 0)
}

4
tests/pytest.ini Normal file
View File

@ -0,0 +1,4 @@
[pytest]
python_files = test*.py
python_classes = test
python_functions = test*

86
tests/test.py Normal file
View File

@ -0,0 +1,86 @@
import pytest
import tictoc
import time
import math
@pytest.fixture
def t():
t = tictoc.init()
return t
class testFunctionality:
def testBasic(self, t):
t.tic()
print("test")
t.toc()
assert t.results.seconds > 0
def testOverwrite(self, t):
t.tic()
print("test")
t.toc()
firstResult = t.results.seconds
print("test2")
t.toc()
secondResult = t.results.seconds
assert firstResult < secondResult
class testInvalid:
def testNoInit(self):
with pytest.raises(Exception):
t.tic()
def testTocBeforeTic(self, t):
with pytest.raises(Exception):
t.toc()
@pytest.mark.parametrize("sleepTime", [0.05, 0.5, 1])
class testAccuracy:
@pytest.fixture(scope="class")
def tol(self):
return 0.0006
def testSingleCall(self, t, sleepTime, tol):
t.tic()
time.sleep(sleepTime)
t.toc()
assert (t.results.seconds > sleepTime) & (
t.results.seconds < (t.results.seconds + tol)
)
def testMultipleCalls(self, t, sleepTime, tol):
t.tic()
time.sleep(sleepTime)
t.toc()
time.sleep(sleepTime)
t.toc()
assert (t.results.seconds > sleepTime * 2) & (
t.results.seconds < (t.results.seconds + tol)
)
class testConsistency:
def testMicros(self, t):
t.tic()
print("test")
t.toc()
assert t.results.micros == (math.floor(t.results.nanos * pow(10, -3)))
def testMillis(self, t):
t.tic()
print("test")
t.toc()
assert t.results.millis == (math.floor(t.results.nanos * pow(10, -6)))
def testSeconds(self, t):
t.tic()
print("test")
t.toc()
assert t.results.seconds == round(
(t.results.nanos * pow(10, -9)), 9
) # f64 vs u128, hence the round