From 799f9820fbce277d05096eaaa53200169a407f4b Mon Sep 17 00:00:00 2001 From: magsyg Date: Thu, 8 Feb 2024 19:20:15 +0100 Subject: [PATCH] ruff --- backend/root/custom_classes/admin_classes.py | 4 +- backend/root/custom_classes/middlewares.py | 1 - .../root/custom_classes/permission_classes.py | 1 - backend/root/db_router.py | 1 - .../root/management/commands/cleanstart.py | 1 - .../management/commands/deletemigrations.py | 1 - .../management/commands/deploymigrations.py | 1 - .../commands/generate_permissions.py | 1 + .../root/management/commands/migratezero.py | 1 - backend/root/management/commands/seed.py | 3 +- .../commands/seed_scripts/events.py | 3 +- .../management/commands/seed_scripts/gangs.py | 32 ++- .../commands/seed_scripts/images.py | 12 +- .../management/commands/seed_scripts/menu.py | 11 +- .../seed_scripts/recruitment_admissions.py | 3 +- .../management/commands/seed_scripts/samf3.py | 4 +- .../commands/seed_scripts/textitems.py | 18 +- .../management/commands/setupmigrations.py | 1 - .../management/commands/setupmigrations2.py | 1 - backend/root/settings/__init__.py | 3 +- backend/root/settings/base.py | 199 +++++++++--------- backend/root/settings/prod.py | 34 ++- backend/root/utils/mixins.py | 4 +- backend/samfundet/conftest.py | 1 + backend/samfundet/homepage/homepage.py | 38 ++-- backend/samfundet/models/general.py | 1 - .../models/tests/test_recruitment.py | 2 - .../models/tests/test_reservation.py | 1 - backend/samfundet/models/utils/fields.py | 2 - backend/samfundet/serializers.py | 29 +-- backend/samfundet/tests/test_signals.py | 2 - backend/samfundet/tests/test_views.py | 7 +- backend/samfundet/utils.py | 11 +- backend/samfundet/views.py | 44 ++-- 34 files changed, 213 insertions(+), 265 deletions(-) diff --git a/backend/root/custom_classes/admin_classes.py b/backend/root/custom_classes/admin_classes.py index 80906cf14..8ba2af927 100644 --- a/backend/root/custom_classes/admin_classes.py +++ b/backend/root/custom_classes/admin_classes.py @@ -54,7 +54,7 @@ def user_link(self, obj: Contact) -> str: def get_admin_url(*, obj: Any) -> str: """https://stackoverflow.com/questions/10420271/django-how-to-get-admin-url-from-model-instance""" info = (obj._meta.app_label, obj._meta.model_name) - admin_url = reverse('admin:%s_%s_change' % info, args=(obj.pk, )) + admin_url = reverse('admin:%s_%s_change' % info, args=(obj.pk,)) return admin_url @@ -258,7 +258,7 @@ def _insert_link(*, field: str, related_links: list[str]) -> str: def autocomplete_filter(**kwargs: Any) -> AutocompleteFilter: """Simple AutocompleteFilter factory.""" - return type('AutocompleteFilter', (AutocompleteFilter, ), kwargs) + return type('AutocompleteFilter', (AutocompleteFilter,), kwargs) class CustomGuardedUserAdmin(CustomGuardedModelAdmin, UserAdmin): diff --git a/backend/root/custom_classes/middlewares.py b/backend/root/custom_classes/middlewares.py index c894b34a7..c208d3118 100644 --- a/backend/root/custom_classes/middlewares.py +++ b/backend/root/custom_classes/middlewares.py @@ -53,7 +53,6 @@ def process_exception(self, request: HttpRequest, exception: Exception) -> None: class ImpersonateUserMiddleware: - def __init__(self, get_response: HttpResponse) -> None: self.get_response = get_response diff --git a/backend/root/custom_classes/permission_classes.py b/backend/root/custom_classes/permission_classes.py index f72892103..70f987f6c 100644 --- a/backend/root/custom_classes/permission_classes.py +++ b/backend/root/custom_classes/permission_classes.py @@ -14,7 +14,6 @@ class SuperUserPermission(BasePermission): - def has_permission(self, request: Request, view: APIView) -> bool: # noqa: PLR0917 user: User = request.user return user.is_active and user.is_superuser diff --git a/backend/root/db_router.py b/backend/root/db_router.py index 4ee9f6db9..9fb9a8268 100644 --- a/backend/root/db_router.py +++ b/backend/root/db_router.py @@ -23,7 +23,6 @@ class SamfundetDatabaseRouter: - def db_for_read(self, model: Type[models.Model], **hints: dict[str, Any]) -> str | None: if model in BILLIG_MODELS: return 'billig' diff --git a/backend/root/management/commands/cleanstart.py b/backend/root/management/commands/cleanstart.py index d48b2014b..b653bff92 100644 --- a/backend/root/management/commands/cleanstart.py +++ b/backend/root/management/commands/cleanstart.py @@ -8,7 +8,6 @@ class Command(BaseCommand): - def add_arguments(self, parser): parser.add_argument( '--noinput', diff --git a/backend/root/management/commands/deletemigrations.py b/backend/root/management/commands/deletemigrations.py index 10f76bbda..86b1e3e85 100644 --- a/backend/root/management/commands/deletemigrations.py +++ b/backend/root/management/commands/deletemigrations.py @@ -12,7 +12,6 @@ class Command(BaseCommand): - def add_arguments(self, parser): parser.add_argument( '--noinput', diff --git a/backend/root/management/commands/deploymigrations.py b/backend/root/management/commands/deploymigrations.py index 4e58d35b4..18ec99279 100644 --- a/backend/root/management/commands/deploymigrations.py +++ b/backend/root/management/commands/deploymigrations.py @@ -8,7 +8,6 @@ class Command(BaseCommand): - def add_arguments(self, parser): parser.add_argument( '--noinput', diff --git a/backend/root/management/commands/generate_permissions.py b/backend/root/management/commands/generate_permissions.py index 55a0ce921..f8ddfbb70 100644 --- a/backend/root/management/commands/generate_permissions.py +++ b/backend/root/management/commands/generate_permissions.py @@ -4,6 +4,7 @@ from django.utils import timezone from django.contrib.auth.models import Permission from django.core.management.base import BaseCommand + """ NOTE: This command cannot run within docker container because the backend has no access to the frontend. Use on host machine. diff --git a/backend/root/management/commands/migratezero.py b/backend/root/management/commands/migratezero.py index 07d401f3b..d404bc231 100644 --- a/backend/root/management/commands/migratezero.py +++ b/backend/root/management/commands/migratezero.py @@ -9,7 +9,6 @@ class Command(BaseCommand): - def add_arguments(self, parser): parser.add_argument( '--noinput', diff --git a/backend/root/management/commands/seed.py b/backend/root/management/commands/seed.py index 4202c7f98..b724bcb62 100755 --- a/backend/root/management/commands/seed.py +++ b/backend/root/management/commands/seed.py @@ -56,8 +56,7 @@ def run_seed_script(*, target: tuple, index: int, count: int): elif type(step) in [int, float]: print_progress(progress=step, prefix=prefix, start_time=start_time) else: - raise Exception(f"Seed script {target[0]} yielded wrong type '{type(step)}', " - 'expected number type or tuple of (number, str)') + raise Exception(f"Seed script {target[0]} yielded wrong type '{type(step)}', " 'expected number type or tuple of (number, str)') # Final output 100%. if isinstance(step, tuple): diff --git a/backend/root/management/commands/seed_scripts/events.py b/backend/root/management/commands/seed_scripts/events.py index 77220be37..10e9176fc 100755 --- a/backend/root/management/commands/seed_scripts/events.py +++ b/backend/root/management/commands/seed_scripts/events.py @@ -150,7 +150,8 @@ def do_seed(): name_nb=f'Billett {i + 1}', name_en=f'Ticket {i + 1}', price=random.randint(50, 200), - ) for i in range(0, random.randint(2, 4)) + ) + for i in range(0, random.randint(2, 4)) ] # Create event(s) diff --git a/backend/root/management/commands/seed_scripts/gangs.py b/backend/root/management/commands/seed_scripts/gangs.py index 0b601ba8c..0810c1644 100755 --- a/backend/root/management/commands/seed_scripts/gangs.py +++ b/backend/root/management/commands/seed_scripts/gangs.py @@ -9,23 +9,21 @@ ('Lørdagskomiteen', 'LØK'), ('Klubbstyret', 'KLST'), ], - 'Drift': - [ - ('Markedsføringsgjengen', 'MG'), - ('Fotogjengen', 'FG'), - ('Diversegjengen', 'DG'), - ('Forsterkerkomiteen', 'FK'), - ('Regi', None), - ('Videokomiteen', 'VK'), - ], - 'Kunstneriske': - [ - ('Studentersamfundets interne teater', 'SIT'), - ('Studentersamfundets Symfoniorkester', 'Symforch'), - ('Strindens promenadeorkester', 'SPO'), - ('Pirum', None), - ('Candiss', None), - ], + 'Drift': [ + ('Markedsføringsgjengen', 'MG'), + ('Fotogjengen', 'FG'), + ('Diversegjengen', 'DG'), + ('Forsterkerkomiteen', 'FK'), + ('Regi', None), + ('Videokomiteen', 'VK'), + ], + 'Kunstneriske': [ + ('Studentersamfundets interne teater', 'SIT'), + ('Studentersamfundets Symfoniorkester', 'Symforch'), + ('Strindens promenadeorkester', 'SPO'), + ('Pirum', None), + ('Candiss', None), + ], 'Styrende': [ ('Finansstyret', 'FS'), ('Styret', None), diff --git a/backend/root/management/commands/seed_scripts/images.py b/backend/root/management/commands/seed_scripts/images.py index 5b148d88c..727ccfbc6 100644 --- a/backend/root/management/commands/seed_scripts/images.py +++ b/backend/root/management/commands/seed_scripts/images.py @@ -40,10 +40,14 @@ def do_seed(): random_image = ImageFile(image_file, name=f'img_{i}') title = words(random.randint(1, 2)) image = Image.objects.create(title=title, image=random_image) - image.tags.set(random.choices( - Tag.objects.all().values_list(flat=True, ), - k=random.randint(1, 4), - )) + image.tags.set( + random.choices( + Tag.objects.all().values_list( + flat=True, + ), + k=random.randint(1, 4), + ) + ) yield int(i / COUNT * 100), 'Creating images' # Remember to close files! diff --git a/backend/root/management/commands/seed_scripts/menu.py b/backend/root/management/commands/seed_scripts/menu.py index 30469418c..a6159a024 100755 --- a/backend/root/management/commands/seed_scripts/menu.py +++ b/backend/root/management/commands/seed_scripts/menu.py @@ -38,10 +38,13 @@ def seed(): FoodPreference.objects.all().delete() # Create food preferences - prefs = [FoodPreference.objects.create( - name_nb=p_name[0], - name_en=p_name[1], - ) for p_name in preferences] + prefs = [ + FoodPreference.objects.create( + name_nb=p_name[0], + name_en=p_name[1], + ) + for p_name in preferences + ] yield 10, f'Created {len(preferences)} food preferences' # Create menu categories diff --git a/backend/root/management/commands/seed_scripts/recruitment_admissions.py b/backend/root/management/commands/seed_scripts/recruitment_admissions.py index ac1ab854a..d777be46d 100644 --- a/backend/root/management/commands/seed_scripts/recruitment_admissions.py +++ b/backend/root/management/commands/seed_scripts/recruitment_admissions.py @@ -27,8 +27,7 @@ def seed(): { 'recruitment_position': position, 'recruitment': position.recruitment, - 'user': users[randint(0, - len(users) - 1)], # random user from all users + 'user': users[randint(0, len(users) - 1)], # random user from all users } ) _admission, created = RecruitmentAdmission.objects.get_or_create(**admission_data) diff --git a/backend/root/management/commands/seed_scripts/samf3.py b/backend/root/management/commands/seed_scripts/samf3.py index 715d226ec..9232d864f 100755 --- a/backend/root/management/commands/seed_scripts/samf3.py +++ b/backend/root/management/commands/seed_scripts/samf3.py @@ -123,7 +123,7 @@ def seed() -> Iterator[tuple[int, str]]: with open(event_path, 'r') as event_file: with open(image_path, 'r') as image_file: events = list(reversed(list(csv.DictReader(event_file)))) - events = events[0:min(max_events, len(events))] + events = events[0 : min(max_events, len(events))] images = list(csv.DictReader(image_file)) event_models = [] @@ -132,7 +132,7 @@ def seed() -> Iterator[tuple[int, str]]: for chunk in range(len(events) // chunk_size): start = chunk * chunk_size - events_in_chunk = events[start:min(start + chunk_size, len(events))] + events_in_chunk = events[start : min(start + chunk_size, len(events))] jobs = [(images, event) for event in events_in_chunk] models = pool.starmap(add_event, jobs) models = [e for e in models if e is not None] diff --git a/backend/root/management/commands/seed_scripts/textitems.py b/backend/root/management/commands/seed_scripts/textitems.py index a9b90e79c..81c7ce8a1 100644 --- a/backend/root/management/commands/seed_scripts/textitems.py +++ b/backend/root/management/commands/seed_scripts/textitems.py @@ -38,23 +38,17 @@ def seed(): 'text_en': 'Do you have any questions or want to get in touch with us? Don"t hesitate to contact us!', }, { - 'key': - 'sulten_reservation_help', - 'text_nb': - """Bord må reserveres minst en dag i forveien. Mat kan forhåndsbestilles slik at dere ikke trenger å vente når dere kommer. + 'key': 'sulten_reservation_help', + 'text_nb': """Bord må reserveres minst en dag i forveien. Mat kan forhåndsbestilles slik at dere ikke trenger å vente når dere kommer. Merk at flertallet av personer må være medlem for å reservere og at alle må være over 20 år etter kl 20:00 i helger.""", - 'text_en': - """Tables must be reserved at least one day in advance. Food can be pre-ordered so you do not have to wait when you arrive. + 'text_en': """Tables must be reserved at least one day in advance. Food can be pre-ordered so you do not have to wait when you arrive. Note that the majority of people must be a member of the Student Society to reserve and that all must be over 20 years after 20:00 on weekends.""", }, { - 'key': - 'sulten_reservation_contact', - 'text_nb': - 'Reservasjonssystemet vårt er fortsatt under utvikling, og vi ber om forbehold om at feil kan forekomme. Klikk her for å bestille via epost: ', - 'text_en': - 'Our reservation system is still under development, and reservation errors may therefore occur. Click here to order via email: ', + 'key': 'sulten_reservation_contact', + 'text_nb': 'Reservasjonssystemet vårt er fortsatt under utvikling, og vi ber om forbehold om at feil kan forekomme. Klikk her for å bestille via epost: ', + 'text_en': 'Our reservation system is still under development, and reservation errors may therefore occur. Click here to order via email: ', }, ] diff --git a/backend/root/management/commands/setupmigrations.py b/backend/root/management/commands/setupmigrations.py index ea3c6242e..29001c5e0 100644 --- a/backend/root/management/commands/setupmigrations.py +++ b/backend/root/management/commands/setupmigrations.py @@ -10,7 +10,6 @@ class Command(BaseCommand): - def handle(self, *args, **options): for app in settings.PROJECT_APPS: try: diff --git a/backend/root/management/commands/setupmigrations2.py b/backend/root/management/commands/setupmigrations2.py index bd1dcc45b..d7016da01 100644 --- a/backend/root/management/commands/setupmigrations2.py +++ b/backend/root/management/commands/setupmigrations2.py @@ -9,7 +9,6 @@ class Command(BaseCommand): - def handle(self, *args, **options): for app in settings.INSTALLED_APPS: appname = app.split('.')[-1] diff --git a/backend/root/settings/__init__.py b/backend/root/settings/__init__.py index e5e20c2d7..7ece708e7 100644 --- a/backend/root/settings/__init__.py +++ b/backend/root/settings/__init__.py @@ -12,8 +12,7 @@ # Raise exception if ENV is invalid (and show possible options). if ENV not in Environment.VALID: ENV_OPTIONS = ''.join([f'\n\t{env}' for env in Environment.VALID]) - raise Exception(f"Environment variable 'ENV' is required to import this module ('{__name__}')." - f'Possible values: {ENV_OPTIONS}') + raise Exception(f"Environment variable 'ENV' is required to import this module ('{__name__}')." f'Possible values: {ENV_OPTIONS}') if ENV == Environment.DEV: from .dev import * # type: ignore[assignment] # noqa: F403 diff --git a/backend/root/settings/base.py b/backend/root/settings/base.py index f613da71f..c1fb44bbf 100644 --- a/backend/root/settings/base.py +++ b/backend/root/settings/base.py @@ -113,16 +113,14 @@ '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', - ], - }, + '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', + ], + }, }, ] @@ -172,13 +170,12 @@ # 'rest_framework.permissions.IsAuthenticated', 'rest_framework.authentication.SessionAuthentication', ], - 'DEFAULT_PERMISSION_CLASSES': - [ - # 'rest_framework.permissions.IsAuthenticated', - # 'rest_framework.permissions.DjangoObjectPermissions', - 'root.custom_classes.permission_classes.SuperUserPermission', - # 'root.custom_classes.permission_classes.CustomDjangoObjectPermissions', - ], + 'DEFAULT_PERMISSION_CLASSES': [ + # 'rest_framework.permissions.IsAuthenticated', + # 'rest_framework.permissions.DjangoObjectPermissions', + 'root.custom_classes.permission_classes.SuperUserPermission', + # 'root.custom_classes.permission_classes.CustomDjangoObjectPermissions', + ], } ### End: DRF ### @@ -217,97 +214,91 @@ LOGGING = { 'version': 1, 'disable_existing_loggers': False, - 'formatters': - { - 'json': { - # Need to be a callable in order to use init parameters. - '()': lambda: JsonFormatter(indent=4 if ENV == Environment.DEV else None), - }, - 'file': { - 'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s', - }, + 'formatters': { + 'json': { + # Need to be a callable in order to use init parameters. + '()': lambda: JsonFormatter(indent=4 if ENV == Environment.DEV else None), + }, + 'file': { + 'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s', + }, + }, + 'filters': { + 'request_context_filter': { + '()': RequestContextFilter, + }, + 'require_debug_false': { + '()': 'django.utils.log.RequireDebugFalse', + }, + 'require_debug_true': { + '()': 'django.utils.log.RequireDebugTrue', + }, + }, + 'handlers': { + 'null': { + 'class': 'logging.NullHandler', }, - 'filters': - { - 'request_context_filter': { - '()': RequestContextFilter, - }, - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse', - }, - 'require_debug_true': { - '()': 'django.utils.log.RequireDebugTrue', - }, + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'filters': ['require_debug_true'], }, - 'handlers': - { - 'null': { - 'class': 'logging.NullHandler', - }, - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - 'filters': ['require_debug_true'], - }, - 'file': { - 'level': 'INFO', - 'class': 'logging.FileHandler', - 'formatter': 'json', - 'filename': LOGFILENAME, - 'filters': ['request_context_filter'], - }, - 'mail_admins': { - 'level': 'ERROR', - 'class': 'django.utils.log.AdminEmailHandler', - 'filters': ['require_debug_false'], - }, - 'humio': - { - 'level': 'DEBUG' if ENV == Environment.DEV else 'INFO', - 'formatter': 'json', - 'class': 'logging.StreamHandler', - 'stream': sys.stdout, - 'filters': ['request_context_filter'], - }, - 'sql_file': - { - 'level': 'DEBUG', - 'class': 'logging.FileHandler', - 'mode': 'w', - 'filename': SQL_LOG_FILE, # Added to '.gitignore'. - 'filters': ['require_debug_true'], - }, + 'file': { + 'level': 'INFO', + 'class': 'logging.FileHandler', + 'formatter': 'json', + 'filename': LOGFILENAME, + 'filters': ['request_context_filter'], }, - 'loggers': - { - # Default logger. - '': { - 'handlers': ['humio', 'file'], - 'propagate': True, - 'level': 'INFO', - }, - # Catch all from django unless explicitly prevented propagation. - 'django': { - 'handlers': ['console', 'mail_admins'], - 'propagate': True, - 'level': 'DEBUG', - }, - 'django.db.backends': { - 'handlers': ['sql_file'], - 'propagate': False, # Don't pass up to 'django'. - 'level': 'DEBUG', - }, - 'django.server': { - 'handlers': ['console'], - 'propagate': False, # Don't pass up to 'django'. - 'level': 'INFO', - }, - 'django.utils.autoreload': { - 'handlers': ['console'], - 'propagate': False, # Don't pass up to 'django'. - 'level': 'INFO', - }, + 'mail_admins': { + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler', + 'filters': ['require_debug_false'], }, + 'humio': { + 'level': 'DEBUG' if ENV == Environment.DEV else 'INFO', + 'formatter': 'json', + 'class': 'logging.StreamHandler', + 'stream': sys.stdout, + 'filters': ['request_context_filter'], + }, + 'sql_file': { + 'level': 'DEBUG', + 'class': 'logging.FileHandler', + 'mode': 'w', + 'filename': SQL_LOG_FILE, # Added to '.gitignore'. + 'filters': ['require_debug_true'], + }, + }, + 'loggers': { + # Default logger. + '': { + 'handlers': ['humio', 'file'], + 'propagate': True, + 'level': 'INFO', + }, + # Catch all from django unless explicitly prevented propagation. + 'django': { + 'handlers': ['console', 'mail_admins'], + 'propagate': True, + 'level': 'DEBUG', + }, + 'django.db.backends': { + 'handlers': ['sql_file'], + 'propagate': False, # Don't pass up to 'django'. + 'level': 'DEBUG', + }, + 'django.server': { + 'handlers': ['console'], + 'propagate': False, # Don't pass up to 'django'. + 'level': 'INFO', + }, + 'django.utils.autoreload': { + 'handlers': ['console'], + 'propagate': False, # Don't pass up to 'django'. + 'level': 'INFO', + }, + }, } # Quick fix for avoiding concurrency issues related to db access diff --git a/backend/root/settings/prod.py b/backend/root/settings/prod.py index 1555e49d1..cd712e696 100644 --- a/backend/root/settings/prod.py +++ b/backend/root/settings/prod.py @@ -27,23 +27,21 @@ DATABASES = { # The default database used for all Samf4 models - 'default': - { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': os.environ['DB_NAME'], - 'USER': os.environ['DB_USER'], - 'PASSWORD': os.environ['DB_PASSWORD'], - 'HOST': os.environ['DB_HOST'], - 'PORT': os.environ['DB_PORT'], - }, + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.environ['DB_NAME'], + 'USER': os.environ['DB_USER'], + 'PASSWORD': os.environ['DB_PASSWORD'], + 'HOST': os.environ['DB_HOST'], + 'PORT': os.environ['DB_PORT'], + }, # The database for the billig system - 'billig': - { - 'ENGINE': 'django.db.backends.postgresql', - 'NAME': os.environ['BILLIG_DB_NAME'], - 'USER': os.environ['BILLIG_DB_USER'], - 'PASSWORD': os.environ['BILLIG_DB_PASSWORD'], - 'HOST': os.environ['BILLIG_DB_HOST'], - 'PORT': os.environ['BILLIG_DB_PORT'], - }, + 'billig': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': os.environ['BILLIG_DB_NAME'], + 'USER': os.environ['BILLIG_DB_USER'], + 'PASSWORD': os.environ['BILLIG_DB_PASSWORD'], + 'HOST': os.environ['BILLIG_DB_HOST'], + 'PORT': os.environ['BILLIG_DB_PORT'], + }, } diff --git a/backend/root/utils/mixins.py b/backend/root/utils/mixins.py index fe52dd818..4ed6c8c4d 100644 --- a/backend/root/utils/mixins.py +++ b/backend/root/utils/mixins.py @@ -140,9 +140,7 @@ def save(self, *args: Any, **kwargs: Any) -> None: else: # Log changes. LOG.info(f'{self} has changed:\n\nold: {dirty_fields_old}\n\n new:{dirty_fields_new}') LOG.info( - f'{self} has changed:\n\n' - f'old: {self.ftm_log_parse(fields=dirty_fields_old)}\n\n' - f'new:{self.ftm_log_parse(fields=dirty_fields_new)}' + f'{self} has changed:\n\n' f'old: {self.ftm_log_parse(fields=dirty_fields_old)}\n\n' f'new:{self.ftm_log_parse(fields=dirty_fields_new)}' ) except Exception as e: # Get all changes. diff --git a/backend/samfundet/conftest.py b/backend/samfundet/conftest.py index afbed63ac..01aff33bd 100644 --- a/backend/samfundet/conftest.py +++ b/backend/samfundet/conftest.py @@ -22,6 +22,7 @@ from samfundet.models.general import Gang, User, Image, Table, Venue, BlogPost, TextItem, Reservation, Organization, InformationPage from samfundet.models.recruitment import Recruitment, RecruitmentPosition, RecruitmentAdmission from samfundet.models.model_choices import EventTicketType, EventAgeRestriction, RecruitmentStatusChoices, RecruitmentPriorityChoices + """ This module contains fixtures available in pytests. These do not need to be imported. diff --git a/backend/samfundet/homepage/homepage.py b/backend/samfundet/homepage/homepage.py index 32ecc5fe5..535d4c485 100644 --- a/backend/samfundet/homepage/homepage.py +++ b/backend/samfundet/homepage/homepage.py @@ -62,7 +62,7 @@ def generate() -> dict[str, Any]: # Splash events # TODO we should make a datamodel for this try: - splash_events = list(upcoming_events[0:min(3, len(upcoming_events))]) + splash_events = list(upcoming_events[0 : min(3, len(upcoming_events))]) splash = EventSerializer(splash_events, many=True).data except IndexError: splash = [] @@ -70,11 +70,13 @@ def generate() -> dict[str, Any]: # Upcoming events try: - elements.append(carousel( - title_nb='Hva skjer?', - title_en="What's happening?", - events=list(upcoming_events[:10]), - )) + elements.append( + carousel( + title_nb='Hva skjer?', + title_en="What's happening?", + events=list(upcoming_events[:10]), + ) + ) except IndexError: pass @@ -89,11 +91,13 @@ def generate() -> dict[str, Any]: # Concerts try: - elements.append(carousel( - title_nb='Konserter', - title_en='Concerts', - events=list(upcoming_events.filter(category=EventCategory.CONCERT)[:10]), - )) + elements.append( + carousel( + title_nb='Konserter', + title_en='Concerts', + events=list(upcoming_events.filter(category=EventCategory.CONCERT)[:10]), + ) + ) except IndexError: pass @@ -108,11 +112,13 @@ def generate() -> dict[str, Any]: # Debates try: - elements.append(carousel( - title_nb='Debatter', - title_en='Debates', - events=list(upcoming_events.filter(category=EventCategory.DEBATE)[:10]), - )) + elements.append( + carousel( + title_nb='Debatter', + title_en='Debates', + events=list(upcoming_events.filter(category=EventCategory.DEBATE)[:10]), + ) + ) except IndexError: pass diff --git a/backend/samfundet/models/general.py b/backend/samfundet/models/general.py index ea98a162c..b80d546a0 100644 --- a/backend/samfundet/models/general.py +++ b/backend/samfundet/models/general.py @@ -33,7 +33,6 @@ class Notification(AbstractNotification): - class Meta(AbstractNotification.Meta): abstract = False diff --git a/backend/samfundet/models/tests/test_recruitment.py b/backend/samfundet/models/tests/test_recruitment.py index e2822e8d0..ca75b3164 100644 --- a/backend/samfundet/models/tests/test_recruitment.py +++ b/backend/samfundet/models/tests/test_recruitment.py @@ -44,7 +44,6 @@ def _create_recruitment_with_dt(*, overrides: dict[str, timezone.datetime]) -> R class TestRecruitmentClean: - def test_all_datetimes_is_in_the_future(self, fixture_org): error_msg = 'All times should be in the future' past = timezone.now() - timezone.timedelta(days=2) @@ -73,7 +72,6 @@ def test_reprioritization_deadline_for_applicant_before_reprioritization_deadlin class TestRecruitmentAdmission: - def test_check_withdraw_sets_unwanted(self, fixture_recruitment_admission: RecruitmentAdmission): assert fixture_recruitment_admission.recruiter_status == RecruitmentStatusChoices.NOT_SET assert fixture_recruitment_admission.recruiter_priority == RecruitmentPriorityChoices.NOT_SET diff --git a/backend/samfundet/models/tests/test_reservation.py b/backend/samfundet/models/tests/test_reservation.py index 3844cd26e..7543de4ce 100644 --- a/backend/samfundet/models/tests/test_reservation.py +++ b/backend/samfundet/models/tests/test_reservation.py @@ -6,7 +6,6 @@ class TestReservation: - def test_check_fetches_times( self, fixture_venue: Venue, diff --git a/backend/samfundet/models/utils/fields.py b/backend/samfundet/models/utils/fields.py index 38bd22201..aed8075bf 100644 --- a/backend/samfundet/models/utils/fields.py +++ b/backend/samfundet/models/utils/fields.py @@ -9,13 +9,11 @@ class LowerCaseField(models.CharField): - def to_python(self, value: str) -> str: return super().to_python(value.lower()) class PhoneNumberField(models.CharField): - def __init__(self, *args: Any, **kwargs: Any) -> None: kwargs['max_length'] = 15 self.validators = [ diff --git a/backend/samfundet/serializers.py b/backend/samfundet/serializers.py index 5dfbe9e61..fbb10cac2 100644 --- a/backend/samfundet/serializers.py +++ b/backend/samfundet/serializers.py @@ -55,7 +55,6 @@ class TagSerializer(CustomBaseSerializer): - class Meta: model = Tag fields = '__all__' @@ -99,14 +98,12 @@ def get_url(self, image: Image) -> str: class EventCustomTicketSerializer(CustomBaseSerializer): - class Meta: model = EventCustomTicket fields = '__all__' class BilligPriceGroupSerializer(CustomBaseSerializer): - class Meta: model = BilligPriceGroup fields = ['id', 'name', 'can_be_put_on_card', 'membership_needed', 'netsale', 'price'] @@ -167,7 +164,6 @@ def to_representation(self, events: list[Event] | QuerySet[Event]) -> list[str]: class EventSerializer(CustomBaseSerializer): - class Meta: model = Event list_serializer_class = EventListSerializer @@ -199,21 +195,18 @@ def create(self, validated_data: dict) -> Event: class EventGroupSerializer(CustomBaseSerializer): - class Meta: model = EventGroup fields = '__all__' class VenueSerializer(CustomBaseSerializer): - class Meta: model = Venue fields = '__all__' class ClosedPeriodSerializer(CustomBaseSerializer): - class Meta: model = ClosedPeriod fields = '__all__' @@ -313,28 +306,24 @@ def validate(self, attrs: dict) -> dict: class GroupSerializer(serializers.ModelSerializer): - class Meta: model = Group fields = '__all__' class ProfileSerializer(serializers.ModelSerializer): - class Meta: model = Profile fields = ['id', 'nickname'] class UserPreferenceSerializer(serializers.ModelSerializer): - class Meta: model = UserPreference fields = '__all__' class CampusSerializer(serializers.ModelSerializer): - class Meta: model = Campus fields = '__all__' @@ -384,14 +373,12 @@ def get_user_preference(self, user: User) -> dict: # GANGS ### class OrganizationSerializer(CustomBaseSerializer): - class Meta: model = Organization fields = '__all__' class GangSerializer(CustomBaseSerializer): - class Meta: model = Gang fields = '__all__' @@ -406,14 +393,12 @@ class Meta: class InformationPageSerializer(CustomBaseSerializer): - class Meta: model = InformationPage fields = '__all__' class BlogPostSerializer(CustomBaseSerializer): - class Meta: model = BlogPost fields = '__all__' @@ -448,21 +433,18 @@ def create(self, validated_data: dict) -> Event: class TextItemSerializer(serializers.ModelSerializer): - class Meta: model = TextItem fields = '__all__' class InfoboxSerializer(CustomBaseSerializer): - class Meta: model = Infobox fields = '__all__' class KeyValueSerializer(serializers.ModelSerializer): - class Meta: model = KeyValue fields = '__all__' @@ -474,14 +456,12 @@ class Meta: class FoodPreferenceSerializer(CustomBaseSerializer): - class Meta: model = FoodPreference fields = '__all__' class FoodCategorySerializer(CustomBaseSerializer): - class Meta: model = FoodCategory fields = '__all__' @@ -504,21 +484,18 @@ class Meta: class TableSerializer(CustomBaseSerializer): - class Meta: model = Table fields = '__all__' class ReservationSerializer(CustomBaseSerializer): - class Meta: model = Reservation fields = '__all__' class ReservationCheckSerializer(serializers.ModelSerializer): - class Meta: model = Reservation fields = ['guest_count', 'occasion', 'reservation_date'] @@ -539,7 +516,6 @@ class Meta: class RecruitmentSerializer(CustomBaseSerializer): - class Meta: model = Recruitment fields = '__all__' @@ -565,7 +541,6 @@ def get_recruitment_admission_ids(self, obj: User) -> list[int]: class InterviewerSerializer(CustomBaseSerializer): - class Meta: model = User fields = [ @@ -613,6 +588,7 @@ def update(self, instance: RecruitmentPosition, validated_data: dict) -> Recruit self._update_interviewers(recruitment_position=updated_instance, interviewer_objects=interviewer_objects) return updated_instance + class ApplicantInterviewSerializer(serializers.ModelSerializer): class Meta: model = Interview @@ -676,7 +652,6 @@ def create(self, validated_data: dict) -> RecruitmentAdmission: class OccupiedtimeslotSerializer(serializers.ModelSerializer): - class Meta: model = Occupiedtimeslot fields = '__all__' @@ -691,14 +666,12 @@ class Meta: class InterviewRoomSerializer(CustomBaseSerializer): - class Meta: model = InterviewRoom fields = '__all__' class InterviewSerializer(CustomBaseSerializer): - class Meta: model = Interview fields = '__all__' diff --git a/backend/samfundet/tests/test_signals.py b/backend/samfundet/tests/test_signals.py index 5c6721304..c3cacf56b 100644 --- a/backend/samfundet/tests/test_signals.py +++ b/backend/samfundet/tests/test_signals.py @@ -8,7 +8,6 @@ class TestUserSignals: - def test_create_user_preference(self): ### Arrange ### user = User.objects.create_user( @@ -45,7 +44,6 @@ def test_create_profile(self): class TestEditorPermissions: - def test_update_editor_permissions_add( self, fixture_event: Event, diff --git a/backend/samfundet/tests/test_views.py b/backend/samfundet/tests/test_views.py index bfccc42cb..94f93838e 100644 --- a/backend/samfundet/tests/test_views.py +++ b/backend/samfundet/tests/test_views.py @@ -114,7 +114,6 @@ def test_get_groups(fixture_rest_client: APIClient, fixture_user: User): class TestInformationPagesView: - def test_get_informationpage( self, fixture_rest_client: APIClient, @@ -286,7 +285,6 @@ def test_updated_and_created_by(self, fixture_rest_client: APIClient, fixture_us class TestBlogPostView: - def test_get_blogpost( self, fixture_rest_client: APIClient, @@ -382,7 +380,6 @@ def test_put_blogpost( class TestKeyValueView: - def test_anyone_can_retrieve_keyvalues(self, fixture_rest_client: APIClient): ### Arrange ### keyvalue = KeyValue.objects.create(key='FOO', value='bar') @@ -432,7 +429,6 @@ def test_crud_not_possible(self, fixture_rest_client: APIClient, fixture_superus class TestTextItemView: - def test_anyone_can_retrieve_textitems(self, fixture_rest_client: APIClient, fixture_text_item: TextItem): ### Arrange ### url = reverse(routes.samfundet__text_item_detail, kwargs={'pk': fixture_text_item.key}) @@ -478,7 +474,6 @@ def test_crud_not_possible(self, fixture_rest_client: APIClient, fixture_superus class TestAssignGroupView: - def test_assign_group( self, fixture_rest_client: APIClient, @@ -683,4 +678,4 @@ def test_recruitment_admission_for_applicant( # Assert the returned data based on the logic in the view assert len(response.data) == 1 assert response.data[0]['admission_text'] == fixture_recruitment_admission.admission_text - assert response.data[0]['recruitment_position'] == fixture_recruitment_admission.recruitment_position.id + assert response.data[0]['recruitment_position']['id'] == fixture_recruitment_admission.recruitment_position.id diff --git a/backend/samfundet/utils.py b/backend/samfundet/utils.py index 0d57cdfc0..a92c778fe 100644 --- a/backend/samfundet/utils.py +++ b/backend/samfundet/utils.py @@ -15,9 +15,14 @@ def event_query(*, query: QueryDict, events: QuerySet[Event] = None) -> QuerySet search = query.get('search', None) if search: events = events.filter( - Q(title_nb__icontains=search) | Q(title_en__icontains=search) | Q(description_long_nb__icontains=search) | - Q(description_long_en__icontains=search) | Q(description_short_en=search) | Q(description_short_nb=search) | Q(location__icontains=search) | - Q(event_group__name=search) + Q(title_nb__icontains=search) + | Q(title_en__icontains=search) + | Q(description_long_nb__icontains=search) + | Q(description_long_en__icontains=search) + | Q(description_short_en=search) + | Q(description_short_nb=search) + | Q(location__icontains=search) + | Q(event_group__name=search) ) event_group = query.get('event_group', None) if event_group: diff --git a/backend/samfundet/views.py b/backend/samfundet/views.py index 8248089c9..a4184e24a 100644 --- a/backend/samfundet/views.py +++ b/backend/samfundet/views.py @@ -145,14 +145,14 @@ class KeyValueView(ReadOnlyModelViewSet): # Images class ImageView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = ImageSerializer queryset = Image.objects.all().order_by('-pk') # Image tags class TagView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = TagSerializer queryset = Tag.objects.all() @@ -163,7 +163,7 @@ class TagView(ModelViewSet): class EventView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = EventSerializer queryset = Event.objects.all() @@ -196,7 +196,7 @@ def get(self, request: Request) -> Response: class EventGroupView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = EventGroupSerializer queryset = EventGroup.objects.all() @@ -207,14 +207,14 @@ class EventGroupView(ModelViewSet): class VenueView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = VenueSerializer queryset = Venue.objects.all() lookup_field = 'slug' class ClosedPeriodView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = ClosedPeriodSerializer queryset = ClosedPeriod.objects.all() @@ -231,49 +231,49 @@ def get_queryset(self) -> QuerySet: class BookingView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = BookingSerializer queryset = Booking.objects.all() class SaksdokumentView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = SaksdokumentSerializer queryset = Saksdokument.objects.all() class OrganizationView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = OrganizationSerializer queryset = Organization.objects.all() class GangView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = GangSerializer queryset = Gang.objects.all() class GangTypeView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = GangTypeSerializer queryset = GangType.objects.all() class InformationPageView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = InformationPageSerializer queryset = InformationPage.objects.all() class InfoboxView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = InfoboxSerializer queryset = Infobox.objects.all() class BlogPostView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = BlogPostSerializer queryset = BlogPost.objects.all() @@ -284,31 +284,31 @@ class BlogPostView(ModelViewSet): class MenuView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = MenuSerializer queryset = Menu.objects.all() class MenuItemView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = MenuItemSerializer queryset = MenuItem.objects.all() class FoodCategoryView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = FoodCategorySerializer queryset = FoodCategory.objects.all() class FoodPreferenceView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = FoodPreferenceSerializer queryset = FoodPreference.objects.all() class TableView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = TableSerializer queryset = Table.objects.all() @@ -412,7 +412,7 @@ def get(self, request: Request) -> Response: class AllUsersView(ListAPIView): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = UserSerializer queryset = User.objects.all() @@ -428,7 +428,7 @@ def post(self, request: Request) -> Response: class AllGroupsView(ListAPIView): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = GroupSerializer queryset = Group.objects.all() @@ -449,7 +449,7 @@ class UserPreferenceView(ModelViewSet): class ProfileView(ModelViewSet): - permission_classes = (DjangoModelPermissionsOrAnonReadOnly, ) + permission_classes = (DjangoModelPermissionsOrAnonReadOnly,) serializer_class = ProfileSerializer queryset = Profile.objects.all()