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: default:
- build image: python:3.9
stages:
- lint
- build
build job: build job:
stage: build stage: build
script: script:
- cd src - cd src
- apt-get update -qy # - apt-get update -qy
- apt-get install -y python3-dev python3-pip python3.12-venv curl # - apt-get install -y python3-dev python3-pip python3.12-venv curl
- python3 -V - python3 -V
# - pip3 install --break-system-packages -r requirements.txt # - pip3 install --break-system-packages -r requirements.txt
- curl -sSL https://pdm-project.org/install-pdm.py | python3 - - curl -sSL https://pdm-project.org/install-pdm.py | python3 -
@@ -22,11 +25,18 @@ build job:
- export FLASK_APP=app - export FLASK_APP=app
- pdm run pytest tests --cov --cov-report term --cov-report html - pdm run pytest tests --cov --cov-report term --cov-report html
artifacts: artifacts:
paths: paths:
- src/htmlcov/ - 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: pages:
stage: build stage: build
dependencies: dependencies:

View File

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

View File

@@ -17,7 +17,6 @@
from urllib.parse import urlencode from urllib.parse import urlencode
import json import json
import pytest
__author__ = 'Michael Mader' __author__ = 'Michael Mader'
__date__ = "2023-03-12" __date__ = "2023-03-12"
@@ -40,48 +39,57 @@ def call(client, path, params):
response = client.get(url) response = client.get(url)
return json.loads(response.data.decode('utf-8')) return json.loads(response.data.decode('utf-8'))
# increment test 1 # increment test 1
def test_plus_one1(client): def test_plus_one1(client):
result = call(client, '/inc', {'x': 2}) result = call(client, '/inc', {'x': 2})
assert result['x'] == 3 assert result['x'] == 3
# increment test 1 # increment test 1
def test_plus_one2(client): def test_plus_one2(client):
result = call(client, '/inc', {'x': -2}) result = call(client, '/inc', {'x': -2})
assert result['x'] == -1 assert result['x'] == -1
# adding test with negative value # adding test with negative value
def test_plus_y(client): def test_plus_y(client):
result = call(client, '/add', {'x': -2, 'y': 7}) result = call(client, '/add', {'x': -2, 'y': 7})
assert result['result'] == 5 assert result['result'] == 5
# multiplication test # multiplication test
def test_multiply(client): def test_multiply(client):
result = call(client, '/mul', {'x': -2, 'y': 7}) result = call(client, '/mul', {'x': -2, 'y': 7})
assert result['result'] == -14 assert result['result'] == -14
# division test # division test
def test_division(client): def test_division(client):
result = call(client, '/div', {'x': 35, 'y': 7}) result = call(client, '/div', {'x': 35, 'y': 7})
assert result['result'] == 5 assert result['result'] == 5
# type tests # type tests
def test_type_inc(client): def test_type_inc(client):
result = call(client, '/inc', {'x': 'a'}) result = call(client, '/inc', {'x': 'a'})
assert result["error"] == "Type error" assert result["error"] == "Type error"
def test_type_add(client): def test_type_add(client):
result = call(client, '/add', {'x': 'a', 'y': 1}) result = call(client, '/add', {'x': 'a', 'y': 1})
assert result["error"] == "Type error" assert result["error"] == "Type error"
result = call(client, '/add', {'x': 1, 'y': 'a'}) result = call(client, '/add', {'x': 1, 'y': 'a'})
assert result["error"] == "Type error" assert result["error"] == "Type error"
def test_type_mul(client): def test_type_mul(client):
result = call(client, '/mul', {'x': 'a', 'y': 1}) result = call(client, '/mul', {'x': 'a', 'y': 1})
assert result["error"] == "Type error" assert result["error"] == "Type error"
result = call(client, '/mul', {'x': 1, 'y': 'a'}) result = call(client, '/mul', {'x': 1, 'y': 'a'})
assert result["error"] == "Type error" assert result["error"] == "Type error"
def test_type_div(client): def test_type_div(client):
result = call(client, '/div', {'x': 'a', 'y': 1}) result = call(client, '/div', {'x': 'a', 'y': 1})
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