Skip to content
Snippets Groups Projects
Commit a1f50c5e authored by fu2662cw's avatar fu2662cw :speech_balloon:
Browse files

Merge with master

parents 2fb24aa9 61ba6f37
No related branches found
No related tags found
No related merge requests found
Showing
with 441 additions and 72 deletions
......@@ -45,9 +45,11 @@ before_script:
#SOURCE: https://stephen-olabode.medium.com/running-black-formatter-to-lint-a-python-file-in-gitlab-ci-cd-ae80111ab363
black:
image: milansuk/python-black:latest
image: python:latest
before_script:
- pip install black
script:
- black --fast .
- black --check .
#SOURCE: https://pypi.org/project/pylint-gitlab/
pylint:
......@@ -57,23 +59,25 @@ pylint:
- python -V
- mkdir -p public/badges public/lint
- echo undefined > public/badges/$CI_JOB_NAME.score
- pip install pylint-gitlab
- pip install pylint-django
- pip install -r requirements.txt
script:
- pylint --exit-zero --output-format=text $(find -type f -name "*.py" ! -path "**/.venv/**") | tee /tmp/pylint.txt
- sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' /tmp/pylint.txt > public/badges/$CI_JOB_NAME.score
- pylint --exit-zero --output-format=pylint_gitlab.GitlabCodeClimateReporter $(find -type f -name "*.py" ! -path "**/.venv/**") > codeclimate.json
- pylint --exit-zero --output-format=pylint_gitlab.GitlabPagesHtmlReporter $(find -type f -name "*.py" ! -path "**/.venv/**") > public/lint/index.html
after_script:
- anybadge --overwrite --label $CI_JOB_NAME --value=$(cat public/badges/$CI_JOB_NAME.score) --file=public/badges/$CI_JOB_NAME.svg 4=red 6=orange 8=yellow 10=green
- |
echo "Your score is: $(cat public/badges/$CI_JOB_NAME.score)"
artifacts:
paths:
- public
reports:
codequality: codeclimate.json
when: always
#Due to Problems with Pylint, Ignored Files need to be presented here for now.
- ./custom_linter.sh
# - pylint --exit-zero --output-format=text $(find -type f -name "*.py" ! -path "**/.venv/**") | tee /tmp/pylint.txt
# - sed -n 's/^Your code has been rated at \([-0-9.]*\)\/.*/\1/p' /tmp/pylint.txt > public/badges/$CI_JOB_NAME.score
# - pylint --exit-zero --output-format=pylint_gitlab.GitlabCodeClimateReporter $(find -type f -name "*.py" ! -path "**/.venv/**") > codeclimate.json
# - pylint --exit-zero --output-format=pylint_gitlab.GitlabPagesHtmlReporter $(find -type f -name "*.py" ! -path "**/.venv/**") > public/lint/index.html
# after_script:
# - anybadge --overwrite --label $CI_JOB_NAME --value=$(cat public/badges/$CI_JOB_NAME.score) --file=public/badges/$CI_JOB_NAME.svg 4=red 6=orange 8=yellow 10=green
# - |
# echo "Your score is: $(cat public/badges/$CI_JOB_NAME.score)"
# artifacts:
# paths:
# - public
# reports:
# codequality: codeclimate.json
# when: always
#pages:
# stage: deploy
......
[MASTER]
fail-under=10
[MESSAGES CONTROL]
disable=line-too-long,
django-not-configured
git ls-files | grep -v 'migrations\|manage.py\|course_scraper\|tests.py' | grep -E '.py$' | xargs pylint --load-plugins=pylint_django
\ No newline at end of file
......@@ -6,6 +6,7 @@ for http://www.buchsys.de for SWP UniSport-O-Mat.
import requests
from bs4 import BeautifulSoup
def fetch_website(url):
"""
Helper function to fetch the content of a website.
......
......@@ -2,7 +2,7 @@
Testing module, yo. Just for the course_scraper.py.
"""
from django.test import TestCase
from course_scraper import scraping #, fetch_website
from course_scraper import scraping # , fetch_website
class ScraperTestCase(TestCase):
......@@ -10,6 +10,7 @@ class ScraperTestCase(TestCase):
Just a few tests, so pylint isn't getting a fit.
Because reasons.
"""
def test_returns_dict(self):
"""
Testing return type of scraping().
......
......@@ -6,7 +6,7 @@ import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unisportomat.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "unisportomat.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
......@@ -18,5 +18,5 @@ def main():
execute_from_command_line(sys.argv)
if __name__ == '__main__':
if __name__ == "__main__":
main()
# Generated by Django 3.2 on 2021-05-25 17:51
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Question",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
),
migrations.CreateModel(
name="Sport",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"sportart",
models.TextField(
choices=[
("After Work Fitness", "After Work Fitness"),
("Ballett", "Ballett"),
("Basketball", "Basketball"),
("Beachvolleyball", "Beachvolleyball"),
("Bouldern", "Bouldern"),
("Drachenfliegen", "Drachenfliegen"),
("Functional Fitness", "Functional Fitness"),
("Gerätturnen", "Gerätturnen"),
("HIIT", "HIIT"),
("Karate", "Karate"),
("Kickboxen", "Kickboxen"),
("Laufen", "Laufen"),
("Pilates", "Pilates"),
("Qigong", "Qigong"),
("Rückenfit", "Rückenfit"),
(
"Segeln Sportbootführerschein",
"Segeln Sportbootführerschein",
),
(
"Skilanglauf & Schneeschuhwandern",
"Skilanglauf & Schneeschuhwandern",
),
("Sweat & Relax", "Sweat & Relax"),
("Tennis", "Tennis"),
("Ultimate Frisbee", "Ultimate Frisbee"),
("Yoga", "Yoga"),
]
),
),
(
"field",
models.CharField(
choices=[("indoor", "indoor"), ("outdoor", "outdoor")],
default="outdoor",
max_length=50,
),
),
(
"einzelsport",
models.IntegerField(
choices=[
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=1,
),
),
(
"mannschaftssport",
models.IntegerField(
choices=[
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=1,
),
),
(
"ausdauer",
models.IntegerField(
choices=[
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=1,
),
),
(
"kraft",
models.IntegerField(
choices=[
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=1,
),
),
(
"kampfsport",
models.IntegerField(
choices=[
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=1,
),
),
(
"technischakrobatisch",
models.IntegerField(
choices=[
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8),
(9, 9),
(10, 10),
],
default=1,
),
),
("url", models.TextField()),
],
),
migrations.CreateModel(
name="Wissensnack",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
],
),
]
# Generated by Django 3.2 on 2021-05-25 15:14
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("quiz", "0001_refactor_sport_and_add_criteria"),
]
operations = [
migrations.CreateModel(
name="Question",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("text", models.TextField()),
],
),
migrations.AlterField(
model_name="criterionrating",
name="rating",
field=models.IntegerField(
validators=[
django.core.validators.MaxValueValidator(10),
django.core.validators.MinValueValidator(1),
]
),
),
]
# Generated by Django 3.2 on 2021-05-26 19:50
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("quiz", "0002_auto_20210525_1514"),
]
operations = [
migrations.AddField(
model_name="criterion",
name="question",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="quiz.question",
),
),
]
# Generated by Django 3.2 on 2021-05-26 20:14
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("quiz", "0003_criterion_question"),
]
operations = [
migrations.RemoveField(
model_name="criterion",
name="question",
),
migrations.RemoveField(
model_name="question",
name="id",
),
migrations.AddField(
model_name="question",
name="criterion",
field=models.OneToOneField(
default=None,
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
serialize=False,
to="quiz.criterion",
),
preserve_default=False,
),
]
# Generated by Django 3.2 on 2021-06-02 13:55
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('quiz', '0003_alter_calltomove_text'),
('quiz', '0004_auto_20210526_2014'),
]
operations = [
]
......@@ -68,3 +68,12 @@ class KnowledgeSnack(models.Model):
text = models.TextField()
image = models.ImageField(null=True, max_length=200)
class Question(models.Model):
"""Defines a Question that is assigned to exactly one Criterion"""
text = models.TextField()
criterion = models.OneToOneField(
Criterion, on_delete=models.CASCADE, primary_key=True
)
......@@ -7,7 +7,7 @@ import tempfile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings
from django.conf import settings
from .models import Sport, Criterion, CallToMove, KnowledgeSnack
from .models import Sport, Criterion, CallToMove, KnowledgeSnack, Question
class SportModelTest(TestCase):
......@@ -71,17 +71,6 @@ class CriterionRatingTest(TestCase):
self.assertEqual(self.test_sport.get_rating(criterion=self.criterion), 8)
class CriterionModelTest(TestCase):
"""Tests the Criterion model"""
def test_criterion_can_be_created(self):
"""New criterion is saved to the db"""
name = "Einzelsport"
Criterion(name=name).save()
test_criterion = Criterion.objects.first()
self.assertEqual(test_criterion.name, name)
FIXTURE_IMAGES = os.path.join(settings.BASE_DIR, "quiz", "fixtures", "images")
MEDIA_ROOT = tempfile.mkdtemp(
suffix="testing"
......@@ -157,3 +146,45 @@ class KnowledgeSnackTest(TestCase):
knowledge_snack = KnowledgeSnack.objects.first()
self.assertEqual(knowledge_snack.text, self.text)
self.assertEqual(knowledge_snack.image.name, self.image.name)
class CriterionAndQuestionModelTest(TestCase):
"""Tests the Criterion and the Question model which have a One to One Relation"""
def setUp(self):
self.name = "Einzelsport"
self.criterion = Criterion(name=self.name)
self.criterion.save()
def test_criterion_can_be_saved_and_loaded(self):
"""New criterion can be loaded from the db"""
test_criterion = Criterion.objects.first()
self.assertEqual(test_criterion.name, self.name)
def test_question_can_be_added(self):
"""
If a question is added to a criterion, then it is accessible through the criterion.
"""
text = "Ich trainiere gerne mit anderen im Team"
question = Question(text=text, criterion=self.criterion)
question.save()
self.criterion.question = question
self.assertEqual(question, self.criterion.question)
def test_criterion_stays_if_question_deleted(self):
"""If assigned question is deleted the foreign key is set None"""
text = "Ich trainiere gerne mit anderen im Team"
question = Question(text=text, criterion=self.criterion)
question.save()
question.delete()
self.criterion = Criterion.objects.first()
with self.assertRaises(Criterion.question.RelatedObjectDoesNotExist):
self.criterion.question
def test_question_can_be_saved_and_loaded(self):
"""New Question is saved to the db and can be loaded"""
text = "Ich trainiere gerne mit anderen im Team"
Question(text=text, criterion=self.criterion).save()
test_question = Question.objects.first()
self.assertEqual(test_question.text, text)
......@@ -11,6 +11,6 @@ import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unisportomat.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "unisportomat.settings")
application = get_asgi_application()
......@@ -22,7 +22,7 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-vl*o#be$=k)9mbtm3!8k!6pe&38cdfg1*#_y3s)kgp$czt4ctm'
SECRET_KEY = "django-insecure-vl*o#be$=k)9mbtm3!8k!6pe&38cdfg1*#_y3s)kgp$czt4ctm"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
......@@ -32,52 +32,52 @@ ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'quiz.apps.QuizConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"quiz.apps.QuizConfig",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = 'unisportomat.urls'
ROOT_URLCONF = "unisportomat.urls"
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = 'unisportomat.wsgi.application'
WSGI_APPLICATION = "unisportomat.wsgi.application"
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
......@@ -86,25 +86,25 @@ DATABASES = {
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = "en-us"
TIME_ZONE = 'UTC'
TIME_ZONE = "UTC"
USE_I18N = True
......@@ -115,9 +115,9 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
STATIC_URL = "/static/"
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
......@@ -17,5 +17,5 @@ from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
path("admin/", admin.site.urls),
]
......@@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'unisportomat.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "unisportomat.settings")
application = get_wsgi_application()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment