Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/settings check #14

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions data_generator/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,18 @@ class DataGeneratorConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "data_generator"
verbose_name = _("Data Generator")

def ready(self) -> None:
"""This method is called when the application is fully loaded.

Its main purpose is to perform startup tasks, such as importing
and registering system checks for validating the configuration
settings of the app. It ensures that all necessary configurations
are in place and properly validated when the Django project initializes.

In this case, it imports the settings checks from the
`data_generator.settings` module to validate the configuration
settings.

"""
from data_generator.settings import check
Empty file.
56 changes: 56 additions & 0 deletions data_generator/settings/check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from typing import Any, List

from django.core.checks import Error, register

from data_generator.settings.conf import config
from data_generator.validators.config_validators import (
validate_custom_field_values,
validate_str_list,
)


@register()
def check_data_generator_settings(app_configs: Any, **kwargs: Any) -> List[Error]:
"""Check and validate data generator settings in the Django configuration.

This function performs validation of various related settings
defined in the Django settings. It returns a list of errors if any issues are found.

Parameters:
-----------
app_configs : Any
Passed by Django during checks (not used here).

kwargs : Any
Additional keyword arguments for flexibility.

Returns:
--------
List[Error]
A list of `Error` objects for any detected configuration issues.

"""
errors: List[Error] = []

errors.extend(
validate_str_list(
config.exclude_apps,
f"{config.prefix}EXCLUDE_APPS",
True,
)
)
errors.extend(
validate_str_list(
config.exclude_models,
f"{config.prefix}EXCLUDE_MODELS",
True,
True,
)
)
errors.extend(
validate_custom_field_values(
config.custom_field_values, f"{config.prefix}CUSTOM_FIELD_VALUES"
)
)

return errors
Empty file.
137 changes: 137 additions & 0 deletions data_generator/validators/config_validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
from typing import List

from django.apps import apps
from django.core.checks import Error

from data_generator.constants.types import CustomFieldValues


def validate_str_list(
elements: List[str],
config_name: str,
allow_empty: bool = False,
is_for_model: bool = False,
) -> List[Error]:
errors = []
if not isinstance(elements, list):
errors.append(
Error(
f"{config_name} is not a list.",
hint=f"Ensure {config_name} is a list of strings.",
id=f"data_generator.E002_{config_name}",
)
)
elif not elements and not allow_empty:
errors.append(
Error(
f"{config_name} is an empty list.",
hint=f"Ensure {config_name} contains at least one valid string.",
id=f"data_generator.E003_{config_name}",
)
)
else:
for element in elements:
if not isinstance(element, str):
errors.append(
Error(
f"Invalid type(s) in {config_name}: {element} is not an string.",
hint=f"Ensure all elements in {config_name} are strings.",
id=f"data_generator.E004_{config_name}",
)
)
continue

if is_for_model:
error = validate_model_existence(element, config_name)
if error:
errors.append(error)
continue

return errors


def validate_custom_field_values(
config: CustomFieldValues, config_name: str
) -> List[Error]:
errors = []

if not isinstance(config, dict):
errors.append(
Error(
f"{config_name} should be a dictionary.",
hint=f"Ensure {config_name} is a dictionary where each key is a model name.",
id=f"data_generator.E005_{config_name}",
)
)
return errors

for model_name, fields in config.items():
if not isinstance(model_name, str):
errors.append(
Error(
f"Model name '{model_name}' in {config_name} is not a string.",
hint="Each model name should be a string.",
id=f"data_generator.E006_{config_name}",
)
)
continue

error = validate_model_existence(model_name, config_name)
if error:
errors.append(error)
continue

if not isinstance(fields, dict):
errors.append(
Error(
f"Fields configuration for model '{model_name}' in {config_name} should be a dictionary.",
hint="Each model's fields configuration should be a dictionary of field-value pairs.",
id=f"data_generator.E008_{config_name}",
)
)
continue
model = apps.get_model(model_name)
model_field_names = {f.name for f in model._meta.fields}
for field_name, value in fields.items():
if not isinstance(field_name, str):
errors.append(
Error(
f"Field name '{field_name}' in model '{model_name}' is not a string.",
hint="Each field name should be a string.",
id=f"data_generator.E009_{config_name}",
)
)
continue

if field_name not in model_field_names:
errors.append(
Error(
f"Field '{field_name}' does not exist in model '{model_name}'.",
hint="Ensure the field name is correct and exists in the model.",
id=f"data_generator.E0010_{config_name}",
)
)

return errors


def validate_model_existence(model: str, config_name: str) -> Error:
"""Validate that the specified model exists in the Django project.

Args:
----
model (str): The model name in 'app_label.ModelName' format.
config_name (str): The configuration name where the model is specified.

Returns:
-------
Optional[Error]: An error object if the model is not found; otherwise, None.
"""
try:
apps.get_model(model)
except (LookupError, ValueError):
return Error(
f"Model '{model}' specified in {config_name} does not exist.",
hint="Ensure the model name is correct and defined with 'app_label.ModelName' in your project.",
id=f"data_generator.E007_{config_name}",
)