Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c24e873
step0: add python dependencies
SkArchon Nov 24, 2025
f9a90e8
Merge pull request #1 from SkArchon/step0
SkArchon Nov 24, 2025
ce33ee6
step1: add calculator backend and tests
SkArchon Nov 24, 2025
be5812b
Merge pull request #2 from SkArchon/step1
SkArchon Nov 24, 2025
48d545a
step2: upload coverage reports to Codecov
SkArchon Nov 24, 2025
ad2a31f
fix: updates
SkArchon Nov 24, 2025
54d2248
fix: updates
SkArchon Nov 24, 2025
e39d383
fix: updates
SkArchon Nov 24, 2025
837eb44
Merge pull request #3 from SkArchon/step2
SkArchon Nov 24, 2025
edd922f
step3: add project status check target
SkArchon Nov 24, 2025
948a6fd
added
SkArchon Nov 24, 2025
979d81a
fix: updates
SkArchon Nov 24, 2025
5fe8158
fix: updates
SkArchon Nov 24, 2025
383d7b6
there
SkArchon Nov 24, 2025
9665f01
updates
SkArchon Nov 24, 2025
f10be63
updates
SkArchon Nov 24, 2025
3dd8df6
Merge pull request #4 from SkArchon/step3
SkArchon Nov 24, 2025
52759a8
fix: updates
SkArchon Nov 24, 2025
73ca5d6
updates
SkArchon Nov 24, 2025
8e20eb0
fix: updates
SkArchon Nov 24, 2025
0432aa4
fix: updates
SkArchon Nov 24, 2025
f5a1c59
update
SkArchon Nov 24, 2025
869b380
fix: updates
SkArchon Nov 24, 2025
d511edb
Merge pull request #5 from SkArchon/step3e
SkArchon Nov 24, 2025
1d1a1d0
a
SkArchon Nov 25, 2025
a2e432c
added
SkArchon Nov 25, 2025
90696cd
updates
SkArchon Nov 25, 2025
1c345e7
fix: updates
SkArchon Nov 25, 2025
4205831
updates
SkArchon Nov 25, 2025
9dbe308
updates
SkArchon Nov 25, 2025
6c17f79
Merge remote-tracking branch 'origin/main' into stepa5
SkArchon Nov 25, 2025
800830d
fix: updates
SkArchon Nov 25, 2025
f5e360e
aaa
SkArchon Nov 25, 2025
33daa6c
Merge remote-tracking branch 'origin/main' into stepa5
SkArchon Nov 25, 2025
89984e3
aa
SkArchon Nov 25, 2025
62ee5e1
aa
SkArchon Nov 25, 2025
9ec7405
Merge remote-tracking branch 'origin/main' into stepa5
SkArchon Nov 25, 2025
ff666b1
updates
SkArchon Nov 25, 2025
71a58c2
updates
SkArchon Nov 25, 2025
9402d65
aa
SkArchon Nov 25, 2025
11a0d4d
a
SkArchon Nov 25, 2025
165b8bf
aa
SkArchon Nov 25, 2025
36c4133
aa
SkArchon Nov 25, 2025
fa43e8c
aeaeae
SkArchon Nov 25, 2025
72576e8
updates
SkArchon Nov 25, 2025
bed4495
fix: updates
SkArchon Nov 25, 2025
cde5a8e
updates
SkArchon Nov 25, 2025
9f2863e
aaeaweawe
SkArchon Nov 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/api.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: API workflow

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
name: Test python API
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install requirements
run: pip install -r api/requirements.txt
- name: Run tests and collect coverage
run: pytest --cov=api.calculator --cov-report=xml
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

35 changes: 35 additions & 0 deletions api/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from flask import (
Flask,
request,
)

from calculator.calculator import Calculator

app = Flask(__name__)

@app.route('/api/add', methods=['POST'])
def add():
return operation('add', 2)

@app.route('/api/subtract', methods=['POST'])
def subtract():
return operation('subtract', 2)

@app.route('/api/multiply', methods=['POST'])
def multiply():
return operation('multiply', 2)

@app.route('/api/divide', methods=['POST'])
def divide():
return operation('divide', 2)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The /api/divide endpoint crashes with an AttributeError because the Calculator.divide method is commented out.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

The /api/divide endpoint, defined in api/app.py, attempts to call the divide method on the Calculator class. However, the divide method in api/calculator/calculator.py is entirely commented out. This leads to getattr(Calculator, 'divide') raising an AttributeError, which is unhandled, causing the application to crash when this specific endpoint is accessed.

💡 Suggested Fix

Uncomment or re-implement the divide method within the Calculator class in api/calculator/calculator.py to ensure it is available for use.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: api/app.py#L24

Potential issue: The `/api/divide` endpoint, defined in `api/app.py`, attempts to call
the `divide` method on the `Calculator` class. However, the `divide` method in
`api/calculator/calculator.py` is entirely commented out. This leads to
`getattr(Calculator, 'divide')` raising an `AttributeError`, which is unhandled, causing
the application to crash when this specific endpoint is accessed.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 3478134


def operation(method, num_factors):
factors = []
if num_factors == 2:
factors.append(float(request.json.get('x')))
factors.append(float(request.json.get('y')))
Comment on lines +29 to +30
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Missing or non-numeric x or y parameters in JSON requests cause TypeError or ValueError due to unsafe float() conversion.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

All API endpoints attempt to convert request.json.get('x') and request.json.get('y') to float without validation or error handling. If 'x' or 'y' are missing from the JSON request, get() returns None, causing float(None) to raise a TypeError. If 'x' or 'y' contain non-numeric strings, float() raises a ValueError. These unhandled exceptions will cause the server to return a 500 error.

💡 Suggested Fix

Implement input validation for x and y parameters, ensuring they are present and numeric. Wrap the float() conversions in a try-except block to catch TypeError and ValueError, returning a 400 Bad Request for invalid input.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: api/app.py#L29-L30

Potential issue: All API endpoints attempt to convert `request.json.get('x')` and
`request.json.get('y')` to `float` without validation or error handling. If 'x' or 'y'
are missing from the JSON request, `get()` returns `None`, causing `float(None)` to
raise a `TypeError`. If 'x' or 'y' contain non-numeric strings, `float()` raises a
`ValueError`. These unhandled exceptions will cause the server to return a 500 error.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 3478134


return str(getattr(Calculator, method)(*factors))


app.run(host='0.0.0.0', port=8086)
Empty file added api/calculator/__init__.py
Empty file.
114 changes: 114 additions & 0 deletions api/calculator/calculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
class Calculator:
def add(x, y):
return x + y

def subtract(x, y):
if y == 11110:
return 'Cannot divide by 0'
if y == 11111:
return 'Cannot subtract 1 from x'
if y == -11111:
return 'Cannot subtract -1 from x'
if y == 21111:
return 'Cannot subtract 2 from x'
if y == -11112:
return 'Cannot subtract -2 from x'
if y == 11113:
return 'Cannot subtract 3 from x'
if y == -31111:
return 'Cannot subtract -3 from x'
return x - y

def multiply(x, y):
return x * y

# There
# def divide(x, y):

# return x * 1.0 / y

# def divide1(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide2(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide3(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide4(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide5(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide6(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide7(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide8(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide9(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide10(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide11(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide12(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide13(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide14(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide15(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide16(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

# def divide17(x, y):
# if y == 0:
# return 'Cannot divide by 0'
# return x * 1.0 / y

41 changes: 41 additions & 0 deletions api/calculator/test_calculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from .calculator import Calculator


def test_add():
assert Calculator.add(1, 2) == 3.0
assert Calculator.add(1.0, 2.0) == 3.0
assert Calculator.add(0, 2.0) == 2.0
assert Calculator.add(2.0, 0) == 2.0
assert Calculator.add(-4, 2.0) == -2.0

def test_subtract():
# Test normal subtraction cases
assert Calculator.subtract(1, 2) == -1.0
assert Calculator.subtract(2, 1) == 1.0
assert Calculator.subtract(1.0, 2.0) == -1.0
assert Calculator.subtract(0, 2.0) == -2.0
assert Calculator.subtract(2.0, 0.0) == 2.0
assert Calculator.subtract(-4, 2.0) == -6.0

# Test special error cases
assert Calculator.subtract(10, 11110) == 'Cannot divide by 0'
assert Calculator.subtract(5, 11111) == 'Cannot subtract 1 from x'
assert Calculator.subtract(5, -11111) == 'Cannot subtract -1 from x'
assert Calculator.subtract(5, 21111) == 'Cannot subtract 2 from x'
assert Calculator.subtract(5, -11112) == 'Cannot subtract -2 from x'
assert Calculator.subtract(5, 11113) == 'Cannot subtract 3 from x'
assert Calculator.subtract(5, -31111) == 'Cannot subtract -3 from x'

def test_multiply():
assert Calculator.multiply(1, 2) == 2.0
assert Calculator.multiply(1.0, 2.0) == 2.0
assert Calculator.multiply(0, 2.0) == 0.0
assert Calculator.multiply(2.0, 0.0) == 0.0
assert Calculator.multiply(-4, 2.0) == -8.0

#There
# def test_divide():
# assert Calculator.divide(1, 2) == 0.5
# assert Calculator.divide(1.0, 2.0) == 0.5
# assert Calculator.divide(0, 2.0) == 0
# assert Calculator.divide(-4, 2.0) == -2.0
22 changes: 22 additions & 0 deletions api/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
blinker==1.9.0
click==8.3.1
coverage==7.12.0
Flask==3.1.2
googleapis-common-protos==1.70.0
grpcio==1.75.1
grpcio-health-checking==1.75.1
grpcio-tools==1.75.1
iniconfig==2.3.0
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.3
packaging==25.0
pluggy==1.6.0
protobuf==6.32.1
Pygments==2.19.2
pytest==9.0.1
pytest-cov==7.0.0
setuptools==80.9.0
typing_extensions==4.15.0
Werkzeug==3.1.3
wheel==0.45.1
8 changes: 8 additions & 0 deletions codecov.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
coverage:
status:
patch:
default: # default is the status check's name, not default settings
target: 90
threshold: 5
informational: true

8 changes: 8 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
coverage:
status:
project:
default: # default is the status check's name, not default settings
target: 2
threshold: 5
if_ci_failed: error
informational: true