fibonacci-kata 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.
- fibonacci_kata-0.1.0/.github/workflows/publish.yml +27 -0
- fibonacci_kata-0.1.0/.github/workflows/tests.yml +31 -0
- fibonacci_kata-0.1.0/.gitignore +10 -0
- fibonacci_kata-0.1.0/.python-version +1 -0
- fibonacci_kata-0.1.0/PKG-INFO +7 -0
- fibonacci_kata-0.1.0/README.md +0 -0
- fibonacci_kata-0.1.0/__marimo__/session/notebook.py.json +15 -0
- fibonacci_kata-0.1.0/notebooks/tdd_fibonacci_marimo_en.py +127 -0
- fibonacci_kata-0.1.0/pyproject.toml +27 -0
- fibonacci_kata-0.1.0/src/fibonacci_kata/core.py +20 -0
- fibonacci_kata-0.1.0/src/fibonacci_kata/init.py +5 -0
- fibonacci_kata-0.1.0/src/fibonacci_tdd_kata/__init__.py +2 -0
- fibonacci_kata-0.1.0/tests/test_core.py +19 -0
- fibonacci_kata-0.1.0/uv.lock +748 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Publish package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write # required for PyPI Trusted Publishing
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
uses: ./.github/workflows/tests.yml # re-run the full test workflow
|
|
13
|
+
|
|
14
|
+
build-and-publish:
|
|
15
|
+
needs: test # only runs if tests succeeded
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v5
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: uv build
|
|
25
|
+
|
|
26
|
+
- name: Publish to PyPI
|
|
27
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_call:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
strategy:
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: uv sync --all-groups
|
|
26
|
+
|
|
27
|
+
- name: Lint
|
|
28
|
+
run: uv run ruff check .
|
|
29
|
+
|
|
30
|
+
- name: Run tests
|
|
31
|
+
run: uv run pytest --cov=src --cov-report=term-missing
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
File without changes
|
|
@@ -0,0 +1,127 @@
|
|
|
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
|
+
|
|
11
|
+
return (mo,)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@app.cell(hide_code=True)
|
|
15
|
+
def _(mo):
|
|
16
|
+
mo.md(r"""
|
|
17
|
+
# Fibonacci Kata
|
|
18
|
+
""")
|
|
19
|
+
#return
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@app.cell(hide_code=True)
|
|
23
|
+
def _(mo):
|
|
24
|
+
mo.md(r"""
|
|
25
|
+
This notebook implements the Fibonacci sequence using TDD.
|
|
26
|
+
|
|
27
|
+
The Fibonacci sequence is defined by:
|
|
28
|
+
|
|
29
|
+
- F(0) = 0
|
|
30
|
+
- F(1) = 1
|
|
31
|
+
- F(n) = F(n-1) + F(n-2)
|
|
32
|
+
""")
|
|
33
|
+
#return
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@app.cell(hide_code=True)
|
|
37
|
+
def _(mo):
|
|
38
|
+
mo.md(r"""
|
|
39
|
+
### Fibonacci function implementation
|
|
40
|
+
""")
|
|
41
|
+
#return
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@app.function
|
|
45
|
+
def fibonacci(n: int) -> int:
|
|
46
|
+
"""
|
|
47
|
+
Returns the n-th Fibonacci number
|
|
48
|
+
Contract:
|
|
49
|
+
- if n = 0: 0
|
|
50
|
+
- if n = 1: 1
|
|
51
|
+
- otherwise: fibonacci(n-1) + fibonacci(n-2)
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
prev = 0
|
|
55
|
+
cur = 1
|
|
56
|
+
|
|
57
|
+
for k in range(n):
|
|
58
|
+
cur, prev = cur + prev, cur
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
return prev
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
app._unparsable_cell(
|
|
65
|
+
r"""
|
|
66
|
+
### Fibonacci optimization
|
|
67
|
+
|
|
68
|
+
The algorthme can be improved to O(log n) by using fast doubling.
|
|
69
|
+
- F(2k) = F(k) * (2*F(k+1) - F(k))
|
|
70
|
+
- F(2k + 1) = F(k)² + F(k+1)²
|
|
71
|
+
""",
|
|
72
|
+
name="_"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@app.cell(hide_code=True)
|
|
77
|
+
def _(mo):
|
|
78
|
+
mo.md(r"""
|
|
79
|
+
### Unit tests
|
|
80
|
+
""")
|
|
81
|
+
#return
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@app.cell
|
|
85
|
+
def _():
|
|
86
|
+
assert fibonacci(0) == 0
|
|
87
|
+
assert fibonacci(1) == 1
|
|
88
|
+
assert fibonacci(2) == 1
|
|
89
|
+
assert fibonacci(5) == 5
|
|
90
|
+
assert fibonacci(10) == 55
|
|
91
|
+
#return
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@app.cell
|
|
95
|
+
def _():
|
|
96
|
+
fibonacci(10**2)
|
|
97
|
+
#return
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@app.cell(hide_code=True)
|
|
101
|
+
def _(mo):
|
|
102
|
+
mo.md(r"""
|
|
103
|
+
### Interactive marimo widget
|
|
104
|
+
""")
|
|
105
|
+
#return
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@app.cell
|
|
109
|
+
def _(mo):
|
|
110
|
+
n_input = mo.ui.number(start=1, stop=1000, step=1, value=5, label="n")
|
|
111
|
+
|
|
112
|
+
return n_input
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@app.cell
|
|
116
|
+
def _(mo, n_input):
|
|
117
|
+
try:
|
|
118
|
+
result = fibonacci(n_input.value)
|
|
119
|
+
output = mo.md(f"`fibonacci({n_input.value})` → **{result}**")
|
|
120
|
+
except ValueError as e:
|
|
121
|
+
output = mo.md(f"⚠️ Error: {e}")
|
|
122
|
+
|
|
123
|
+
return output
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == "__main__":
|
|
127
|
+
app.run()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fibonacci-kata"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A TDD kata: Fibonacci, from notebook exploration to a tested, published package"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
license = { text = "MIT" }
|
|
8
|
+
authors = [{ name = "Rina Ralijaona", email = "rinaralijaona4@gmail.com" }]
|
|
9
|
+
|
|
10
|
+
[build-system]
|
|
11
|
+
requires = ["hatchling"]
|
|
12
|
+
build-backend = "hatchling.build"
|
|
13
|
+
|
|
14
|
+
[tool.hatch.build.targets.wheel]
|
|
15
|
+
packages = ["src/fibonacci_kata"]
|
|
16
|
+
|
|
17
|
+
[dependency-groups]
|
|
18
|
+
dev = [
|
|
19
|
+
"pytest>=8.0",
|
|
20
|
+
"pytest-cov>=5.0",
|
|
21
|
+
"ruff>=0.6",
|
|
22
|
+
"marimo>=0.10",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[tool.pytest.ini_options]
|
|
26
|
+
pythonpath = ["src"]
|
|
27
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
def fibonacci(n: int) -> int:
|
|
2
|
+
"""
|
|
3
|
+
Returns the n-th Fibonacci number
|
|
4
|
+
Contract:
|
|
5
|
+
- if n = 0: 0
|
|
6
|
+
- if n = 1: 1
|
|
7
|
+
- otherwise: fibonacci(n-1) + fibonacci(n-2)
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
if not isinstance(n, int) or n < 0:
|
|
12
|
+
raise ValueError("fibonacci expects a positive integer")
|
|
13
|
+
|
|
14
|
+
prev = 0
|
|
15
|
+
cur = 1
|
|
16
|
+
|
|
17
|
+
for k in range(n):
|
|
18
|
+
cur, prev = cur + prev, cur
|
|
19
|
+
|
|
20
|
+
return prev
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from fibonacci_kata.core import fibonacci
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize(
|
|
7
|
+
("n", "expected"),
|
|
8
|
+
[
|
|
9
|
+
(0, 0),
|
|
10
|
+
(1, 1),
|
|
11
|
+
(2, 1),
|
|
12
|
+
(3, 2),
|
|
13
|
+
(10, 55),
|
|
14
|
+
(20, 6765)
|
|
15
|
+
],
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
def test_cases(n, expected):
|
|
19
|
+
assert fibonacci(n) == expected
|