fibonacci-tdd-kataa 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+
2
+ name: Publish package
3
+
4
+ on:
5
+ release:
6
+ types: [published]
7
+
8
+ permissions:
9
+ id-token: write
10
+
11
+ jobs:
12
+ test:
13
+ uses: ./.github/workflows/tests.yml
14
+
15
+ build-and-publish:
16
+ needs: test
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+
24
+ - name: Build package
25
+ run: uv build
26
+
27
+ - name: Publish to PyPI
28
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,33 @@
1
+
2
+ name: Tests
3
+
4
+ on:
5
+ push:
6
+ branches: [main]
7
+ pull_request:
8
+ branches: [main]
9
+ workflow_call:
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ python-version: ["3.12"]
17
+
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install dependencies
27
+ run: uv sync --all-groups
28
+
29
+ - name: Lint
30
+ run: uv run ruff check .
31
+
32
+ - name: Run tests
33
+ run: uv run pytest --cov=src --cov-report=term-missing
@@ -0,0 +1,5 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ .pytest_cache/
5
+ __marimo__/
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.5
2
+ Name: fibonacci-tdd-kataa
3
+ Version: 0.1.0
4
+ Summary: A TDD kata: Fibonacci, from notebook exploration to a tested, published package
5
+ Author-email: malak khalil <malak.khalil@lau.edu>
6
+ Requires-Python: >=3.12
File without changes
@@ -0,0 +1,157 @@
1
+ import marimo
2
+
3
+ __generated_with = "0.24.2"
4
+ app = marimo.App(width="medium")
5
+
6
+
7
+ @app.cell
8
+ def _():
9
+ import marimo as mo
10
+ import pytest
11
+
12
+ return (mo,)
13
+
14
+
15
+ @app.cell
16
+ def _(mo):
17
+ mo.md("""
18
+ # Fibonacci TDD Kata
19
+
20
+ ## Objective
21
+
22
+ This notebook demonstrates the Test-Driven Development workflow by implementing
23
+ the Fibonacci sequence step by step.
24
+
25
+ ## Fibonacci sequence
26
+
27
+ The sequence is defined as:
28
+
29
+ - F(0) = 0
30
+ - F(1) = 1
31
+ - F(n) = F(n - 1) + F(n - 2) for n >= 2
32
+
33
+ ## TDD workflow
34
+
35
+ The implementation follows the Red → Green → Refactor cycle:
36
+
37
+ 1. Write tests that initially fail.
38
+ 2. Implement the function until all tests pass.
39
+ 3. Refactor the code while keeping the test suite green.
40
+
41
+ ## Interactive demo
42
+
43
+ Use the widget below to select a value of `n` and display the corresponding
44
+ Fibonacci number.
45
+ """)
46
+ return
47
+
48
+
49
+ @app.function
50
+ def fibonacci(n):
51
+ def fib_pair(k):
52
+ if k == 0:
53
+ return 0, 1
54
+
55
+ a, b = fib_pair(k // 2)
56
+
57
+ c = a * (2 * b - a)
58
+ d = a * a + b * b
59
+
60
+ if k % 2 == 0:
61
+ return c, d
62
+ return d, c + d
63
+
64
+ return fib_pair(n)[0]
65
+
66
+
67
+ @app.cell
68
+ def _():
69
+ def test_fibonacci_zero():
70
+ assert fibonacci(0) == 0
71
+
72
+ def test_fibonacci_one():
73
+ assert fibonacci(1) == 1
74
+
75
+ def test_fibonacci_two():
76
+ assert fibonacci(2) == 1
77
+
78
+ def test_fibonacci_three():
79
+ assert fibonacci(3) == 2
80
+
81
+ def test_fibonacci_four():
82
+ assert fibonacci(4) == 3
83
+
84
+ def test_fibonacci_five():
85
+ assert fibonacci(5) == 5
86
+
87
+ return
88
+
89
+
90
+ @app.cell
91
+ def _(mo):
92
+ n_input = mo.ui.number(
93
+ start=0,
94
+ stop=30,
95
+ step=1,
96
+ value=10,
97
+ label="n"
98
+ )
99
+
100
+ n_input
101
+ return (n_input,)
102
+
103
+
104
+ @app.cell
105
+ def _(mo, n_input):
106
+ mo.md(
107
+ f"**F({n_input.value}) = {fibonacci(n_input.value)}**"
108
+ )
109
+ return
110
+
111
+
112
+ @app.cell
113
+ def _(mo):
114
+ mo.md("""
115
+ ## Large-value tests
116
+
117
+ These tests serve two purposes:
118
+
119
+ 1. **Correctness after optimization**
120
+ We verify that the function still returns known Fibonacci values for larger inputs.
121
+
122
+ 2. **Performance motivation**
123
+ We use a much larger input to reveal the limitations of the naive recursive implementation
124
+ before refactoring it for better performance.
125
+ """)
126
+ return
127
+
128
+
129
+ @app.function
130
+ def test_fibonacci_large_values():
131
+ assert fibonacci(10) == 55
132
+ assert fibonacci(20) == 6765
133
+ assert fibonacci(30) == 832040
134
+
135
+
136
+ @app.function
137
+ def test_fibonacci_large_recurrence():
138
+ n = 1000
139
+ assert fibonacci(n) == fibonacci(n - 1) + fibonacci(n - 2)
140
+
141
+
142
+ @app.function
143
+ # Large-scale performance and correctness test:
144
+ # Verifies that the optimized implementation can handle n = 10^7.
145
+ # Two consecutive Fibonacci numbers are always coprime.
146
+ def test_fibonacci_very_large():
147
+ import math
148
+
149
+ n = 10**7
150
+ fn = fibonacci(n)
151
+ fn_next = fibonacci(n + 1)
152
+
153
+ assert math.gcd(fn, fn_next) == 1
154
+
155
+
156
+ if __name__ == "__main__":
157
+ app.run()
@@ -0,0 +1,33 @@
1
+
2
+ [project]
3
+ name = "fibonacci-tdd-kataa"
4
+ version = "0.1.0"
5
+ description = "A TDD kata: Fibonacci, from notebook exploration to a tested, published package"
6
+ readme = "README.md"
7
+ requires-python = ">=3.12"
8
+ authors = [
9
+ { name = "malak khalil", email = "malak.khalil@lau.edu" }
10
+ ]
11
+ dependencies = []
12
+
13
+ [build-system]
14
+ requires = ["hatchling"]
15
+ build-backend = "hatchling.build"
16
+
17
+ [tool.hatch.build.targets.wheel]
18
+ packages = ["src/fibonacci_tdd_kata"]
19
+
20
+ [dependency-groups]
21
+ dev = [
22
+ "pytest>=9.1.1",
23
+ "pytest-cov>=5.0",
24
+ "ruff>=0.16.8",
25
+ "marimo>=0.24.2",
26
+ ]
27
+
28
+ [tool.pytest.ini_options]
29
+ pythonpath = ["src"]
30
+ testpaths = ["tests"]
31
+
32
+ [tool.ruff.lint.per-file-ignores]
33
+ "notebooks/*.py" = ["B018", "PLR1711", "F401"]
@@ -0,0 +1,7 @@
1
+
2
+ """Fibonacci TDD kata package — see core.py for the implementation."""
3
+
4
+ from fibonacci_tdd_kata.core import fibonacci
5
+
6
+ __all__ = ["fibonacci"]
7
+ __version__ = "0.1.0"
@@ -0,0 +1,22 @@
1
+
2
+ """Core Fibonacci implementation."""
3
+
4
+
5
+ def fibonacci(n: int) -> int:
6
+ """Return F(n) using the fast-doubling algorithm."""
7
+ if not isinstance(n, int) or n < 0:
8
+ raise ValueError("n must be a non-negative integer")
9
+
10
+ def fib_pair(k: int) -> tuple[int, int]:
11
+ if k == 0:
12
+ return 0, 1
13
+
14
+ a, b = fib_pair(k // 2)
15
+ c = a * (2 * b - a)
16
+ d = a * a + b * b
17
+
18
+ if k % 2 == 0:
19
+ return c, d
20
+ return d, c + d
21
+
22
+ return fib_pair(n)[0]
@@ -0,0 +1,62 @@
1
+
2
+ """Tests for the Fibonacci implementation."""
3
+
4
+ import math
5
+
6
+ import pytest
7
+
8
+ from fibonacci_tdd_kata.core import fibonacci
9
+
10
+
11
+ def test_fibonacci_zero():
12
+ assert fibonacci(0) == 0
13
+
14
+
15
+ def test_fibonacci_one():
16
+ assert fibonacci(1) == 1
17
+
18
+
19
+ def test_fibonacci_two():
20
+ assert fibonacci(2) == 1
21
+
22
+
23
+ def test_fibonacci_three():
24
+ assert fibonacci(3) == 2
25
+
26
+
27
+ def test_fibonacci_four():
28
+ assert fibonacci(4) == 3
29
+
30
+
31
+ def test_fibonacci_five():
32
+ assert fibonacci(5) == 5
33
+
34
+
35
+ @pytest.mark.parametrize(
36
+ ("n", "expected"),
37
+ [
38
+ (10, 55),
39
+ (20, 6765),
40
+ (30, 832040),
41
+ ],
42
+ )
43
+ def test_fibonacci_large_values(n, expected):
44
+ assert fibonacci(n) == expected
45
+
46
+
47
+ def test_fibonacci_large_recurrence():
48
+ n = 1000
49
+ assert fibonacci(n) == fibonacci(n - 1) + fibonacci(n - 2)
50
+
51
+
52
+ def test_fibonacci_very_large():
53
+ n = 10**7
54
+ fn = fibonacci(n)
55
+ fn_next = fibonacci(n + 1)
56
+
57
+ assert math.gcd(fn, fn_next) == 1
58
+
59
+
60
+ def test_fibonacci_negative_input():
61
+ with pytest.raises(ValueError):
62
+ fibonacci(-1)