Coverage for core/apps.py: 87%
36 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« 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
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
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')
17# Use our custom destructor to ignore certain attributes when calculating field migrations
18models.Field.deconstruct = custom_deconstruct
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
27class CoreConfig(AppConfig):
28 name = "core"
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
41 from . import data_backends, events, search # noqa: F401
43 # Register models
44 register_models(*self.get_models())
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()
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