binnev-python-template 1.2.2__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.
- binnev_python_template-1.2.2/PKG-INFO +54 -0
- binnev_python_template-1.2.2/README.md +19 -0
- binnev_python_template-1.2.2/pyproject.toml +77 -0
- binnev_python_template-1.2.2/setup.cfg +4 -0
- binnev_python_template-1.2.2/src/__init__.py +0 -0
- binnev_python_template-1.2.2/src/api/__init__.py +1 -0
- binnev_python_template-1.2.2/src/api/app.py +7 -0
- binnev_python_template-1.2.2/src/api/calculator.py +75 -0
- binnev_python_template-1.2.2/src/binnev_python_template.egg-info/PKG-INFO +54 -0
- binnev_python_template-1.2.2/src/binnev_python_template.egg-info/SOURCES.txt +20 -0
- binnev_python_template-1.2.2/src/binnev_python_template.egg-info/dependency_links.txt +1 -0
- binnev_python_template-1.2.2/src/binnev_python_template.egg-info/requires.txt +26 -0
- binnev_python_template-1.2.2/src/binnev_python_template.egg-info/top_level.txt +4 -0
- binnev_python_template-1.2.2/src/cli/__init__.py +1 -0
- binnev_python_template-1.2.2/src/cli/__main__.py +4 -0
- binnev_python_template-1.2.2/src/cli/calculator.py +94 -0
- binnev_python_template-1.2.2/src/core/__init__.py +2 -0
- binnev_python_template-1.2.2/src/core/calculator.py +95 -0
- binnev_python_template-1.2.2/tests/test_api.py +50 -0
- binnev_python_template-1.2.2/tests/test_async_stuff.py +18 -0
- binnev_python_template-1.2.2/tests/test_calculator.py +30 -0
- binnev_python_template-1.2.2/tests/test_cli.py +36 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: binnev-python-template
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author-email: Robin Neville <robin.m.neville@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/binnev/python-template
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: fastapi>=0.115.12
|
|
11
|
+
Requires-Dist: httpx>=0.28.1
|
|
12
|
+
Requires-Dist: typer>=0.15.4
|
|
13
|
+
Requires-Dist: uvicorn>=0.34.2
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: pytest>=8.3.5; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
|
|
17
|
+
Requires-Dist: pytest-dotenv>=0.5.2; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-watcher>=0.4.3; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-cov>=6.1.1; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest-sugar>=1.0.0; extra == "dev"
|
|
22
|
+
Requires-Dist: pytest-better-parametrize>=0.2.0; extra == "dev"
|
|
23
|
+
Requires-Dist: coverage>=7.8.0; extra == "dev"
|
|
24
|
+
Requires-Dist: ruff>=0.11.10; extra == "dev"
|
|
25
|
+
Requires-Dist: mypy>=1.15.0; extra == "dev"
|
|
26
|
+
Requires-Dist: mkdocs>=1.6.1; extra == "dev"
|
|
27
|
+
Requires-Dist: mkdocs-material>=9.6.14; extra == "dev"
|
|
28
|
+
Requires-Dist: mkdocstrings[python]>=0.29.1; extra == "dev"
|
|
29
|
+
Requires-Dist: mkdocs-mermaid2-plugin>=1.2.1; extra == "dev"
|
|
30
|
+
Requires-Dist: mike>=2.1.3; extra == "dev"
|
|
31
|
+
Requires-Dist: commitizen>=4.7.2; extra == "dev"
|
|
32
|
+
Requires-Dist: pre-commit>=4.2.0; extra == "dev"
|
|
33
|
+
Requires-Dist: build>=1.2.2.post1; extra == "dev"
|
|
34
|
+
Requires-Dist: twine>=6.1.0; extra == "dev"
|
|
35
|
+
|
|
36
|
+
# Python project template
|
|
37
|
+
This project is a template for new python projects. It contains up-to-date tooling for tests, docs, versioning, and dependency management.
|
|
38
|
+
|
|
39
|
+
In a nutshell, the idea is that you clone/fork this project, and then modify it to suit your new project. The [`docs/how-to/getting-started.md`](tutorials/getting-started.md) page provides a step-by-step guide.
|
|
40
|
+
|
|
41
|
+
## Documentation
|
|
42
|
+
To view the documentation, run:
|
|
43
|
+
```sh
|
|
44
|
+
mkdocs serve
|
|
45
|
+
```
|
|
46
|
+
and go to [localhost:8000](http://localhost:8000) in your browser.
|
|
47
|
+
|
|
48
|
+
The documentation provides a detailed guide to the project. It is structured using the [Diátaxis framework](https://diataxis.fr/) to help you navigate and understand the project effectively. This framework consists of 4 categories:
|
|
49
|
+
|
|
50
|
+
1. **Tutorials**: Guides that teach a concept.
|
|
51
|
+
2. **How-To Guides**: Step-by-step instructions to achieve specific goals or tasks.
|
|
52
|
+
3. **Reference**: Technical descriptions of the project's components and APIs.
|
|
53
|
+
4. **Explanations**: In-depth discussions of concepts and motivations.
|
|
54
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Python project template
|
|
2
|
+
This project is a template for new python projects. It contains up-to-date tooling for tests, docs, versioning, and dependency management.
|
|
3
|
+
|
|
4
|
+
In a nutshell, the idea is that you clone/fork this project, and then modify it to suit your new project. The [`docs/how-to/getting-started.md`](tutorials/getting-started.md) page provides a step-by-step guide.
|
|
5
|
+
|
|
6
|
+
## Documentation
|
|
7
|
+
To view the documentation, run:
|
|
8
|
+
```sh
|
|
9
|
+
mkdocs serve
|
|
10
|
+
```
|
|
11
|
+
and go to [localhost:8000](http://localhost:8000) in your browser.
|
|
12
|
+
|
|
13
|
+
The documentation provides a detailed guide to the project. It is structured using the [Diátaxis framework](https://diataxis.fr/) to help you navigate and understand the project effectively. This framework consists of 4 categories:
|
|
14
|
+
|
|
15
|
+
1. **Tutorials**: Guides that teach a concept.
|
|
16
|
+
2. **How-To Guides**: Step-by-step instructions to achieve specific goals or tasks.
|
|
17
|
+
3. **Reference**: Technical descriptions of the project's components and APIs.
|
|
18
|
+
4. **Explanations**: In-depth discussions of concepts and motivations.
|
|
19
|
+
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
urls = { Homepage = "https://github.com/binnev/python-template" }
|
|
3
|
+
|
|
4
|
+
name = "binnev-python-template"
|
|
5
|
+
version = "1.2.2"
|
|
6
|
+
authors = [{ name = "Robin Neville", email = "robin.m.neville@gmail.com" }]
|
|
7
|
+
description = "Add your description here"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"fastapi>=0.115.12",
|
|
13
|
+
"httpx>=0.28.1",
|
|
14
|
+
"typer>=0.15.4",
|
|
15
|
+
"uvicorn>=0.34.2",
|
|
16
|
+
]
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
dev = [
|
|
19
|
+
"pytest>=8.3.5",
|
|
20
|
+
"pytest-asyncio>=1.0.0",
|
|
21
|
+
"pytest-dotenv>=0.5.2",
|
|
22
|
+
"pytest-watcher>=0.4.3",
|
|
23
|
+
"pytest-cov>=6.1.1",
|
|
24
|
+
"pytest-xdist>=3.6.1",
|
|
25
|
+
"pytest-sugar>=1.0.0",
|
|
26
|
+
"pytest-better-parametrize>=0.2.0",
|
|
27
|
+
"coverage>=7.8.0",
|
|
28
|
+
"ruff>=0.11.10",
|
|
29
|
+
"mypy>=1.15.0",
|
|
30
|
+
"mkdocs>=1.6.1",
|
|
31
|
+
"mkdocs-material>=9.6.14",
|
|
32
|
+
"mkdocstrings[python]>=0.29.1",
|
|
33
|
+
"mkdocs-mermaid2-plugin>=1.2.1",
|
|
34
|
+
"mike>=2.1.3",
|
|
35
|
+
"commitizen>=4.7.2",
|
|
36
|
+
"pre-commit>=4.2.0",
|
|
37
|
+
"build>=1.2.2.post1",
|
|
38
|
+
"twine>=6.1.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[tool.pytest.ini_options]
|
|
42
|
+
asyncio_mode = "auto"
|
|
43
|
+
asyncio_default_fixture_loop_scope = "session"
|
|
44
|
+
addopts = ["-p no:cacheprovider"]
|
|
45
|
+
testpaths = ["tests"]
|
|
46
|
+
|
|
47
|
+
[tool.coverage.report]
|
|
48
|
+
show_missing = true
|
|
49
|
+
skip_covered = true
|
|
50
|
+
fail_under = 70
|
|
51
|
+
exclude_lines = [
|
|
52
|
+
"if __name__ == .__main__.:",
|
|
53
|
+
"pragma: no cover",
|
|
54
|
+
"def __repr__",
|
|
55
|
+
"raise NotImplementedError",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.pytest-watcher]
|
|
59
|
+
now = true # run tests immediately; don't wait for the first file edit
|
|
60
|
+
clear = true # clear the terminal before each test run
|
|
61
|
+
delay = 0.2
|
|
62
|
+
runner = "pytest"
|
|
63
|
+
runner_args = []
|
|
64
|
+
patterns = ["*.py"]
|
|
65
|
+
ignore_patterns = []
|
|
66
|
+
|
|
67
|
+
[tool.commitizen]
|
|
68
|
+
name = "cz_conventional_commits"
|
|
69
|
+
tag_format = "$version"
|
|
70
|
+
version_scheme = "semver2"
|
|
71
|
+
version_provider = "pep621"
|
|
72
|
+
update_changelog_on_bump = false
|
|
73
|
+
version_files = ["pyproject.toml:version", "src/core/__init__.py:__version__"]
|
|
74
|
+
|
|
75
|
+
[tool.ruff]
|
|
76
|
+
line-length = 80
|
|
77
|
+
select = ["E", "F", "W", "C90", "B", "I", "N"]
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .app import app as app
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from fastapi import APIRouter, HTTPException
|
|
2
|
+
|
|
3
|
+
from src.core import calculator
|
|
4
|
+
|
|
5
|
+
calculator_router = APIRouter()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@calculator_router.get("/add")
|
|
9
|
+
def add(a: float, b: float):
|
|
10
|
+
"""
|
|
11
|
+
Endpoint to add two numbers.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
a (float): The first number to add.
|
|
15
|
+
b (float): The second number to add.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
dict: The result of the addition.
|
|
19
|
+
"""
|
|
20
|
+
result = calculator.add(a, b)
|
|
21
|
+
return {"result": result}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@calculator_router.get("/subtract")
|
|
25
|
+
def subtract(a: float, b: float):
|
|
26
|
+
"""
|
|
27
|
+
Endpoint to subtract two numbers.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
a (float): The number to subtract from.
|
|
31
|
+
b (float): The number to subtract.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
dict: The result of the subtraction.
|
|
35
|
+
"""
|
|
36
|
+
result = calculator.subtract(a, b)
|
|
37
|
+
return {"result": result}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@calculator_router.get("/multiply")
|
|
41
|
+
def multiply(a: float, b: float):
|
|
42
|
+
"""
|
|
43
|
+
Endpoint to multiply two numbers.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
a (float): The first number to multiply.
|
|
47
|
+
b (float): The second number to multiply.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
dict: The result of the multiplication.
|
|
51
|
+
"""
|
|
52
|
+
result = calculator.multiply(a, b)
|
|
53
|
+
return {"result": result}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@calculator_router.get("/divide")
|
|
57
|
+
def divide(a: float, b: float):
|
|
58
|
+
"""
|
|
59
|
+
Endpoint to divide two numbers.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
a (float): The numerator.
|
|
63
|
+
b (float): The denominator.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
dict: The result of the division.
|
|
67
|
+
|
|
68
|
+
Raises:
|
|
69
|
+
HTTPException: If division by zero is attempted.
|
|
70
|
+
"""
|
|
71
|
+
try:
|
|
72
|
+
result = calculator.divide(a, b)
|
|
73
|
+
return {"result": result}
|
|
74
|
+
except ValueError as e:
|
|
75
|
+
raise HTTPException(status_code=400, detail=str(e))
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: binnev-python-template
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author-email: Robin Neville <robin.m.neville@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/binnev/python-template
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: fastapi>=0.115.12
|
|
11
|
+
Requires-Dist: httpx>=0.28.1
|
|
12
|
+
Requires-Dist: typer>=0.15.4
|
|
13
|
+
Requires-Dist: uvicorn>=0.34.2
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: pytest>=8.3.5; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == "dev"
|
|
17
|
+
Requires-Dist: pytest-dotenv>=0.5.2; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-watcher>=0.4.3; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-cov>=6.1.1; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-xdist>=3.6.1; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest-sugar>=1.0.0; extra == "dev"
|
|
22
|
+
Requires-Dist: pytest-better-parametrize>=0.2.0; extra == "dev"
|
|
23
|
+
Requires-Dist: coverage>=7.8.0; extra == "dev"
|
|
24
|
+
Requires-Dist: ruff>=0.11.10; extra == "dev"
|
|
25
|
+
Requires-Dist: mypy>=1.15.0; extra == "dev"
|
|
26
|
+
Requires-Dist: mkdocs>=1.6.1; extra == "dev"
|
|
27
|
+
Requires-Dist: mkdocs-material>=9.6.14; extra == "dev"
|
|
28
|
+
Requires-Dist: mkdocstrings[python]>=0.29.1; extra == "dev"
|
|
29
|
+
Requires-Dist: mkdocs-mermaid2-plugin>=1.2.1; extra == "dev"
|
|
30
|
+
Requires-Dist: mike>=2.1.3; extra == "dev"
|
|
31
|
+
Requires-Dist: commitizen>=4.7.2; extra == "dev"
|
|
32
|
+
Requires-Dist: pre-commit>=4.2.0; extra == "dev"
|
|
33
|
+
Requires-Dist: build>=1.2.2.post1; extra == "dev"
|
|
34
|
+
Requires-Dist: twine>=6.1.0; extra == "dev"
|
|
35
|
+
|
|
36
|
+
# Python project template
|
|
37
|
+
This project is a template for new python projects. It contains up-to-date tooling for tests, docs, versioning, and dependency management.
|
|
38
|
+
|
|
39
|
+
In a nutshell, the idea is that you clone/fork this project, and then modify it to suit your new project. The [`docs/how-to/getting-started.md`](tutorials/getting-started.md) page provides a step-by-step guide.
|
|
40
|
+
|
|
41
|
+
## Documentation
|
|
42
|
+
To view the documentation, run:
|
|
43
|
+
```sh
|
|
44
|
+
mkdocs serve
|
|
45
|
+
```
|
|
46
|
+
and go to [localhost:8000](http://localhost:8000) in your browser.
|
|
47
|
+
|
|
48
|
+
The documentation provides a detailed guide to the project. It is structured using the [Diátaxis framework](https://diataxis.fr/) to help you navigate and understand the project effectively. This framework consists of 4 categories:
|
|
49
|
+
|
|
50
|
+
1. **Tutorials**: Guides that teach a concept.
|
|
51
|
+
2. **How-To Guides**: Step-by-step instructions to achieve specific goals or tasks.
|
|
52
|
+
3. **Reference**: Technical descriptions of the project's components and APIs.
|
|
53
|
+
4. **Explanations**: In-depth discussions of concepts and motivations.
|
|
54
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/__init__.py
|
|
4
|
+
src/api/__init__.py
|
|
5
|
+
src/api/app.py
|
|
6
|
+
src/api/calculator.py
|
|
7
|
+
src/binnev_python_template.egg-info/PKG-INFO
|
|
8
|
+
src/binnev_python_template.egg-info/SOURCES.txt
|
|
9
|
+
src/binnev_python_template.egg-info/dependency_links.txt
|
|
10
|
+
src/binnev_python_template.egg-info/requires.txt
|
|
11
|
+
src/binnev_python_template.egg-info/top_level.txt
|
|
12
|
+
src/cli/__init__.py
|
|
13
|
+
src/cli/__main__.py
|
|
14
|
+
src/cli/calculator.py
|
|
15
|
+
src/core/__init__.py
|
|
16
|
+
src/core/calculator.py
|
|
17
|
+
tests/test_api.py
|
|
18
|
+
tests/test_async_stuff.py
|
|
19
|
+
tests/test_calculator.py
|
|
20
|
+
tests/test_cli.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
fastapi>=0.115.12
|
|
2
|
+
httpx>=0.28.1
|
|
3
|
+
typer>=0.15.4
|
|
4
|
+
uvicorn>=0.34.2
|
|
5
|
+
|
|
6
|
+
[dev]
|
|
7
|
+
pytest>=8.3.5
|
|
8
|
+
pytest-asyncio>=1.0.0
|
|
9
|
+
pytest-dotenv>=0.5.2
|
|
10
|
+
pytest-watcher>=0.4.3
|
|
11
|
+
pytest-cov>=6.1.1
|
|
12
|
+
pytest-xdist>=3.6.1
|
|
13
|
+
pytest-sugar>=1.0.0
|
|
14
|
+
pytest-better-parametrize>=0.2.0
|
|
15
|
+
coverage>=7.8.0
|
|
16
|
+
ruff>=0.11.10
|
|
17
|
+
mypy>=1.15.0
|
|
18
|
+
mkdocs>=1.6.1
|
|
19
|
+
mkdocs-material>=9.6.14
|
|
20
|
+
mkdocstrings[python]>=0.29.1
|
|
21
|
+
mkdocs-mermaid2-plugin>=1.2.1
|
|
22
|
+
mike>=2.1.3
|
|
23
|
+
commitizen>=4.7.2
|
|
24
|
+
pre-commit>=4.2.0
|
|
25
|
+
build>=1.2.2.post1
|
|
26
|
+
twine>=6.1.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .calculator import app as app
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides CLI commands for performing basic arithmetic operations.
|
|
3
|
+
|
|
4
|
+
It uses the `typer` library to define commands for addition, subtraction,
|
|
5
|
+
multiplication, and division. Each command takes two numbers as input and prints
|
|
6
|
+
the result to the console.
|
|
7
|
+
|
|
8
|
+
The module relies on the `core.calculator` module for the actual arithmetic
|
|
9
|
+
operations.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
import typer
|
|
15
|
+
|
|
16
|
+
from src import core
|
|
17
|
+
from src.core import calculator
|
|
18
|
+
|
|
19
|
+
app = typer.Typer()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@app.command()
|
|
23
|
+
def add(a: float, b: float) -> None:
|
|
24
|
+
"""
|
|
25
|
+
Add two numbers.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
a (float): The first number to add.
|
|
29
|
+
b (float): The second number to add.
|
|
30
|
+
"""
|
|
31
|
+
result = calculator.add(a, b)
|
|
32
|
+
typer.echo(f"The result of addition is: {result}")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@app.command()
|
|
36
|
+
def subtract(a: float, b: float) -> None:
|
|
37
|
+
"""
|
|
38
|
+
Subtract two numbers.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
a (float): The number to subtract from.
|
|
42
|
+
b (float): The number to subtract.
|
|
43
|
+
"""
|
|
44
|
+
result = calculator.subtract(a, b)
|
|
45
|
+
typer.echo(f"The result of subtraction is: {result}")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@app.command()
|
|
49
|
+
def multiply(a: float, b: float) -> None:
|
|
50
|
+
"""
|
|
51
|
+
Multiply two numbers.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
a (float): The first number to multiply.
|
|
55
|
+
b (float): The second number to multiply.
|
|
56
|
+
"""
|
|
57
|
+
result = calculator.multiply(a, b)
|
|
58
|
+
typer.echo(f"The result of multiplication is: {result}")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@app.command()
|
|
62
|
+
def divide(a: float, b: float) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Divide two numbers.
|
|
65
|
+
Args:
|
|
66
|
+
a (float): The numerator.
|
|
67
|
+
b (float): The denominator.
|
|
68
|
+
"""
|
|
69
|
+
try:
|
|
70
|
+
result = calculator.divide(a, b)
|
|
71
|
+
typer.echo(f"The result of division is: {result}")
|
|
72
|
+
except ValueError as e:
|
|
73
|
+
typer.echo(f"Error: {e}")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _version_callback(value: bool) -> None:
|
|
77
|
+
if value:
|
|
78
|
+
typer.echo(f"{core.__app_name__} v{core.__version__}")
|
|
79
|
+
raise typer.Exit()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@app.callback()
|
|
83
|
+
def main(
|
|
84
|
+
version: Optional[bool] = typer.Option(
|
|
85
|
+
None,
|
|
86
|
+
"--version",
|
|
87
|
+
"-v",
|
|
88
|
+
help="Show the application's version and exit.",
|
|
89
|
+
callback=_version_callback,
|
|
90
|
+
is_eager=True,
|
|
91
|
+
),
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Handles the --version flag"""
|
|
94
|
+
return
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""The core calculator library with basic arithmetic operations."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def add(a: float, b: float) -> float:
|
|
5
|
+
"""
|
|
6
|
+
Return the sum of two numbers.
|
|
7
|
+
|
|
8
|
+
The `add` function is a simple utility designed to perform the addition of
|
|
9
|
+
two floating-point numbers. It takes two arguments, `a` and `b`, both of
|
|
10
|
+
which are expected to be of type `float`. The function returns their sum,
|
|
11
|
+
also as a `float`.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
a: The first number.
|
|
15
|
+
b: The second number.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
The sum of the two numbers.
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
>>> add(2, 3)
|
|
22
|
+
5
|
|
23
|
+
|
|
24
|
+
>>> add(-1, 1)
|
|
25
|
+
0
|
|
26
|
+
"""
|
|
27
|
+
return a + b
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def subtract(a: float, b: float) -> float:
|
|
31
|
+
"""
|
|
32
|
+
Return the difference of two numbers.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
a: The first number.
|
|
36
|
+
b: The second number.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
The difference of the two numbers.
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
>>> subtract(5, 3)
|
|
43
|
+
2
|
|
44
|
+
|
|
45
|
+
>>> subtract(2, 5)
|
|
46
|
+
-3
|
|
47
|
+
"""
|
|
48
|
+
return a - b
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def multiply(a: float, b: float) -> float:
|
|
52
|
+
"""
|
|
53
|
+
Return the product of two numbers.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
a: The first number.
|
|
57
|
+
b: The second number.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
The product of the two numbers.
|
|
61
|
+
|
|
62
|
+
Examples:
|
|
63
|
+
>>> multiply(2, 3)
|
|
64
|
+
6
|
|
65
|
+
|
|
66
|
+
>>> multiply(-1, 4)
|
|
67
|
+
-4
|
|
68
|
+
"""
|
|
69
|
+
return a * b
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def divide(a: float, b: float) -> float:
|
|
73
|
+
"""
|
|
74
|
+
Return the division of two numbers. Raise an error if dividing by zero.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
a: The numerator.
|
|
78
|
+
b: The denominator.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
The result of the division.
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
ValueError: If the denominator is zero.
|
|
85
|
+
|
|
86
|
+
Examples:
|
|
87
|
+
>>> divide(6, 3)
|
|
88
|
+
2.0
|
|
89
|
+
|
|
90
|
+
>>> divide(5, 2)
|
|
91
|
+
2.5
|
|
92
|
+
"""
|
|
93
|
+
if b == 0:
|
|
94
|
+
raise ValueError("Cannot divide by zero.")
|
|
95
|
+
return a / b
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from httpx import ASGITransport, AsyncClient
|
|
3
|
+
|
|
4
|
+
from src.api.app import app
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@pytest.fixture
|
|
8
|
+
def test_client() -> AsyncClient:
|
|
9
|
+
return AsyncClient(
|
|
10
|
+
transport=ASGITransport(app=app),
|
|
11
|
+
base_url="http://test",
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
async def test_add(test_client: AsyncClient):
|
|
16
|
+
response = await test_client.get("/calculator/add", params={"a": 1, "b": 2})
|
|
17
|
+
assert response.status_code == 200
|
|
18
|
+
assert response.json() == {"result": 3}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def test_subtract(test_client: AsyncClient):
|
|
22
|
+
response = await test_client.get(
|
|
23
|
+
"/calculator/subtract", params={"a": 5, "b": 3}
|
|
24
|
+
)
|
|
25
|
+
assert response.status_code == 200
|
|
26
|
+
assert response.json() == {"result": 2}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def test_multiply(test_client: AsyncClient):
|
|
30
|
+
response = await test_client.get(
|
|
31
|
+
"/calculator/multiply", params={"a": 4, "b": 2}
|
|
32
|
+
)
|
|
33
|
+
assert response.status_code == 200
|
|
34
|
+
assert response.json() == {"result": 8}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def test_divide(test_client: AsyncClient):
|
|
38
|
+
response = await test_client.get(
|
|
39
|
+
"/calculator/divide", params={"a": 10, "b": 2}
|
|
40
|
+
)
|
|
41
|
+
assert response.status_code == 200
|
|
42
|
+
assert response.json() == {"result": 5}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def test_divide_by_zero(test_client: AsyncClient):
|
|
46
|
+
response = await test_client.get(
|
|
47
|
+
"/calculator/divide", params={"a": 10, "b": 0}
|
|
48
|
+
)
|
|
49
|
+
assert response.status_code == 400
|
|
50
|
+
assert response.json()["detail"] == "Cannot divide by zero."
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
N = 100
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.parametrize("n", range(N))
|
|
10
|
+
async def test_blocking(n: int):
|
|
11
|
+
"""These tests won't benefit from asyncio.gather"""
|
|
12
|
+
time.sleep(0.1)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.mark.parametrize("n", range(N))
|
|
16
|
+
async def test_non_blocking(n: int):
|
|
17
|
+
"""These tests won't benefit from asyncio.gather"""
|
|
18
|
+
await asyncio.sleep(0.1)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from src.core.calculator import add, divide, multiply, subtract
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_add():
|
|
7
|
+
assert add(2, 3) == 5
|
|
8
|
+
assert add(-1, 1) == 0
|
|
9
|
+
assert add(0, 0) == 0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_subtract():
|
|
13
|
+
assert subtract(10, 5) == 5
|
|
14
|
+
assert subtract(0, 5) == -5
|
|
15
|
+
assert subtract(-5, -5) == 0
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_multiply():
|
|
19
|
+
assert multiply(3, 4) == 12
|
|
20
|
+
assert multiply(-2, 3) == -6
|
|
21
|
+
assert multiply(0, 5) == 0
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_divide():
|
|
25
|
+
assert divide(10, 2) == 5
|
|
26
|
+
assert divide(-6, 3) == -2
|
|
27
|
+
assert divide(5, 2) == 2.5
|
|
28
|
+
|
|
29
|
+
with pytest.raises(ValueError):
|
|
30
|
+
divide(10, 0)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from typer.testing import CliRunner
|
|
2
|
+
|
|
3
|
+
from src.cli.calculator import app
|
|
4
|
+
from src.core import __version__
|
|
5
|
+
|
|
6
|
+
runner = CliRunner()
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_add_command():
|
|
10
|
+
result = runner.invoke(app, ["add", "2", "3"])
|
|
11
|
+
assert result.exit_code == 0
|
|
12
|
+
assert result.output.strip() == "The result of addition is: 5.0"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_subtract_command():
|
|
16
|
+
result = runner.invoke(app, ["subtract", "5", "3"])
|
|
17
|
+
assert result.exit_code == 0
|
|
18
|
+
assert result.output.strip() == "The result of subtraction is: 2.0"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_multiply_command():
|
|
22
|
+
result = runner.invoke(app, ["multiply", "4", "3"])
|
|
23
|
+
assert result.exit_code == 0
|
|
24
|
+
assert result.output.strip() == "The result of multiplication is: 12.0"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_divide_command():
|
|
28
|
+
result = runner.invoke(app, ["divide", "10", "2"])
|
|
29
|
+
assert result.exit_code == 0
|
|
30
|
+
assert result.output.strip() == "The result of division is: 5.0"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_version_flag():
|
|
34
|
+
result = runner.invoke(app, ["--version"])
|
|
35
|
+
assert result.exit_code == 0
|
|
36
|
+
assert result.output.strip() == f"python-template v{__version__}"
|