<commit_before>from celery import chain
from django.core import checks
from django.db.models import Model
from django.db.migrations.topological_sort import stable_topological_sort

from nodeconductor.core import NodeConductorExtension
from nodeconductor.core import executors as core_executors
from nodeconductor.core import tasks as core_tasks
from nodeconductor.core import utils as core_utils
from nodeconductor.structure.tasks import ConnectSharedSettingsTask


class ServiceSettingsCreateExecutor(core_executors.CreateExecutor):

    @classmethod
    def get_task_signature(cls, settings, serialized_settings, **kwargs):
        creation_tasks = [core_tasks.StateTransitionTask().si(serialized_settings, state_transition='begin_creating')]
        # connect settings to all customers if they are shared
        if settings.shared:
            creation_tasks.append(ConnectSharedSettingsTask().si(serialized_settings))
        # sync settings if they have not only global properties
        backend = settings.get_backend()
        if not backend.has_global_properties():
            creation_tasks.append(core_tasks.IndependentBackendMethodTask().si(serialized_settings, 'sync'))
        return chain(*creation_tasks)


class ServiceSettingsPullExecutor(core_executors.ActionExecutor):

    @classmethod
    def get_task_signature(cls, settings, serialized_settings, **kwargs):
        return core_tasks.IndependentBackendMethodTask().si(
            serialized_settings, 'sync', state_transition='begin_updating')


class ServiceSettingsConnectSharedExecutor(core_executors.BaseExecutor):

    @classmethod
    def get_task_signature(cls, settings, serialized_settings, **kwargs):
        return ConnectSharedSettingsTask().si(serialized_settings)


class BaseCleanupExecutor(core_executors.BaseExecutor):
    """
    In order to delete project and related resources, we need to take into account three constraints:

    1) dependencies between resources;
    2) dependencies between applications;
    3) backend API calls to delete resources.

    All these steps are optional, because some applications don't have all these constraints.
    In order to delete resources with respect to dependencies between them,
    cleanup executor should specify models in the correct order.

    For example, if Snapshot should be deleted before Virtual machine,
    models should be equal to (Snapshot, VirtualMachine)

    It is assumed that each model class can be filtered by project.
    Models are deleted before executors are applied.

    executors is optional list of tuples (model class, executor class).
    When executor is applied, all resources in the project are deleted using this executor.
    If related_executor is specified, then current executor is applied before related executor.

    Consider for example:

    class OpenStackCleanupExecutor(structure_executors.BaseCleanupExecutor):
        executors = (
            (models.SecurityGroup, SecurityGroupDeleteExecutor),
            (models.FloatingIP, FloatingIPDeleteExecutor),
            (models.SubNet, SubNetDeleteExecutor),
            (models.Network, NetworkDeleteExecutor),
            (models.Tenant, TenantDeleteExecutor),
        )

    class OpenStackTenantCleanupExecutor(structure_executors.BaseCleanupExecutor):
        related_executor = openstack_executors.OpenStackCleanupExecutor

        pre_models = (
            models.SnapshotSchedule,
            models.BackupSchedule,
        )

        executors = (
            (models.Snapshot, SnapshotDeleteExecutor),
            (models.Backup, BackupDeleteExecutor),
            (models.Instance, InstanceDeleteExecutor),
            (models.Volume, VolumeDeleteExecutor),
        )

    """

    pre_models = []
    executors = []
    related_executor = None

    @classmethod
    def pre_apply(cls, instance, **kwargs):
        for model_cls in cls.pre_models:
            model_cls.objects.filter(project=instance).delete()

    @classmethod
    def get_task_signature(cls, instance, serialized_instance, **kwargs):
        """
        Delete each resource using specific executor.
        Convert executors to task and combine all deletion task into single sequential task.
        """
        cleanup_tasks = [<commit_msg>Improve docstring for BaseCleanupExecutor [WAL-1151]<commit_after>from celery import chain
from django.core import checks
from django.db.models import Model
from django.db.migrations.topological_sort import stable_topological_sort

from nodeconductor.core import NodeConductorExtension
from nodeconductor.core import executors as core_executors
from nodeconductor.core import tasks as core_tasks
from nodeconductor.core import utils as core_utils
from nodeconductor.structure.tasks import ConnectSharedSettingsTask


class ServiceSettingsCreateExecutor(core_executors.CreateExecutor):

    @classmethod
    def get_task_signature(cls, settings, serialized_settings, **kwargs):
        creation_tasks = [core_tasks.StateTransitionTask().si(serialized_settings, state_transition='begin_creating')]
        # connect settings to all customers if they are shared
        if settings.shared:
            creation_tasks.append(ConnectSharedSettingsTask().si(serialized_settings))
        # sync settings if they have not only global properties
        backend = settings.get_backend()
        if not backend.has_global_properties():
            creation_tasks.append(core_tasks.IndependentBackendMethodTask().si(serialized_settings, 'sync'))
        return chain(*creation_tasks)


class ServiceSettingsPullExecutor(core_executors.ActionExecutor):

    @classmethod
    def get_task_signature(cls, settings, serialized_settings, **kwargs):
        return core_tasks.IndependentBackendMethodTask().si(
            serialized_settings, 'sync', state_transition='begin_updating')


class ServiceSettingsConnectSharedExecutor(core_executors.BaseExecutor):

    @classmethod
    def get_task_signature(cls, settings, serialized_settings, **kwargs):
        return ConnectSharedSettingsTask().si(serialized_settings)


class BaseCleanupExecutor(core_executors.BaseExecutor):
    """
    In order to delete project and related resources, we need to take into account three constraints:

    1) dependencies between applications;
    2) dependencies between resources;
    3) backend API calls to delete resources.

    All these steps are optional, because some applications don't have all these constraints.

    1) If `related_executor` is specified, then current executor is applied before related executor.

    2) Project's resources are specified by the `pre_models` field.
       It is assumed that each model class can be filtered by project.

    3) The value of `executors` field is list of tuples (model class, executor class).
       Executors are applied after resources specified by pre_models field are deleted.
       When executor is applied, all resources in the project are deleted using this executor.

    Consider for example:

    class OpenStackCleanupExecutor(structure_executors.BaseCleanupExecutor):
        executors = (
            (models.SecurityGroup, SecurityGroupDeleteExecutor),
            (models.FloatingIP, FloatingIPDeleteExecutor),
            (models.SubNet, SubNetDeleteExecutor),
            (models.Network, NetworkDeleteExecutor),
            (models.Tenant, TenantDeleteExecutor),
        )

    class OpenStackTenantCleanupExecutor(structure_executors.BaseCleanupExecutor):
        related_executor = openstack_executors.OpenStackCleanupExecutor

        pre_models = (
            models.SnapshotSchedule,
            models.BackupSchedule,
        )

        executors = (
            (models.Snapshot, SnapshotDeleteExecutor),
            (models.Backup, BackupDeleteExecutor),
            (models.Instance, InstanceDeleteExecutor),
            (models.Volume, VolumeDeleteExecutor),
        )
    """

    pre_models = []
    executors = []
    related_executor = None

    @classmethod
    def pre_apply(cls, instance, **kwargs):
        for model_cls in cls.pre_models:
            model_cls.objects.filter(project=instance).delete()

    @classmethod
    def get_task_signature(cls, instance, serialized_instance, **kwargs):
        """
        Delete each resource using specific executor.
        Convert executors to task and combine all deletion task into single sequential task.
        """
        cleanup_tasks = [
{'fraction_non_alphanumeric': 0.06514000949216896, 'fraction_numerical': 0.0015424774560987185, 'mean_word_length': 3.6905954368391765, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2960340', 'n_tokens_mistral': 2087, 'n_tokens_neox': 2019, 'n_words': 617}