Coverage for core/apps.py: 87%

36 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from django.apps import AppConfig 

2from django.conf import settings 

3from django.core.cache import cache 

4from django.db import models 

5from django.db.migrations.operations import AlterModelOptions 

6from django.utils.translation import gettext as _ 

7from PIL import Image 

8 

9from core.events import * 

10from netbox.events import EVENT_TYPE_KIND_DANGER, EVENT_TYPE_KIND_SUCCESS, EVENT_TYPE_KIND_WARNING, EventType 

11from utilities.migration import custom_deconstruct 

12 

13# Ignore verbose_name & verbose_name_plural Meta options when calculating model migrations 

14AlterModelOptions.ALTER_OPTION_KEYS.remove('verbose_name') 

15AlterModelOptions.ALTER_OPTION_KEYS.remove('verbose_name_plural') 

16 

17# Use our custom destructor to ignore certain attributes when calculating field migrations 

18models.Field.deconstruct = custom_deconstruct 

19 

20# Cap the maximum size of an image Pillow will decode, to mitigate decompression-bomb DoS attacks. Pillow raises a 

21# DecompressionBombError when an image's declared dimensions exceed 2x this value, before allocating pixel buffers. 

22# Django's & DRF's ImageField already convert that exception into a validation error, so no additional handling is 

23# required; this single assignment covers all image upload paths (UI forms, REST API, and direct model saves). 

24Image.MAX_IMAGE_PIXELS = 25_000_000 

25 

26 

27class CoreConfig(AppConfig): 

28 name = "core" 

29 

30 def ready(self): 

31 from core.api import schema # noqa: F401 

32 from core.checks import ( # noqa: F401 

33 check_duplicate_indexes, 

34 check_postgresql_version, 

35 check_redis_version, 

36 ) 

37 from netbox import context_managers # noqa: F401 

38 from netbox.models.features import register_models 

39 from netbox.search import signals as search_signals # noqa: F401 

40 

41 from . import data_backends, events, search # noqa: F401 

42 

43 # Register models 

44 register_models(*self.get_models()) 

45 

46 # Register core events 

47 EventType(OBJECT_CREATED, _('Object created')).register() 

48 EventType(OBJECT_UPDATED, _('Object updated')).register() 

49 EventType(OBJECT_DELETED, _('Object deleted'), destructive=True).register() 

50 EventType(JOB_STARTED, _('Job started')).register() 

51 EventType(JOB_COMPLETED, _('Job completed'), kind=EVENT_TYPE_KIND_SUCCESS).register() 

52 EventType(JOB_FAILED, _('Job failed'), kind=EVENT_TYPE_KIND_WARNING).register() 

53 EventType(JOB_ERRORED, _('Job errored'), kind=EVENT_TYPE_KIND_DANGER).register() 

54 

55 # Clear Redis cache on startup in development mode 

56 if settings.DEBUG: 56 ↛ 57line 56 didn't jump to line 57 because the condition on line 56 was never true

57 try: 

58 cache.clear() 

59 except Exception: 

60 pass