Merge branch 'feat/Q1.3'

Feat/q1.3

See merge request Klagarge/mse2425-grp09!3
This commit is contained in:
Alec Schmidt
2025-03-18 09:45:02 +00:00
7 changed files with 48 additions and 23 deletions

View File

@@ -1,13 +1,16 @@
stages:
- build
default:
image: python:3.9
stages:
- lint
- build
build job:
stage: build
script:
- cd src
- apt-get update -qy
- apt-get install -y python3-dev python3-pip python3.12-venv curl
# - apt-get update -qy
# - apt-get install -y python3-dev python3-pip python3.12-venv curl
- python3 -V
# - pip3 install --break-system-packages -r requirements.txt
- curl -sSL https://pdm-project.org/install-pdm.py | python3 -
@@ -22,11 +25,18 @@ build job:
- export FLASK_APP=app
- pdm run pytest tests --cov --cov-report term --cov-report html
artifacts:
paths:
- src/htmlcov/
lint job:
stage: lint
dependencies: []
script:
- python3 -m pip install flake8
- flake8 src/
allow_failure: true # Linter can fail, fixing it is for now outside of the projects scope
pages:
stage: build
dependencies:

View File

@@ -11,3 +11,7 @@
## Q1.2
- It's a very bad practice. The secret key will be exposed in the codebase and can be easily accessed by anyone who has access to the codebase. This can lead to security vulnerabilities and compromise the integrity of the application.
- To fix this, you can use environment variables to store the secret key.
## Q1.3
- A linter is a tool to statically analyse code for readability and improving code quality. It is usually executed from a standalone tool.
- It is used to check for errors, vulns, code smells or general issues but also to enforce a coding style over the whole project.

View File

@@ -18,12 +18,8 @@
from flask import request, Flask, url_for, render_template, redirect
import operators
import json
from dotenv import load_dotenv
import os
__author__ = 'Michael Mäder'
__date__ = "2025-03-10"
__version__ = "0.5"
@@ -40,7 +36,8 @@ A little web application that offers API calls for arithmetic operations
# creation of the Flask application
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY') # super secure key against CSRF attacks
# super secure key against CSRF attacks
app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY')
# global variable containing the name of the login user
global_data = {'username': 'no_user'}
@@ -51,18 +48,19 @@ global_data = {'username': 'no_user'}
def plus_one():
try:
x = int(request.args.get('x', 1))
except:
except ValueError:
return json.dumps({"error": "Type error"})
return json.dumps({'x': operators.addition(x, 1)})
# addition route, the parameters will be passed with 'x' and 'y'
@app.route('/add')
def plus_y():
try:
x = int(request.args.get('x', 1))
y = int(request.args.get('y', 1))
except:
except ValueError:
return json.dumps({"error": "Type error"})
return json.dumps({'result': operators.addition(x, y)})
@@ -73,7 +71,7 @@ def multiply_y():
try:
x = int(request.args.get('x', 1))
y = int(request.args.get('y', 1))
except:
except ValueError:
return json.dumps({"error": "Type error"})
return json.dumps({'result': operators.multiplication(x, y)})
@@ -84,7 +82,7 @@ def division_y():
try:
x = int(request.args.get('x', 1))
y = int(request.args.get('y', 1))
except:
except ValueError:
return json.dumps({"error": "Type error"})
return json.dumps({'result': operators.division(x, y)})

View File

@@ -23,17 +23,17 @@ __email__ = "michael.maeder@hefr.ch"
# file containing the operations for the calculator
# addition: returns x+y
# addition: returns x+y
def addition(x, y):
return x+y
# subtraction: returns x-y
# subtraction: returns x-y
def subtraction(x, y):
return x-y
# multiplication: returns x*y
# multiplication: returns x*y
def multiplication(x, y):
return x*y
@@ -42,6 +42,6 @@ def multiplication(x, y):
# returns None if the divisor is zero
# the result might be of float type
def division(x, y):
if y==0:
if y == 0:
return None
return x/y

View File

@@ -5,7 +5,7 @@ from app import app
# the client here allow to use the app without running in live server
# see https://flask.palletsprojects.com/en/2.0.x/testing/#sending-requests-with-the-test-client
# see https://flask.palletsprojects.com/en/2.0.x/testing/#sending-requests-with-the-test-client # noqa: E501
@pytest.fixture
def client():
app.config['TESTING'] = True

View File

@@ -17,7 +17,6 @@
from urllib.parse import urlencode
import json
import pytest
__author__ = 'Michael Mader'
__date__ = "2023-03-12"
@@ -27,12 +26,12 @@ __email__ = "michael.maeder@hefr.ch"
def call(client, path, params):
"""calling function that simulates an API webcall of a specific function/route
Args:
client: this is the client object used by pytest to 'simulate' the API without running the webserver
path: route of the API to use
params: GET parameter that are passed to the function
Returns:
json: the result of the client call
"""
@@ -40,50 +39,59 @@ def call(client, path, params):
response = client.get(url)
return json.loads(response.data.decode('utf-8'))
# increment test 1
def test_plus_one1(client):
result = call(client, '/inc', {'x': 2})
assert result['x'] == 3
# increment test 1
def test_plus_one2(client):
result = call(client, '/inc', {'x': -2})
assert result['x'] == -1
# adding test with negative value
def test_plus_y(client):
result = call(client, '/add', {'x': -2, 'y': 7})
assert result['result'] == 5
# multiplication test
def test_multiply(client):
result = call(client, '/mul', {'x': -2, 'y': 7})
assert result['result'] == -14
# division test
def test_division(client):
result = call(client, '/div', {'x': 35, 'y': 7})
assert result['result'] == 5
# type tests
def test_type_inc(client):
result = call(client, '/inc', {'x': 'a'})
assert result["error"] == "Type error"
def test_type_add(client):
result = call(client, '/add', {'x': 'a', 'y': 1})
assert result["error"] == "Type error"
result = call(client, '/add', {'x': 1, 'y': 'a'})
assert result["error"] == "Type error"
def test_type_mul(client):
result = call(client, '/mul', {'x': 'a', 'y': 1})
assert result["error"] == "Type error"
result = call(client, '/mul', {'x': 1, 'y': 'a'})
assert result["error"] == "Type error"
def test_type_div(client):
result = call(client, '/div', {'x': 'a', 'y': 1})
assert result["error"] == "Type error"
result = call(client, '/div', {'x': 1, 'y': 'a'})
assert result["error"] == "Type error"
assert result["error"] == "Type error"

5
tox.ini Normal file
View File

@@ -0,0 +1,5 @@
[flake8]
extend-ignore = E203
exclude = .git,__pycache__,.venv
max-complexity = 10
max-line-length = 120