Compare commits

..

28 Commits

Author SHA1 Message Date
5b69fe25b4 Link from Day 5 2025-10-24 20:34:06 +00:00
97d4d9c9a7 Fix #12
accidentally opening a jupyter notebook in api/
caused apidoc to try to incorporate that into
the api docs.
2025-10-24 15:10:13 -05:00
e3ffd2210b Merge pull request 'Implement Unit Testing for fancymath' (#8) from unit_tests into main
Reviewed-on: #8
2025-10-24 17:10:58 +00:00
aa7dc496dc Merge pull request 'Add subtests for test_cross_product.' (#11) from test/vector-cross-subtests into unit_tests
Reviewed-on: #11
Reviewed-by: Tim Diller <tim@dillerdigital.com>
2025-10-24 16:09:11 +00:00
Corran Webster
66123f6064 Add subtests for test_cross_product. 2025-10-24 16:54:47 +01:00
913169fe68 Merge pull request 'unit_tests_ambar' (#10) from unit_tests_ambar into unit_tests
Reviewed-on: #10
Reviewed-by: Tim Diller <tim@dillerdigital.com>
2025-10-24 15:42:56 +00:00
5850743394 Merge branch 'unit_tests' into unit_tests_ambar 2025-10-24 10:42:22 -05:00
79b6c10b70 Corrected syntax for vecotr.abs() test 2025-10-24 11:38:26 -04:00
491c531ed8 Merge pull request 'Add cross-product and tests' (#9) from enh/cross-product into unit_tests
Reviewed-on: #9
2025-10-24 15:25:26 +00:00
Corran Webster
437be17f51 Add cross product impleimentation 2025-10-24 16:21:50 +01:00
64f06ce7c1 Merge branch 'unit_tests' into enh/cross-product 2025-10-24 15:19:46 +00:00
4d5e2db71a add test for proper failure of Vector.dot 2025-10-24 10:18:04 -05:00
b613241807 Add unit test for Vector.abs 2025-10-24 11:17:40 -04:00
Corran Webster
13ac74132c Add cross-product and tests 2025-10-24 16:13:25 +01:00
35a1705570 Add unit test for Vecotr.abs method 2025-10-24 11:10:39 -04:00
352480ac14 add test_dot_product to test_vector.py 2025-10-24 10:08:28 -05:00
6ba84c9859 add tests for adding Vectors 2025-10-24 09:58:26 -05:00
6d98c08e89 tests for is_even and is_odd 2025-10-24 09:46:21 -05:00
56c892d944 make test folder importable 2025-10-24 09:34:21 -05:00
922ed4d394 initial commit test suite 2025-10-24 09:33:33 -05:00
a3e89d3460 Fix formatting typo in README 2025-10-24 13:58:25 +00:00
b90d601490 Day 4 notebook and README links 2025-10-23 13:48:00 -05:00
6ae7933baa add assertion to main block in vector.py as an example of simple test 2025-10-23 13:36:54 -05:00
4198198e02 logger handles exception 2025-10-23 11:37:12 -05:00
bac8d74803 add logging and main function to fancymath 2025-10-23 11:25:35 -05:00
a40a2ff442 Update README with links from Day 3 2025-10-22 18:25:43 +00:00
830eda6e1c GIAT convert_mass example from class 2025-10-22 13:21:46 -05:00
68d6df3a4f add __name__ == '__main__' block in fancy math 2025-10-22 13:19:34 -05:00
12 changed files with 2224 additions and 5 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@
*.egg-info
doc/_build/
*.ipynb_checkpoints/
fancymath.log

View File

@@ -28,5 +28,28 @@ $ pip install -e .
# Day 3 Resources
- *Python Typing is for Humans*: [Unital.dev blog](https://www.unital.dev/blog/python-typing-is-for-humans/) or [LinkedIn](https://www.linkedin.com/pulse/python-typing-humans-corran-webster-u66ee)
- [*Domain Driven Design*](https://www.oreilly.com/library/view/domain-driven-design-tackling/0321125215/) (O'Reilly)
- [PyData Sphinx Theme](https://pydata-sphinx-theme.readthedocs.io/en/stable/)
- [Sphinx AutoAPI](https://sphinx-autoapi.readthedocs.io/en/latest/)
- [Sphinx AutoAPI](https://sphinx-autoapi.readthedocs.io/en/latest/)
- Find the refactoring Give It A Try in `files/convert_mass.py`
# Day 4 Resourecs
- The [Day 4 Notebook](files/Day4.ipynb) is in `files/Day4.ipynb`.
- [Arrays and Lists](https://blog.dillerdigital.com/arrays-and-lists/) from the Diller Digital Blog
- [Cython](https://cython.org/) - tool for building C extensions in Python. Particularly good for seamlessly handing off Numpy `ndarray`s to C-array code. Tim and Corran's former coworker Kurt Smith literally [wrote the book](https://www.oreilly.com/library/view/cython/9781491901731/) on Cython.
- [`ctypes`](https://docs.python.org/3/library/ctypes.html) - a lower level tool for extending Python with C.
- [Tim's favorite logging setup](https://github.com/timdiller/favorite_logging_setup) on Github.
- [`line_profiler`](https://kernprof.readthedocs.io/en/latest/#line-profiler-basic-usage) written by Tim and Corran's former coworker Robert Kern (hence the name `kernprof` for the command line tool). Summary of usage:
```
> pip install line_profiler
# add `from line_profiler import profile` to module to be profiled
# decorate functions to be profiled with `@profile`
> kernprof -l module_to_profile.py
Wrote profile results to 'module_to_profile.py.lprof'
Inspect results with:
python -m line_profiler -rmt module_to_profile.py.lprof
> python -m line_profiler -rmt module_to_profile.py.lprof
```
# Day 5 Resources
- [5 Worlds](https://www.joelonsoftware.com/2002/05/06/five-worlds/) from Joel Spolsky's blog.

View File

@@ -17,7 +17,13 @@ release = '0.0.1'
extensions = ["sphinx.ext.autodoc", "sphinx.ext.viewcode"]
templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.ipynb_checkpoints']
exclude_patterns = [
'_build',
'Thumbs.db',
'.DS_Store',
'.ipynb_checkpoints',
'api/.ipynb_checkpoints'
]

2001
files/Day4.ipynb Normal file

File diff suppressed because it is too large Load Diff

27
files/convert_mass.py Normal file
View File

@@ -0,0 +1,27 @@
''' Refactor the following code
mass_oz = [0.5, 0.6, 1.2, 3.4]
mass_g = [mass * 28.3496 for mass in mass_oz]
mass_kg = [mass * 28.3496 / 1000 for mass in mass_oz]
'''
# Refactor Step 1
G_OZ = 28.3496
KG_OZ = G_OZ / 1000
mass_oz = [0.5, 0.6, 1.2, 3.4]
mass_g = [mass * G_OZ for mass in mass_oz]
mass_kg = [mass * KG_OZ for mass in mass_oz]
# Refactor Step 2
def convert_mass(mass_oz, conv_factor):
return [m * conv_factor for m in mass_oz]
# Refactor Step 3
if __name__ == "__main__":
mass_oz = [0.5, 0.6, 1.2, 3.4, 5.6, 7.8, 9.1]
print("Ounces")
print(", ".join(str(m) for m in mass_oz))
print("Grams")
print(", ".join(str(m) for m in convert_mass(mass_oz, G_OZ)))
print("Kilograms")
print(", ".join(str(m) for m in convert_mass(mass_oz, KG_OZ)))

39
src/fancymath/__main__.py Normal file
View File

@@ -0,0 +1,39 @@
import logging
root_logger = logging.getLogger()
fmt = "%(asctime)s %(levelname)-8.8s [%(name)s:%(lineno)s] %(message)s"
formatter = logging.Formatter(fmt)
sh = logging.StreamHandler()
sh.setFormatter(formatter)
sh.setLevel(logging.INFO)
fh = logging.FileHandler("fancymath.log")
fh.setFormatter(formatter)
fh.setLevel(logging.NOTSET)
root_logger.addHandler(sh)
root_logger.addHandler(fh)
root_logger.setLevel(logging.NOTSET)
logger = logging.getLogger(__name__)
logger.info("Welcome to FancyMath, a silly library for demonstrations.")
from fancymath.vector import Vector
v1 = Vector(1,2,3)
v2 = Vector(2,3,4)
v3 = v1.dot(v2)
logger.info(f"{v1=}")
logger.info(f"{v2=}")
logger.info(f"{v3=}")
try:
v4 = v2.dot([1,2,3])
except ValueError as err:
logger.exception(err)

View File

@@ -12,4 +12,19 @@ def fact(n: int) -> int:
if n == 1:
return 1
else:
return n * fact(n - 1)
return n * fact(n - 1)
def is_even(x):
return x % 2 == 0
def is_odd(x):
return x % 2 == 1
if __name__ == '__main__':
n = 5
assert fact(n) == 120
assert add(5, 6) == 11
print("Tests passed")

View File

@@ -1,8 +1,11 @@
"""This module defines the Vector class. """
import logging
from math import acos, sqrt
logger = logging.getLogger(__name__)
class Vector(object):
def __init__(self, x, y, z):
"""Constructor method."""
@@ -12,6 +15,9 @@ class Vector(object):
def dot(self, v):
"""Returns the dot product with Vector *v*."""
if not isinstance(v, self.__class__):
msg = f"Expected an instance of {self.__class__}, but got {type(v)} instead."
raise ValueError(msg)
d = self.x * v.x + self.y * v.y + self.z * v.z
return d
@@ -24,9 +30,26 @@ class Vector(object):
s = "Vector(x=%s, y=%s, z=%s)" % (self.x, self.y, self.z)
return s
def __add__(self, other):
x = self.x + other.x
y = self.y + other.y
z = self.z + other.z
return self.__class__(x, y, z)
def __mul__(self, other):
if not isinstance(other, Vector):
return NotImplemented
x = self.y * other.z - self.z * other.y
y = self.z * other.x - self.x * other.z
z = self.x * other.y - self.y * other.x
return self.__class__(x, y, z)
if __name__ == "__main__":
v1 = Vector(2.0, 13.0, -1.0)
v1 = Vector(3, 4, 0)
print(v1, " magnitude is", v1.abs())
v2 = Vector(1.0, 2.0, 3.0)
print("v1.dot(v2) =", v1.dot(v2))
assert v1.abs() == 5
print("Tests passed!")

0
test/__init__.py Normal file
View File

25
test/test_math.py Normal file
View File

@@ -0,0 +1,25 @@
import unittest
from fancymath.math import is_even, is_odd
class TestMath(unittest.TestCase):
def test_is_even(self):
"Test the is_even function"
self.assertTrue(is_even(2))
self.assertTrue(is_even(-4))
self.assertTrue(is_even(0))
self.assertFalse(is_even(1))
self.assertFalse(is_even(2.5))
def test_is_odd(self):
"Test the is_odd function"
self.assertTrue(is_odd(3))
self.assertTrue(is_odd(-5))
self.assertFalse(is_odd(0))
self.assertFalse(is_odd(2))
self.assertFalse(is_odd(2.5))
if __name__ == "__main__":
unittest.main()

0
test/test_util.py Normal file
View File

59
test/test_vector.py Normal file
View File

@@ -0,0 +1,59 @@
import unittest
from fancymath.vector import Vector
class TestVector(unittest.TestCase):
def test_cross_product(self):
# Dictionary of (v1, v2): v3
values = {
(Vector(1, 2, 3), Vector(3, 2, 1)): Vector(-4, 8, -4),
(Vector(0, 0, 0), Vector(1, 2, 3)): Vector(0, 0, 0),
(Vector(1, 0, 0), Vector(1, 0, 0)): Vector(0, 0, 0),
}
for inputs, expected in values.items():
v1, v2 = inputs
with self.subTest(v1=v1, v2=v2):
v3 = v1 * v2
self.assertIsInstance(v3, Vector)
self.assertEqual(v3.x, expected.x)
self.assertEqual(v3.y, expected.y)
self.assertEqual(v3.z, expected.z)
def test_cross_product_failure(self):
v1 = Vector(1, 2, 3)
v2 = (3, 2, 1)
with self.assertRaises(TypeError):
v1 * v2
def test_add_vector(self):
v1 = Vector(1, 2, 3)
v2 = Vector(-3, -2, -1)
v3 = v1 + v2
self.assertIsInstance(v3, Vector)
self.assertEqual(v3.x, v1.x + v2.x)
def test_abs(self):
v1 = Vector(0, 0, 0)
v2 = Vector(1, 2, 2)
v3 = Vector(1, -2, 2)
self.assertEqual(v1.abs(), 0)
self.assertEqual(v2.abs(), 3)
self.assertEqual(v2.abs(), v3.abs())
def test_dot_failure(self):
with self.assertRaises(ValueError):
v1 = Vector(1, 2, 3)
v1.dot(3)
def test_dot_product(self):
v1 = Vector(1, 2, 3)
v2 = Vector(-3, -2, -1)
v3 = v1.dot(v2)
self.assertEqual(v3,v1.x * v2.x + v1.y * v2.y + v1.z * v2.z)
vzero = Vector(0, 0, 0)
self.assertEqual(v1.dot(vzero),0)