webloom 1.0.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.
- webloom-1.0.2/.github/workflows/code_style.yml +36 -0
- webloom-1.0.2/.github/workflows/code_test.yml +96 -0
- webloom-1.0.2/.github/workflows/dist_build.yml +40 -0
- webloom-1.0.2/.github/workflows/docs_build.yml +52 -0
- webloom-1.0.2/.github/workflows/publish_dist.yml +82 -0
- webloom-1.0.2/.gitignore +16 -0
- webloom-1.0.2/.python-version +1 -0
- webloom-1.0.2/PKG-INFO +14 -0
- webloom-1.0.2/README.md +5 -0
- webloom-1.0.2/docs/about.md +13 -0
- webloom-1.0.2/docs/index.md +21 -0
- webloom-1.0.2/mkdocs.yml +17 -0
- webloom-1.0.2/pyproject.toml +76 -0
- webloom-1.0.2/src/webloom/__init__.py +14 -0
- webloom-1.0.2/src/webloom/utils.py +94 -0
- webloom-1.0.2/tests/__init__.py +0 -0
- webloom-1.0.2/tests/test_utils.py +91 -0
- webloom-1.0.2/uv.lock +1581 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: Lint and Format
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [ main ]
|
|
9
|
+
paths: [ '**/*.py' ]
|
|
10
|
+
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: ${{ github.workflow }}/${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
python-format:
|
|
19
|
+
name: Ruff Lint and Format
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout Repository
|
|
24
|
+
uses: actions/checkout@v6
|
|
25
|
+
|
|
26
|
+
- name: Setup Ruff
|
|
27
|
+
uses: astral-sh/ruff-action@v3
|
|
28
|
+
with:
|
|
29
|
+
args: --version
|
|
30
|
+
|
|
31
|
+
- name: Enforce Lint
|
|
32
|
+
run: ruff check .
|
|
33
|
+
|
|
34
|
+
- name: Enforce Format
|
|
35
|
+
run: |
|
|
36
|
+
ruff format --diff .
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
name: Code Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [ main ]
|
|
9
|
+
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
workflow_call:
|
|
12
|
+
outputs:
|
|
13
|
+
artifact_name:
|
|
14
|
+
value: ${{ jobs.fresh_build.outputs.artifact_name }}
|
|
15
|
+
artifact_run_id:
|
|
16
|
+
value: ${{ jobs.fresh_build.outputs.run_id }}
|
|
17
|
+
|
|
18
|
+
concurrency:
|
|
19
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
20
|
+
cancel-in-progress: true
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
|
|
24
|
+
setup:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- name: Fetch Supported Python
|
|
29
|
+
id: fetch-versions
|
|
30
|
+
run: |
|
|
31
|
+
versions=$(curl -fsSL https://endoflife.date/api/v1/products/python/ \
|
|
32
|
+
| jq '[ .result.releases[] | select(.isEol == false) | .label ]')
|
|
33
|
+
|
|
34
|
+
echo "supported_versions=$(echo $versions |jq -c '.')" >> $GITHUB_OUTPUT
|
|
35
|
+
echo "bound_versions=$(echo $versions |jq -c '[.[0],.[-1]]')" >> $GITHUB_OUTPUT
|
|
36
|
+
|
|
37
|
+
outputs:
|
|
38
|
+
supported_versions: ${{ steps.fetch-versions.outputs.supported_versions }}
|
|
39
|
+
bound_versions: ${{ steps.fetch-versions.outputs.bound_versions }}
|
|
40
|
+
|
|
41
|
+
fresh_build:
|
|
42
|
+
uses: ./.github/workflows/dist_build.yml
|
|
43
|
+
|
|
44
|
+
testing:
|
|
45
|
+
runs-on: ${{ matrix.os }}
|
|
46
|
+
|
|
47
|
+
permissions:
|
|
48
|
+
id-token: write # for working of oidc of codecov
|
|
49
|
+
|
|
50
|
+
strategy:
|
|
51
|
+
matrix:
|
|
52
|
+
os: [ ubuntu-latest ]
|
|
53
|
+
py-version: ${{ fromJson(needs.setup.outputs.supported_versions) }}
|
|
54
|
+
include:
|
|
55
|
+
- os: windows-latest
|
|
56
|
+
py-version: ${{ fromJson(needs.setup.outputs.bound_versions)[0] }}
|
|
57
|
+
- os: windows-latest
|
|
58
|
+
py-version: ${{ fromJson(needs.setup.outputs.bound_versions)[1] }}
|
|
59
|
+
- os: macos-latest
|
|
60
|
+
py-version: ${{ fromJson(needs.setup.outputs.bound_versions)[0] }}
|
|
61
|
+
- os: macos-latest
|
|
62
|
+
py-version: ${{ fromJson(needs.setup.outputs.bound_versions)[1] }}
|
|
63
|
+
|
|
64
|
+
needs:
|
|
65
|
+
- fresh_build
|
|
66
|
+
- setup
|
|
67
|
+
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v6
|
|
70
|
+
|
|
71
|
+
- name: Download Build Artifacts
|
|
72
|
+
uses: actions/download-artifact@v7
|
|
73
|
+
with:
|
|
74
|
+
name: ${{ needs.fresh_build.outputs.artifact_name }}
|
|
75
|
+
run-id: ${{ needs.fresh_build.outputs.run_id }}
|
|
76
|
+
path: ./dist
|
|
77
|
+
|
|
78
|
+
- uses: astral-sh/setup-uv@v7
|
|
79
|
+
with:
|
|
80
|
+
python-version: ${{ matrix.py-version }}
|
|
81
|
+
|
|
82
|
+
- name: Install Packages
|
|
83
|
+
shell: bash
|
|
84
|
+
run: |
|
|
85
|
+
uv sync --no-dev --group test
|
|
86
|
+
uv pip install -v ./dist/*.whl
|
|
87
|
+
|
|
88
|
+
- name: Run Tests
|
|
89
|
+
run: uv run --no-sync pytest -v -n auto --cov --cov-report=xml
|
|
90
|
+
|
|
91
|
+
- name: Upload coverage to Codecov
|
|
92
|
+
uses: codecov/codecov-action@v5
|
|
93
|
+
with:
|
|
94
|
+
fail_ci_if_error: true
|
|
95
|
+
use_oidc: true
|
|
96
|
+
verbose: true
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Build Distribution
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
outputs:
|
|
6
|
+
artifact_name:
|
|
7
|
+
value: ${{ jobs.build.outputs.artifact_name }}
|
|
8
|
+
run_id:
|
|
9
|
+
value: ${{ github.run_id }}
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0
|
|
19
|
+
|
|
20
|
+
- name: Setup uv
|
|
21
|
+
uses: astral-sh/setup-uv@v7
|
|
22
|
+
|
|
23
|
+
- name: Build distribution
|
|
24
|
+
run: uv build -v --clear .
|
|
25
|
+
|
|
26
|
+
- name: Set Artifact Name
|
|
27
|
+
id: artifact-name
|
|
28
|
+
run: |
|
|
29
|
+
echo "artifact_name=${{ github.run_id }}[${{ github.run_attempt }}]--build-artifacts" \
|
|
30
|
+
| tee -a $GITHUB_OUTPUT
|
|
31
|
+
|
|
32
|
+
- name: Upload Build Artifacts
|
|
33
|
+
uses: actions/upload-artifact@v6
|
|
34
|
+
with:
|
|
35
|
+
name: ${{ steps.artifact-name.outputs.artifact_name }}
|
|
36
|
+
path: dist
|
|
37
|
+
if-no-files-found: error
|
|
38
|
+
|
|
39
|
+
outputs:
|
|
40
|
+
artifact_name: ${{ steps.artifact-name.outputs.artifact_name }}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Build Documentation
|
|
2
|
+
permissions:
|
|
3
|
+
pages: write
|
|
4
|
+
id-token: write
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [ main ]
|
|
9
|
+
workflow_call:
|
|
10
|
+
inputs: &build-docs-inputs
|
|
11
|
+
deploy:
|
|
12
|
+
type: boolean
|
|
13
|
+
required: false
|
|
14
|
+
default: false
|
|
15
|
+
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
inputs: *build-docs-inputs
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: docs-build
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
|
|
24
|
+
build:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v6
|
|
29
|
+
|
|
30
|
+
- name: Setup uv
|
|
31
|
+
uses: astral-sh/setup-uv@v7
|
|
32
|
+
|
|
33
|
+
- name: Build Documentation
|
|
34
|
+
run: uv run --no-dev --group docs mkdocs build --clean --strict
|
|
35
|
+
|
|
36
|
+
- name: Set Artifact Name
|
|
37
|
+
id: artifact-name
|
|
38
|
+
run: |
|
|
39
|
+
echo "artifact_name=${{ github.run_id }}[${{ github.run_attempt }}]--build-artifacts" \
|
|
40
|
+
| tee -a $GITHUB_OUTPUT
|
|
41
|
+
|
|
42
|
+
- name: Upload Pages Artifacts
|
|
43
|
+
uses: actions/upload-pages-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: ${{ steps.artifact-name.outputs.artifact_name }}
|
|
46
|
+
path: build/docs
|
|
47
|
+
|
|
48
|
+
- name: Deploy to GitHub Pages
|
|
49
|
+
if: ${{ inputs.deploy }}
|
|
50
|
+
uses: actions/deploy-pages@v4
|
|
51
|
+
with:
|
|
52
|
+
artifact_name: ${{ steps.artifact-name.outputs.artifact_name }}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: [ 'v*.*.*' ]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
id-token: write
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: ${{ github.workflow }}
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
testing:
|
|
15
|
+
uses: ./.github/workflows/code_test.yml
|
|
16
|
+
|
|
17
|
+
publish-test-pypi:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
|
|
20
|
+
environment:
|
|
21
|
+
name: test-pypi
|
|
22
|
+
url: https://test.pypi.org/p/webloom
|
|
23
|
+
|
|
24
|
+
needs: testing
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
|
|
28
|
+
- &download_dist
|
|
29
|
+
name: Download Distributions
|
|
30
|
+
uses: actions/download-artifact@v7
|
|
31
|
+
with:
|
|
32
|
+
name: ${{ needs.testing.outputs.artifact_name }}
|
|
33
|
+
run-id: ${{ needs.testing.outputs.artifact_run_id }}
|
|
34
|
+
path: ./dist
|
|
35
|
+
|
|
36
|
+
- name: Publish to Test PyPI
|
|
37
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
38
|
+
with:
|
|
39
|
+
repository-url: https://test.pypi.org/legacy/
|
|
40
|
+
verbose: true
|
|
41
|
+
|
|
42
|
+
- name: Smoke Test on Test PyPI
|
|
43
|
+
run: |
|
|
44
|
+
pip install -v --index-url https://test.pypi.org/simple/ \
|
|
45
|
+
--extra-index-url https://pypi.org/simple/ webloom
|
|
46
|
+
python -c "import webloom;print(webloom.__version__)"
|
|
47
|
+
|
|
48
|
+
publish-to-pypi:
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
|
|
51
|
+
permissions:
|
|
52
|
+
id-token: write
|
|
53
|
+
|
|
54
|
+
environment:
|
|
55
|
+
name: pypi
|
|
56
|
+
url: https://pypi.org/p/webloom
|
|
57
|
+
|
|
58
|
+
needs: testing
|
|
59
|
+
|
|
60
|
+
steps:
|
|
61
|
+
|
|
62
|
+
- *download_dist
|
|
63
|
+
- name: Publish to PyPI
|
|
64
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
65
|
+
with:
|
|
66
|
+
verbose: true
|
|
67
|
+
|
|
68
|
+
- name: Smoke Test on PyPI
|
|
69
|
+
run: |
|
|
70
|
+
pip install -v --index-url https://pypi.org/simple/ webloom
|
|
71
|
+
python -c "import webloom;print(webloom.__version__)"
|
|
72
|
+
|
|
73
|
+
publish_docs:
|
|
74
|
+
needs: publish-to-pypi
|
|
75
|
+
|
|
76
|
+
permissions:
|
|
77
|
+
pages: write
|
|
78
|
+
id-token: write
|
|
79
|
+
|
|
80
|
+
uses: ./.github/workflows/docs_build.yml
|
|
81
|
+
with:
|
|
82
|
+
deploy: true
|
webloom-1.0.2/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
webloom-1.0.2/PKG-INFO
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: webloom
|
|
3
|
+
Version: 1.0.2
|
|
4
|
+
Author-email: M Laraib Ali <laraibg786@outlook.com>
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Requires-Dist: numpy>=2.0.2
|
|
7
|
+
Requires-Dist: scipy>=1.13.1
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
This is dummy project created for sole purpose of testing. If you require this
|
|
11
|
+
project for some real use case, please contact the author. I will be happy to
|
|
12
|
+
take down the project or give you the ownership whatever suits you best.
|
|
13
|
+
|
|
14
|
+
Thanks!
|
webloom-1.0.2/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# About Webloom
|
|
2
|
+
|
|
3
|
+
This is a dummy project to test the github actions.
|
|
4
|
+
|
|
5
|
+
## Project Structure
|
|
6
|
+
|
|
7
|
+
- `src/webloom/`: Main package code
|
|
8
|
+
- `docs/`: Documentation files
|
|
9
|
+
- `pyproject.toml`: Project configuration
|
|
10
|
+
|
|
11
|
+
## Contributing
|
|
12
|
+
|
|
13
|
+
Contributions are welcome! Please see the main repository for guidelines.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Welcome to Webloom
|
|
2
|
+
|
|
3
|
+
Webloom is a powerful tool for [describe what it does here].
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Feature 1: Description
|
|
8
|
+
- Feature 2: Description
|
|
9
|
+
- Feature 3: Description
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
To get started with Webloom, follow these steps:
|
|
14
|
+
|
|
15
|
+
1. Install the package: `pip install webloom`
|
|
16
|
+
2. Import in your code: `import webloom`
|
|
17
|
+
3. Use it!
|
|
18
|
+
|
|
19
|
+
## Documentation
|
|
20
|
+
|
|
21
|
+
For more detailed information, check out the [About](about.md) page.
|
webloom-1.0.2/mkdocs.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
site_name: Webloom Documentation
|
|
2
|
+
site_description: Documentation for the Webloom project
|
|
3
|
+
site_author: M Laraib Ali
|
|
4
|
+
site_dir: build/docs
|
|
5
|
+
|
|
6
|
+
theme:
|
|
7
|
+
name: material
|
|
8
|
+
palette:
|
|
9
|
+
primary: blue
|
|
10
|
+
accent: blue
|
|
11
|
+
|
|
12
|
+
nav:
|
|
13
|
+
- Home: index.md
|
|
14
|
+
- About: about.md
|
|
15
|
+
|
|
16
|
+
plugins:
|
|
17
|
+
- search
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "webloom"
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
readme = "README.md"
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "M Laraib Ali", email = "laraibg786@outlook.com" }
|
|
7
|
+
]
|
|
8
|
+
requires-python = ">=3.9"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"numpy>=2.0.2",
|
|
11
|
+
"scipy>=1.13.1",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[project.scripts]
|
|
15
|
+
webloom = "webloom:main"
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["hatchling>=1.26", "hatch-vcs"]
|
|
19
|
+
build-backend = "hatchling.build"
|
|
20
|
+
|
|
21
|
+
[tool.hatch.version]
|
|
22
|
+
source = "vcs"
|
|
23
|
+
|
|
24
|
+
[tool.ruff]
|
|
25
|
+
line-length = 80
|
|
26
|
+
indent-width = 4
|
|
27
|
+
preview = true
|
|
28
|
+
output-format = "grouped"
|
|
29
|
+
|
|
30
|
+
select = [
|
|
31
|
+
"ANN", # flake8-annotations (required strict type annotations for public functions)
|
|
32
|
+
"S", # flake8-bandit (checks basic security issues in code)
|
|
33
|
+
"BLE", # flake8-blind-except (checks the except blocks that do not specify exception)
|
|
34
|
+
"FBT", # flake8-boolean-trap (ensure that boolean args can be used with kw only)
|
|
35
|
+
"E", # pycodestyle errors (PEP 8 style guide violations)
|
|
36
|
+
"W", # pycodestyle warnings (e.g., extra spaces, indentation issues)
|
|
37
|
+
"DOC", # pydoclint issues (e.g., extra or missing return, yield, warnings)
|
|
38
|
+
"A", # flake8-buitins (check variable and function names to not shadow builtins)
|
|
39
|
+
"N", # Naming convention checks (e.g., PEP 8 variable and function names)
|
|
40
|
+
"F", # Pyflakes errors (e.g., unused imports, undefined variables)
|
|
41
|
+
"I", # isort (Ensures imports are sorted properly)
|
|
42
|
+
"B", # flake8-bugbear (Detects likely bugs and bad practices)
|
|
43
|
+
"TID", # flake8-tidy-imports (Checks for banned or misplaced imports)
|
|
44
|
+
"UP", # pyupgrade (Automatically updates old Python syntax)
|
|
45
|
+
"YTT", # flake8-2020 (Detects outdated Python 2/3 compatibility issues)
|
|
46
|
+
"FLY", # flynt (Converts old-style string formatting to f-strings)
|
|
47
|
+
"PIE", # flake8-pie
|
|
48
|
+
"PL", # pylint
|
|
49
|
+
"RUF", # Ruff-specific rules (Additional optimizations and best practices)
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.ruff.format]
|
|
53
|
+
docstring-code-format = true
|
|
54
|
+
skip-magic-trailing-comma = true
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
addopts = "--doctest-modules"
|
|
58
|
+
|
|
59
|
+
[dependency-groups]
|
|
60
|
+
dev = [
|
|
61
|
+
{include-group = "docs"},
|
|
62
|
+
{include-group = "lint"},
|
|
63
|
+
{include-group = "test"}
|
|
64
|
+
]
|
|
65
|
+
docs = [
|
|
66
|
+
"mkdocs>=1.6.1",
|
|
67
|
+
"mkdocs-material>=9.7.1",
|
|
68
|
+
]
|
|
69
|
+
lint = [
|
|
70
|
+
"ruff>=0.15.0",
|
|
71
|
+
]
|
|
72
|
+
test = [
|
|
73
|
+
"pytest>=8.4.2",
|
|
74
|
+
"pytest-cov>=7.0.0",
|
|
75
|
+
"pytest-xdist>=3.8.0",
|
|
76
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
2
|
+
|
|
3
|
+
from webloom.utils import add_numbers, multiply_numbers, is_even, fibonacci
|
|
4
|
+
|
|
5
|
+
try: # noqa: RUF067
|
|
6
|
+
__version__ = version(__name__)
|
|
7
|
+
except PackageNotFoundError:
|
|
8
|
+
__version__ = "unknown"
|
|
9
|
+
|
|
10
|
+
def main() -> None:
|
|
11
|
+
print("Hello from webloom!")
|
|
12
|
+
print(__version__)
|
|
13
|
+
|
|
14
|
+
__all__ = ["add_numbers", "multiply_numbers", "is_even", "fibonacci", "main", "__version__"]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""Utility functions for Webloom."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def add_numbers(a: int, b: int) -> int:
|
|
5
|
+
"""
|
|
6
|
+
Add two numbers together.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
a: First number
|
|
10
|
+
b: Second number
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
The sum of a and b
|
|
14
|
+
|
|
15
|
+
Examples:
|
|
16
|
+
>>> add_numbers(1, 2)
|
|
17
|
+
3
|
|
18
|
+
>>> add_numbers(-1, 1)
|
|
19
|
+
0
|
|
20
|
+
"""
|
|
21
|
+
return a + b
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def multiply_numbers(a: int, b: int) -> int:
|
|
25
|
+
"""
|
|
26
|
+
Multiply two numbers.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
a: First number
|
|
30
|
+
b: Second number
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
The product of a and b
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
>>> multiply_numbers(2, 3)
|
|
37
|
+
6
|
|
38
|
+
>>> multiply_numbers(0, 5)
|
|
39
|
+
0
|
|
40
|
+
"""
|
|
41
|
+
return a * b
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def is_even(n: int) -> bool:
|
|
45
|
+
"""
|
|
46
|
+
Check if a number is even.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
n: The number to check
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
True if n is even, False otherwise
|
|
53
|
+
|
|
54
|
+
Examples:
|
|
55
|
+
>>> is_even(2)
|
|
56
|
+
True
|
|
57
|
+
>>> is_even(3)
|
|
58
|
+
False
|
|
59
|
+
>>> is_even(0)
|
|
60
|
+
True
|
|
61
|
+
"""
|
|
62
|
+
return n % 2 == 0
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def fibonacci(n: int) -> int:
|
|
66
|
+
"""
|
|
67
|
+
Calculate the nth Fibonacci number.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
n: The position in the Fibonacci sequence (0-based)
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
The nth Fibonacci number
|
|
74
|
+
|
|
75
|
+
Examples:
|
|
76
|
+
>>> fibonacci(0)
|
|
77
|
+
0
|
|
78
|
+
>>> fibonacci(1)
|
|
79
|
+
1
|
|
80
|
+
>>> fibonacci(5)
|
|
81
|
+
5
|
|
82
|
+
>>> fibonacci(10)
|
|
83
|
+
55
|
|
84
|
+
"""
|
|
85
|
+
if n < 0:
|
|
86
|
+
raise ValueError("n must be non-negative")
|
|
87
|
+
if n == 0:
|
|
88
|
+
return 0
|
|
89
|
+
if n == 1:
|
|
90
|
+
return 1
|
|
91
|
+
a, b = 0, 1
|
|
92
|
+
for _ in range(2, n + 1):
|
|
93
|
+
a, b = b, a + b
|
|
94
|
+
return b
|
|
File without changes
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Tests for webloom.utils module."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from webloom.utils import add_numbers, multiply_numbers, is_even, fibonacci
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestAddNumbers:
|
|
9
|
+
"""Test cases for add_numbers function."""
|
|
10
|
+
|
|
11
|
+
def test_positive_numbers(self):
|
|
12
|
+
"""Test adding positive numbers."""
|
|
13
|
+
assert add_numbers(1, 2) == 3
|
|
14
|
+
assert add_numbers(10, 20) == 30
|
|
15
|
+
|
|
16
|
+
def test_negative_numbers(self):
|
|
17
|
+
"""Test adding negative numbers."""
|
|
18
|
+
assert add_numbers(-1, -2) == -3
|
|
19
|
+
assert add_numbers(-5, 5) == 0
|
|
20
|
+
|
|
21
|
+
def test_zero(self):
|
|
22
|
+
"""Test adding with zero."""
|
|
23
|
+
assert add_numbers(0, 5) == 5
|
|
24
|
+
assert add_numbers(5, 0) == 5
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestMultiplyNumbers:
|
|
28
|
+
"""Test cases for multiply_numbers function."""
|
|
29
|
+
|
|
30
|
+
def test_basic_multiplication(self):
|
|
31
|
+
"""Test basic multiplication."""
|
|
32
|
+
assert multiply_numbers(2, 3) == 6
|
|
33
|
+
assert multiply_numbers(5, 4) == 20
|
|
34
|
+
|
|
35
|
+
def test_with_zero(self):
|
|
36
|
+
"""Test multiplication with zero."""
|
|
37
|
+
assert multiply_numbers(0, 5) == 0
|
|
38
|
+
assert multiply_numbers(5, 0) == 0
|
|
39
|
+
|
|
40
|
+
def test_negative_numbers(self):
|
|
41
|
+
"""Test multiplication with negative numbers."""
|
|
42
|
+
assert multiply_numbers(-2, 3) == -6
|
|
43
|
+
assert multiply_numbers(-2, -3) == 6
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class TestIsEven:
|
|
47
|
+
"""Test cases for is_even function."""
|
|
48
|
+
|
|
49
|
+
def test_even_numbers(self):
|
|
50
|
+
"""Test even numbers."""
|
|
51
|
+
assert is_even(0) is True
|
|
52
|
+
assert is_even(2) is True
|
|
53
|
+
assert is_even(100) is True
|
|
54
|
+
|
|
55
|
+
def test_odd_numbers(self):
|
|
56
|
+
"""Test odd numbers."""
|
|
57
|
+
assert is_even(1) is False
|
|
58
|
+
assert is_even(3) is False
|
|
59
|
+
assert is_even(99) is False
|
|
60
|
+
|
|
61
|
+
def test_negative_even(self):
|
|
62
|
+
"""Test negative even numbers."""
|
|
63
|
+
assert is_even(-2) is True
|
|
64
|
+
assert is_even(-4) is True
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class TestFibonacci:
|
|
68
|
+
"""Test cases for fibonacci function."""
|
|
69
|
+
|
|
70
|
+
def test_base_cases(self):
|
|
71
|
+
"""Test base cases."""
|
|
72
|
+
assert fibonacci(0) == 0
|
|
73
|
+
assert fibonacci(1) == 1
|
|
74
|
+
|
|
75
|
+
def test_small_values(self):
|
|
76
|
+
"""Test small Fibonacci numbers."""
|
|
77
|
+
assert fibonacci(2) == 1
|
|
78
|
+
assert fibonacci(3) == 2
|
|
79
|
+
assert fibonacci(4) == 3
|
|
80
|
+
assert fibonacci(5) == 5
|
|
81
|
+
assert fibonacci(6) == 8
|
|
82
|
+
|
|
83
|
+
def test_larger_value(self):
|
|
84
|
+
"""Test a larger Fibonacci number."""
|
|
85
|
+
assert fibonacci(10) == 55
|
|
86
|
+
assert fibonacci(15) == 610
|
|
87
|
+
|
|
88
|
+
def test_negative_raises_error(self):
|
|
89
|
+
"""Test that negative n raises ValueError."""
|
|
90
|
+
with pytest.raises(ValueError, match="n must be non-negative"):
|
|
91
|
+
fibonacci(-1)
|