def test_m2m_to_abstract_model(self): class AbstractModel(models.Model): class Meta: abstract = True class Model(models.Model): rel_string_m2m = models.ManyToManyField('AbstractModel') rel_class_m2m = models.ManyToManyField(AbstractModel) fields = [ Model._meta.get_field('rel_string_m2m'), Model._meta.get_field('rel_class_m2m'), ] expected_error = Error( "Field defines a relation with model 'AbstractModel', " "which is either not installed, or is abstract.", id='fields.E300', ) for field in fields: expected_error.obj = field errors = field.check(from_model=Model) self.assertEqual(errors, [expected_error])
def test_referencing_to_swapped_model(self): class Replacement(models.Model): pass class SwappedModel(models.Model): class Meta: swappable = 'TEST_SWAPPED_MODEL' class Model(models.Model): explicit_fk = models.ForeignKey(SwappedModel, related_name='explicit_fk') implicit_fk = models.ForeignKey('invalid_models_tests.SwappedModel', related_name='implicit_fk') explicit_m2m = models.ManyToManyField(SwappedModel, related_name='explicit_m2m') implicit_m2m = models.ManyToManyField( 'invalid_models_tests.SwappedModel', related_name='implicit_m2m') fields = [ Model._meta.get_field('explicit_fk'), Model._meta.get_field('implicit_fk'), Model._meta.get_field('explicit_m2m'), Model._meta.get_field('implicit_m2m'), ] expected_error = Error( ("Field defines a relation with the model " "'invalid_models_tests.SwappedModel', which has been swapped out."), hint="Update the relation to point at 'settings.TEST_SWAPPED_MODEL'.", id='fields.E301', ) for field in fields: expected_error.obj = field errors = field.check(from_model=Model) self.assertEqual(errors, [expected_error])
def test_printing_field_error(self): field = SimpleModel._meta.get_field('field') e = Error("Error", obj=field) expected = "check_framework.SimpleModel.field: Error" self.assertEqual(force_text(e), expected)
def create_error_07_setting_does_not_exist(setting: str) -> Error: return Error(f"{setting} is not declared in settings", id="sheetstorm.E010")
def create_error_05_module_does_not_have_attribute(module: str, attribute: str) -> Error: return Error(f"Attribute {attribute} from module {module} doesn't exist", id="sheetstorm.E007")
def create_error_03_site_id_value_must_be_integer() -> Error: return Error("SITE_ID value must be an integer", id="sheetstorm.E004")
def create_error_01_valid_email_domain_list_is_not_a_list() -> Error: return Error("The value of VALID_EMAIL_DOMAIN_LIST setting is not a list", id="sheetstorm.E001")
def test_no_domain(self): self.assertEqual(domains_available_check(None), [Error(DOMAIN_ERROR_MSG)])
def best_practice(app_configs, **kwargs): """ Test for configuration recommendations. These are best practices, they avoid hard to find bugs and unexpected behaviour. """ if app_configs is None: app_configs = apps.get_app_configs() # Take the app_configs and turn them into *old style* application names. # This is what we expect in the SHARED_APPS and TENANT_APPS settings. INSTALLED_APPS = [ config.name for config in app_configs ] if not hasattr(settings, 'TENANT_APPS'): return [Critical('TENANT_APPS setting not set')] if not hasattr(settings, 'TENANT_MODEL'): return [Critical('TENANT_MODEL setting not set')] if not hasattr(settings, 'SHARED_APPS'): return [Critical('SHARED_APPS setting not set')] if 'tenant_schemas.routers.TenantSyncRouter' not in settings.DATABASE_ROUTERS: return [ Critical("DATABASE_ROUTERS setting must contain " "'tenant_schemas.routers.TenantSyncRouter'.") ] errors = [] django_index = next(i for i, s in enumerate(INSTALLED_APPS) if s.startswith('django.')) if INSTALLED_APPS.index('tenant_schemas') > django_index: errors.append( Warning("You should put 'tenant_schemas' before any django " "core applications in INSTALLED_APPS.", obj="django.conf.settings", hint="This is necessary to overwrite built-in django " "management commands with their schema-aware " "implementations.", id="tenant_schemas.W001")) if not settings.TENANT_APPS: errors.append( Error("TENANT_APPS is empty.", hint="Maybe you don't need this app?", id="tenant_schemas.E001")) if hasattr(settings, 'PG_EXTRA_SEARCH_PATHS'): if get_public_schema_name() in settings.PG_EXTRA_SEARCH_PATHS: errors.append(Critical( "%s can not be included on PG_EXTRA_SEARCH_PATHS." % get_public_schema_name())) # make sure no tenant schema is in settings.PG_EXTRA_SEARCH_PATHS invalid_schemas = set(settings.PG_EXTRA_SEARCH_PATHS).intersection( get_tenant_model().objects.all().values_list('schema_name', flat=True)) if invalid_schemas: errors.append(Critical( "Do not include tenant schemas (%s) on PG_EXTRA_SEARCH_PATHS." % ", ".join(sorted(invalid_schemas)))) if not settings.SHARED_APPS: errors.append( Warning("SHARED_APPS is empty.", id="tenant_schemas.W002")) if not set(settings.TENANT_APPS).issubset(INSTALLED_APPS): delta = set(settings.TENANT_APPS).difference(INSTALLED_APPS) errors.append( Error("You have TENANT_APPS that are not in INSTALLED_APPS", hint=[a for a in settings.TENANT_APPS if a in delta], id="tenant_schemas.E002")) if not set(settings.SHARED_APPS).issubset(INSTALLED_APPS): delta = set(settings.SHARED_APPS).difference(INSTALLED_APPS) if 'raven.contrib.django.raven_compat' in delta: delta.remove('raven.contrib.django.raven_compat') if delta: errors.append( Error("You have SHARED_APPS that are not in INSTALLED_APPS", hint=[a for a in settings.SHARED_APPS if a in delta], id="tenant_schemas.E003")) if not isinstance(default_storage, TenantStorageMixin): errors.append(Warning( "Your default storage engine is not tenant aware.", hint="Set settings.DEFAULT_FILE_STORAGE to " "'tenant_schemas.storage.TenantFileSystemStorage'", id="tenant_schemas.W003" )) return errors
def test_M2M_long_column_name(self): """ #13711 -- Model check for long M2M column names when database has column name length limits. """ allowed_len, db_alias = get_max_column_name_length() # A model with very long name which will be used to set relations to. class VeryLongModelNamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz( models.Model): title = models.CharField(max_length=11) # Main model for which checks will be performed. class ModelWithLongField(models.Model): m2m_field = models.ManyToManyField( VeryLongModelNamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, related_name="rn1") m2m_field2 = models.ManyToManyField( VeryLongModelNamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, related_name="rn2", through='m2msimple') m2m_field3 = models.ManyToManyField( VeryLongModelNamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, related_name="rn3", through='m2mcomplex') fk = models.ForeignKey( VeryLongModelNamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, models.CASCADE, related_name="rn4", ) # Models used for setting `through` in M2M field. class m2msimple(models.Model): id2 = models.ForeignKey(ModelWithLongField, models.CASCADE) class m2mcomplex(models.Model): id2 = models.ForeignKey(ModelWithLongField, models.CASCADE) long_field_name = 'a' * (self.max_column_name_length + 1) models.ForeignKey( VeryLongModelNamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, models.CASCADE, ).contribute_to_class(m2msimple, long_field_name) models.ForeignKey( VeryLongModelNamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz, models.CASCADE, db_column=long_field_name).contribute_to_class( m2mcomplex, long_field_name) errors = ModelWithLongField.check() # First error because of M2M field set on the model with long name. m2m_long_name = "verylongmodelnamezzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz_id" if self.max_column_name_length > len(m2m_long_name): # Some databases support names longer than the test name. expected = [] else: expected = [ Error( 'Autogenerated column name too long for M2M field "%s". ' 'Maximum length is "%s" for database "%s".' % (m2m_long_name, self.max_column_name_length, self.column_limit_db_alias), hint=("Use 'through' to create a separate model for " "M2M and then set column_name using 'db_column'."), obj=ModelWithLongField, id='models.E019', ) ] # Second error because the FK specified in the `through` model # `m2msimple` has auto-generated name longer than allowed. # There will be no check errors in the other M2M because it # specifies db_column for the FK in `through` model even if the actual # name is longer than the limits of the database. expected.append( Error( 'Autogenerated column name too long for M2M field "%s_id". ' 'Maximum length is "%s" for database "%s".' % (long_field_name, self.max_column_name_length, self.column_limit_db_alias), hint=("Use 'through' to create a separate model for " "M2M and then set column_name using 'db_column'."), obj=ModelWithLongField, id='models.E019', )) self.assertEqual(errors, expected)
def check_all_models(app_configs=None, **kwargs): #print('【django.core.checks.model_checks.check_all_models】app_configs:', app_configs) #print('【django.core.checks.model_checks.check_all_models】kwargs:', kwargs) db_table_models = defaultdict(list) indexes = defaultdict(list) constraints = defaultdict(list) errors = [] if app_configs is None: models = apps.get_models() else: models = chain.from_iterable(app_config.get_models() for app_config in app_configs) # 下面这几行打印 models 中的映射类 ''' print() print(f'【django.core.checks.model_checks.check_all_models】models: ({len(models)})') for model in models: print('\t', model) print() ''' # 变量 models 是一个列表,列表里是各个应用中定义的映射类: # <class 'django.contrib.admin.models.LogEntry'> # <class 'django.contrib.auth.models.Permission'> # 重点分析 # <class 'django.contrib.auth.models.Group'> # 重点分析 # <class 'django.contrib.auth.models.User'> # <class 'django.contrib.contenttypes.models.ContentType'> # <class 'django.contrib.sessions.models.Session'> # <class 'authentication.models.User'> # 重点分析 for model in models: if model._meta.managed and not model._meta.proxy: #print(f'\t {model._meta.db_table} {model._meta.label}', # [i for i in dir(model) if not i.startswith('__') and # not inspect.ismethod(getattr(model, i))] #) # model._meta.db_table 是数据表的名字的字符串,通常是用下划线连接应用名和映射类名的全小写 # model._meta.label 是指向映射类的别名的字符串,通常是用点号连接应用名和映射类名 db_table_models[model._meta.db_table].append(model._meta.label) # 此处检查映射类的 check 属性是方法,如果不是就把异常对象放到 errors 列表里 if not inspect.ismethod(model.check): errors.append( Error( "The '%s.check()' class method is currently overridden by %r." % (model.__name__, model.check), obj=model, id='models.E020')) # 此处调用映射类的 check 方法 else: # model 是映射类,所有映射类都继承自 django.db.models.base.Model 类 # model.check 就是在后者中定义的 errors.extend(model.check(**kwargs)) for model_index in model._meta.indexes: indexes[model_index.name].append(model._meta.label) for model_constraint in model._meta.constraints: constraints[model_constraint.name].append(model._meta.label) if settings.DATABASE_ROUTERS: error_class, error_id = Warning, 'models.W035' error_hint = ( 'You have configured settings.DATABASE_ROUTERS. Verify that %s ' 'are correctly routed to separate databases.') else: error_class, error_id = Error, 'models.E028' error_hint = None for db_table, model_labels in db_table_models.items(): if len(model_labels) != 1: model_labels_str = ', '.join(model_labels) errors.append( error_class( "db_table '%s' is used by multiple models: %s." % (db_table, model_labels_str), obj=db_table, hint=(error_hint % model_labels_str) if error_hint else None, id=error_id, )) for index_name, model_labels in indexes.items(): if len(model_labels) > 1: model_labels = set(model_labels) errors.append( Error( "index name '%s' is not unique %s %s." % ( index_name, 'for model' if len(model_labels) == 1 else 'amongst models:', ', '.join(sorted(model_labels)), ), id='models.E029' if len(model_labels) == 1 else 'models.E030', ), ) for constraint_name, model_labels in constraints.items(): if len(model_labels) > 1: model_labels = set(model_labels) errors.append( Error( "constraint name '%s' is not unique %s %s." % ( constraint_name, 'for model' if len(model_labels) == 1 else 'amongst models:', ', '.join(sorted(model_labels)), ), id='models.E031' if len(model_labels) == 1 else 'models.E032', ), ) print(f'【django.core.checks.model_checks】errors: {len(errors)}') for e in errors: print('\t', e) return errors
def test_lazy_reference_checks(self, apps): class DummyModel(models.Model): author = models.ForeignKey('Author', models.CASCADE) class Meta: app_label = 'invalid_models_tests' class DummyClass: def __call__(self, **kwargs): pass def dummy_method(self): pass def dummy_function(*args, **kwargs): pass apps.lazy_model_operation(dummy_function, ('auth', 'imaginarymodel')) apps.lazy_model_operation(dummy_function, ('fanciful_app', 'imaginarymodel')) post_init.connect(dummy_function, sender='missing-app.Model', apps=apps) post_init.connect(DummyClass(), sender='missing-app.Model', apps=apps) post_init.connect(DummyClass().dummy_method, sender='missing-app.Model', apps=apps) self.assertEqual(_check_lazy_references(apps), [ Error( "%r contains a lazy reference to auth.imaginarymodel, " "but app 'auth' doesn't provide model 'imaginarymodel'." % dummy_function, obj=dummy_function, id='models.E022', ), Error( "%r contains a lazy reference to fanciful_app.imaginarymodel, " "but app 'fanciful_app' isn't installed." % dummy_function, obj=dummy_function, id='models.E022', ), Error( "An instance of class 'DummyClass' was connected to " "the 'post_init' signal with a lazy reference to the sender " "'missing-app.model', but app 'missing-app' isn't installed.", hint=None, obj='invalid_models_tests.test_models', id='signals.E001', ), Error( "Bound method 'DummyClass.dummy_method' was connected to the " "'post_init' signal with a lazy reference to the sender " "'missing-app.model', but app 'missing-app' isn't installed.", hint=None, obj='invalid_models_tests.test_models', id='signals.E001', ), Error( "The field invalid_models_tests.DummyModel.author was declared " "with a lazy reference to 'invalid_models_tests.author', but app " "'invalid_models_tests' isn't installed.", hint=None, obj=DummyModel.author.field, id='fields.E307', ), Error( "The function 'dummy_function' was connected to the 'post_init' " "signal with a lazy reference to the sender " "'missing-app.model', but app 'missing-app' isn't installed.", hint=None, obj='invalid_models_tests.test_models', id='signals.E001', ), ])
from django.conf import settings from django.core.checks import register, Error, Tags, Warning from django.core.exceptions import ValidationError from django.core.validators import URLValidator E001 = Error( "CACHEOPS_DEFAULTS['timeout'] value cannot be 0. To disable caching set CACHEOPS_ENABLED=False.", id="nautobot.core.E001", ) E002 = Error( "'nautobot.core.authentication.ObjectPermissionBackend' must be included in AUTHENTICATION_BACKENDS", id="nautobot.core.E002", ) E003 = Error( "RELEASE_CHECK_TIMEOUT must be at least 3600 seconds (1 hour)", id="nautobot.core.E003", ) E004 = Error( "RELEASE_CHECK_URL must be a valid API URL. Example: https://api.github.com/repos/nautobot/nautobot", id="nautobot.core.E004", ) W005 = Warning( "STORAGE_CONFIG has been set but STORAGE_BACKEND is not defined. STORAGE_CONFIG will be ignored.", id="nautobot.core.W005", )
import logging import pwd import os from django.core.checks import register, Error, Warning from django.conf import settings from django import apps E001 = Error('Raven config is not set.', id='preflight_reporting.E001') E002 = Error('Raven config is not complete.', id='preflight_reporting.E002') E003 = Error('Raven is disabled.', id='preflight_reporting.E003') E004 = Error('Raven could not send test message.', id='preflight_reporting.E004') E005 = Error('Raven is in INSTALLED_APPS, but the package is not installed.', id='preflight_reporting.E005') W001 = Warning('Raven is not installed.', id='preflight_reporting.W001') # noinspection PyUnusedLocal @register('preflight', deploy=True) def check_reporting(app_configs, **kwargs): errors = [] current_user = pwd.getpwuid(os.getuid()).pw_name # Get all configs if we don't get a specific set
def best_practice(app_configs, **kwargs): """ Test for configuration recommendations. These are best practices, they avoid hard to find bugs and unexpected behaviour. """ # Take the app_configs and turn them into *old style* application names. # This is what we expect in the SHARED_APPS and TENANT_APPS settings. INSTALLED_APPS = [config.name for config in app_configs] if not hasattr(settings, 'TENANT_APPS'): return [Critical('TENANT_APPS setting not set')] if not hasattr(settings, 'TENANT_MODEL'): return [Critical('TENANT_MODEL setting not set')] if not hasattr(settings, 'SHARED_APPS'): return [Critical('SHARED_APPS setting not set')] if 'tenant_schemas.routers.TenantSyncRouter' not in settings.DATABASE_ROUTERS: return [ Critical("DATABASE_ROUTERS setting must contain " "'tenant_schemas.routers.TenantSyncRouter'.") ] errors = [] if INSTALLED_APPS[0] != 'tenant_schemas': errors.append( Warning("You should put 'tenant_schemas' first in INSTALLED_APPS.", obj="django.conf.settings", hint="This is necessary to overwrite built-in django " "management commands with their schema-aware " "implementations.")) if not settings.TENANT_APPS: errors.append( Error("TENANT_APPS is empty.", hint="Maybe you don't need this app?")) if hasattr(settings, 'PG_EXTRA_SEARCH_PATHS'): if get_public_schema_name() in settings.PG_EXTRA_SEARCH_PATHS: errors.append( Critical("%s can not be included on PG_EXTRA_SEARCH_PATHS." % get_public_schema_name())) # make sure no tenant schema is in settings.PG_EXTRA_SEARCH_PATHS invalid_schemas = set(settings.PG_EXTRA_SEARCH_PATHS).intersection( get_tenant_model().objects.all().values_list('schema_name', flat=True)) if invalid_schemas: errors.append( Critical( "Do not include tenant schemas (%s) on PG_EXTRA_SEARCH_PATHS." % ", ".join(sorted(invalid_schemas)))) if not settings.SHARED_APPS: errors.append(Warning("SHARED_APPS is empty.")) if not set(settings.TENANT_APPS).issubset(INSTALLED_APPS): delta = set(settings.TENANT_APPS).difference(INSTALLED_APPS) errors.append( Error("You have TENANT_APPS that are not in INSTALLED_APPS", hint=[a for a in settings.TENANT_APPS if a in delta])) if not set(settings.SHARED_APPS).issubset(INSTALLED_APPS): delta = set(settings.SHARED_APPS).difference(INSTALLED_APPS) errors.append( Error("You have SHARED_APPS that are not in INSTALLED_APPS", hint=[a for a in settings.SHARED_APPS if a in delta])) return errors
def snapshots_check(app_configs, **kwargs): """自动检查过去snapshots的净值。必须确保代码修改不会不小心造成账户净值出错。""" from stocks.models import Account, Snapshot errors = [] try: public_account = Account.objects.get(id=4) snapshots = public_account.snapshots.all()[:13] expected_net_assets = [ Decimal('402409.11'), Decimal('418005.48'), Decimal('448114.82'), Decimal('460585.62'), Decimal('532143.95'), Decimal('513612.32'), Decimal('545341.27'), Decimal('568601.91'), Decimal('591513.78'), Decimal('581557.38'), Decimal('600266.95'), Decimal('710184.95'), Decimal('760989.55') ] expected_increases = [ Decimal('0.0000'), Decimal('0.0388'), Decimal('0.0720'), Decimal('0.0278'), Decimal('0.1554'), Decimal('-0.0348'), Decimal('0.0618'), Decimal('0.0427'), Decimal('0.0403'), Decimal('-0.0168'), Decimal('0.0322'), Decimal('0.1831'), Decimal('0.0715') ] for i, snapshot in enumerate(snapshots): if i + 1 != snapshot.serial_number: errors.append( Error( 'serial number error', hint='{} != {}'.format(snapshot.serial_number, i + 1), obj=Snapshot, id='stocks.E001', )) if (snapshot.serial_number - 1) % 12 == 0: if not snapshot.is_annual: errors.append( Error( 'is_annual', hint='is_annual_should be True for snapshot {}'. format(snapshot.serial_number), obj=Snapshot, id='stocks.E002', )) expected_net_asset = expected_net_assets[i] if snapshot.net_asset != expected_net_asset: errors.append( Error( 'Net asset mismatch', hint= 'Net asset should be {} for snapshot #{}. Yet it is {}' .format(expected_net_asset, snapshot.serial_number, snapshot.net_asset), obj=Snapshot, id='stocks.E003', )) expected_increase = expected_increases[i] if snapshot.increase != expected_increase: errors.append( Error( 'Change mismatch', hint='Change should be {} for snapshot #{}. Yet it is {}' .format(expected_increase, snapshot.serial_number, snapshot.increase), obj=Snapshot, id='stocks.E004', )) return errors except (OperationalError, Account.DoesNotExist): return [ ] # skip if database is not created/migrated yet, or account doesn't exit.
def check_comprehensive_theme_settings(app_configs, **kwargs): """ Checks the comprehensive theming theme directory settings. Raises compatibility Errors upon: - COMPREHENSIVE_THEME_DIRS is not a list - theme dir path is not a string - theme dir path is not an absolute path - path specified in COMPREHENSIVE_THEME_DIRS does not exist Returns: List of any Errors. """ if not getattr(settings, "ENABLE_COMPREHENSIVE_THEMING"): # Only perform checks when comprehensive theming is enabled. return [] errors = [] # COMPREHENSIVE_THEME_DIR is no longer supported - support has been removed. if hasattr(settings, "COMPREHENSIVE_THEME_DIR"): theme_dir = settings.COMPREHENSIVE_THEME_DIR errors.append( Error( "COMPREHENSIVE_THEME_DIR setting has been removed in favor of COMPREHENSIVE_THEME_DIRS.", hint= 'Transfer the COMPREHENSIVE_THEME_DIR value to COMPREHENSIVE_THEME_DIRS.', obj=theme_dir, id='openedx.core.djangoapps.theming.E001', )) if hasattr(settings, "COMPREHENSIVE_THEME_DIRS"): theme_dirs = settings.COMPREHENSIVE_THEME_DIRS if not isinstance(theme_dirs, list): errors.append( Error( "COMPREHENSIVE_THEME_DIRS must be a list.", obj=theme_dirs, id='openedx.core.djangoapps.theming.E004', )) if not all([ isinstance(theme_dir, six.string_types) for theme_dir in theme_dirs ]): errors.append( Error( "COMPREHENSIVE_THEME_DIRS must contain only strings.", obj=theme_dirs, id='openedx.core.djangoapps.theming.E005', )) if not all([theme_dir.startswith("/") for theme_dir in theme_dirs]): errors.append( Error( "COMPREHENSIVE_THEME_DIRS must contain only absolute paths to themes dirs.", obj=theme_dirs, id='openedx.core.djangoapps.theming.E006', )) if not all([os.path.isdir(theme_dir) for theme_dir in theme_dirs]): errors.append( Error( "COMPREHENSIVE_THEME_DIRS must contain valid paths.", obj=theme_dirs, id='openedx.core.djangoapps.theming.E007', )) return errors
def add_error(self, title, numeric_id: int, **kwargs): issue_id = 'otree.E' + str(numeric_id).zfill(3) kwargs.setdefault('obj', self.app_config.label) return self.errors.append(Error(title, id=issue_id, **kwargs))
def test_domain_disabled(self): factories.DomainFactory(enabled=False) self.assertEqual(domains_available_check(None), [Error(DOMAIN_ERROR_MSG)])
def check_all_models(app_configs=None, **kwargs): db_table_models = defaultdict(list) indexes = defaultdict(list) constraints = defaultdict(list) errors = [] if app_configs is None: models = apps.get_models() else: models = chain.from_iterable(app_config.get_models() for app_config in app_configs) for model in models: if model._meta.managed and not model._meta.proxy: db_table_models[model._meta.db_table].append(model._meta.label) if not inspect.ismethod(model.check): errors.append( Error( "The '%s.check()' class method is currently overridden by %r." % (model.__name__, model.check), obj=model, id='models.E020')) else: errors.extend(model.check(**kwargs)) for model_index in model._meta.indexes: indexes[model_index.name].append(model._meta.label) for model_constraint in model._meta.constraints: constraints[model_constraint.name].append(model._meta.label) if settings.DATABASE_ROUTERS: error_class, error_id = Warning, 'models.W035' error_hint = ( 'You have configured settings.DATABASE_ROUTERS. Verify that %s ' 'are correctly routed to separate databases.') else: error_class, error_id = Error, 'models.E028' error_hint = None for db_table, model_labels in db_table_models.items(): if len(model_labels) != 1: model_labels_str = ', '.join(model_labels) errors.append( error_class( "db_table '%s' is used by multiple models: %s." % (db_table, model_labels_str), obj=db_table, hint=(error_hint % model_labels_str) if error_hint else None, id=error_id, )) for index_name, model_labels in indexes.items(): if len(model_labels) > 1: model_labels = set(model_labels) errors.append( Error( "index name '%s' is not unique %s %s." % ( index_name, 'for model' if len(model_labels) == 1 else 'amongst models:', ', '.join(sorted(model_labels)), ), id='models.E029' if len(model_labels) == 1 else 'models.E030', ), ) for constraint_name, model_labels in constraints.items(): if len(model_labels) > 1: model_labels = set(model_labels) errors.append( Error( "constraint name '%s' is not unique %s %s." % ( constraint_name, 'for model' if len(model_labels) == 1 else 'amongst models:', ', '.join(sorted(model_labels)), ), id='models.E031' if len(model_labels) == 1 else 'models.E032', ), ) return errors
def create_error_02_invalid_domain_address(domain: str) -> Error: return Error(f"Domain {domain} should be valid url address", hint="Fix domain name.", id="sheetstorm.E002")
def custom_error_system_check(app_configs, **kwargs): return [Error( 'Error', hint=None, id='myerrorcheck.E001', )]
def create_error_04_email_backend_value_must_be_string() -> Error: return Error("EMAIL_BACKEND value must be a string", id="sheetstorm.E005")
def test_printing(self): e = Error("Message", hint="Hint", obj=DummyObj()) expected = "obj: Message\n\tHINT: Hint" self.assertEqual(force_text(e), expected)
def create_error_06_can_not_import_path(path: str) -> Error: return Error(f"Module from path: {path} can not be imported", id="sheetstorm.E008")
def test_printing_no_hint(self): e = Error("Message", hint=None, obj=DummyObj()) expected = "obj: Message" self.assertEqual(force_text(e), expected)
def check_celery(app_configs, **kwargs): errors = [] if settings.CELERY_TASK_ALWAYS_EAGER: errors.append( Error( 'Celery is configured in the eager mode', hint=get_doc_url('admin/install', 'celery'), id='weblate.E005', ) ) elif settings.CELERY_BROKER_URL == 'memory://': errors.append( Critical( 'Celery is configured to store queue in local memory', hint=get_doc_url('admin/install', 'celery'), id='weblate.E026', ) ) else: if is_celery_queue_long(): errors.append( Critical( 'The Celery tasks queue is too long, either the worker ' 'is not running or is too slow.', hint=get_doc_url('admin/install', 'celery'), id='weblate.E009', ) ) result = ping.delay() try: result.get(timeout=10, disable_sync_subtasks=False) except TimeoutError: errors.append( Critical( 'The Celery does not process tasks or is too slow ' 'in processing them.', hint=get_doc_url('admin/install', 'celery'), id='weblate.E019', ) ) except NotImplementedError: errors.append( Critical( 'The Celery is not configured to store results, ' 'CELERY_RESULT_BACKEND is probably not set.', hint=get_doc_url('admin/install', 'celery'), id='weblate.E020', ) ) heartbeat = cache.get('celery_heartbeat') if not heartbeat or time.time() - heartbeat > 600: errors.append( Critical( 'The Celery beats scheduler is not executing periodic tasks ' 'in a timely manner.', hint=get_doc_url('admin/install', 'celery'), id='weblate.C030', ) ) return errors
def test_printing_no_object(self): e = Error("Message", hint="Hint", obj=None) expected = "?: Message\n\tHINT: Hint" self.assertEqual(force_text(e), expected)
def test_printing_model_error(self): e = Error("Error", obj=SimpleModel) expected = "check_framework.SimpleModel: Error" self.assertEqual(force_text(e), expected)
def test_printing_with_given_id(self): e = Error("Message", hint="Hint", obj=DummyObj(), id="ID") expected = "obj: (ID) Message\n\tHINT: Hint" self.assertEqual(force_text(e), expected)
def test_printing_manager_error(self): manager = SimpleModel.manager e = Error("Error", hint=None, obj=manager) expected = "check_framework.SimpleModel.manager: Error" self.assertEqual(force_text(e), expected)
def test_printing_no_hint(self): e = Error("Message", obj=DummyObj()) expected = "obj: Message" self.assertEqual(str(e), expected)