<commit_before>import re

from django.core.validators import MinValueValidator
from django.utils.translation import ugettext_lazy as _
from rest_framework import exceptions as rf_exceptions
from rest_framework import serializers as rf_serializers

from waldur_core.core import serializers as core_serializers
from waldur_core.structure import serializers as structure_serializers
from waldur_core.structure.permissions import _has_owner_access
from waldur_freeipa import models as freeipa_models
from waldur_slurm import mixins as slurm_mixins

from . import models


class ServiceSerializer(
    core_serializers.ExtraFieldOptionsMixin,
    core_serializers.RequiredFieldsMixin,
    structure_serializers.BaseServiceSerializer,
):
    SERVICE_ACCOUNT_FIELDS = {
        'username': '',
    }
    SERVICE_ACCOUNT_EXTRA_FIELDS = {
        'hostname': _('Hostname or IP address of master node'),
        'port': '',
        'use_sudo': _('Set to true to activate privilege escalation'),
        'gateway': _('Hostname or IP address of gateway node'),
        'default_account': _('Default SLURM account for user'),
        'batch_service': _('Batch service, SLURM or MOAB'),
    }

    class Meta(structure_serializers.BaseServiceSerializer.Meta):
        model = models.SlurmService
        required_fields = ('hostname', 'username', 'batch_service')
        extra_field_options = {
            'username': {'default_value': 'root',},
            'use_sudo': {'default_value': False,},
            'default_account': {'required': True,},
        }


class ServiceProjectLinkSerializer(
    structure_serializers.BaseServiceProjectLinkSerializer
):
    class Meta(structure_serializers.BaseServiceProjectLinkSerializer.Meta):
        model = models.SlurmServiceProjectLink
        extra_kwargs = {
            'service': {'lookup_field': 'uuid', 'view_name': 'slurm-detail'},
        }


class AllocationSerializer(
    structure_serializers.BaseResourceSerializer,
    core_serializers.AugmentedSerializerMixin,
):
    service = rf_serializers.HyperlinkedRelatedField(
        source='service_project_link.service',
        view_name='slurm-detail',
        read_only=True,
        lookup_field='uuid',
    )

    service_project_link = rf_serializers.HyperlinkedRelatedField(
        view_name='slurm-spl-detail',
        queryset=models.SlurmServiceProjectLink.objects.all(),
        allow_null=True,
        required=False,
    )

    username = rf_serializers.SerializerMethodField()
    gateway = rf_serializers.SerializerMethodField()
    batch_service = rf_serializers.ReadOnlyField()
    homepage = rf_serializers.ReadOnlyField(
        source='service_project_link.service.settings.homepage'
    )

    def get_username(self, allocation):
        request = self.context['request']
        try:
            profile = freeipa_models.Profile.objects.get(user=request.user)
            return profile.username
        except freeipa_models.Profile.DoesNotExist:
            return None

    def get_gateway(self, allocation):
        options = allocation.service_project_link.service.settings.options
        return options.get('gateway') or options.get('hostname')

    class Meta(structure_serializers.BaseResourceSerializer.Meta):
        model = models.Allocation
        fields = structure_serializers.BaseResourceSerializer.Meta.fields + (
            'cpu_limit',
            'cpu_usage',
            'gpu_limit',
            'gpu_usage',
            'ram_limit',
            'ram_usage',
            'deposit_limit',
            'deposit_usage',
            'username',
            'gateway',
            'is_active',
            'batch_service',
            'homepage',
        )
        read_only_fields = (
            structure_serializers.BaseResourceSerializer.Meta.read_only_fields
            + (
                'cpu_usage',
                'gpu_usage',
                'ram_usage',
                'cpu_limit',
                'gpu_limit',
                'ram_limit',
                'is_active',
                'deposit_limit',
                'deposit_usage',
            )
        )
        extra_kwargs = dict(
            url={'lookup_field': 'uuid', 'view_name': 'slurm-allocation-detail'},
            cpu_limit={'validators': [MinValueValidator(0)]},
            gpu_limit={'validators': [MinValueValidator(0)]},
            ram_limit={'validators': [MinValueValidator(0)]},
        )

    def validate(self, attrs):
        attrs = super(AllocationSerializer, self).validate(attrs)
        # Skip validation on update
        if self.instance:
            return attrs

        correct_name_regex = '^([%s]{1,63})$' % models.SLURM_ALLOCATION_REGEX
        name = attrs.get('name')
        if not re.match(correct_name_regex, name):
            raise core_serializers.ValidationError(
                _(
                    "Name '%s' must be 1-63 characters long, each of "
                    "which can only be alphanumeric or a hyphen"
                )
                % name
            )

        spl = attrs['service_project_link']
        user = self.context['request'].user
        if not _has_owner_access(user, spl.project.customer):
            raise rf_exceptions.PermissionDenied(
                _('You do not have permissions to create allocation for given project.')
            )
        return attrs


class AllocationUsageSerializer(slurm_mixins.AllocationUsageSerializerMixin):
    class Meta(slurm_mixins.AllocationUsageSerializerMixin.Meta):
        model = models.AllocationUsage
        fields = (
            'allocation',
            'year',
            'month',
        ) + slurm_mixins.AllocationUsageSerializerMixin.Meta.fields
        extra_kwargs = {
            'allocation': {
                'lookup_field': 'uuid',
                'view_name': 'slurm-allocation-detail',
            },
        }


class AllocationUserUsageSerializer(slurm_mixins.AllocationUsageSerializerMixin):
    full_name = rf_serializers.ReadOnlyField(source='user.full_name')

    class Meta(slurm_mixins.AllocationUsageSerializerMixin.Meta):
        model = models.AllocationUserUsage
        fields = (
            'allocation_usage',
            'user',
            'username',
            'full_name',
        ) + slurm_mixins.AllocationUsageSerializerMixin.Meta.fields
        extra_kwargs = {
            'allocation_usage': {
                'lookup_field': 'uuid',
                'view_name': 'slurm-allocation-usage-detail',
            },
            'user': {'lookup_field': 'uuid', 'view_name': 'user-detail',},
        }<commit_msg>Remove uuid as lookup field for AllocationUsage<commit_after>import re

from django.core.validators import MinValueValidator
from django.utils.translation import ugettext_lazy as _
from rest_framework import exceptions as rf_exceptions
from rest_framework import serializers as rf_serializers

from waldur_core.core import serializers as core_serializers
from waldur_core.structure import serializers as structure_serializers
from waldur_core.structure.permissions import _has_owner_access
from waldur_freeipa import models as freeipa_models
from waldur_slurm import mixins as slurm_mixins

from . import models


class ServiceSerializer(
    core_serializers.ExtraFieldOptionsMixin,
    core_serializers.RequiredFieldsMixin,
    structure_serializers.BaseServiceSerializer,
):
    SERVICE_ACCOUNT_FIELDS = {
        'username': '',
    }
    SERVICE_ACCOUNT_EXTRA_FIELDS = {
        'hostname': _('Hostname or IP address of master node'),
        'port': '',
        'use_sudo': _('Set to true to activate privilege escalation'),
        'gateway': _('Hostname or IP address of gateway node'),
        'default_account': _('Default SLURM account for user'),
        'batch_service': _('Batch service, SLURM or MOAB'),
    }

    class Meta(structure_serializers.BaseServiceSerializer.Meta):
        model = models.SlurmService
        required_fields = ('hostname', 'username', 'batch_service')
        extra_field_options = {
            'username': {'default_value': 'root',},
            'use_sudo': {'default_value': False,},
            'default_account': {'required': True,},
        }


class ServiceProjectLinkSerializer(
    structure_serializers.BaseServiceProjectLinkSerializer
):
    class Meta(structure_serializers.BaseServiceProjectLinkSerializer.Meta):
        model = models.SlurmServiceProjectLink
        extra_kwargs = {
            'service': {'lookup_field': 'uuid', 'view_name': 'slurm-detail'},
        }


class AllocationSerializer(
    structure_serializers.BaseResourceSerializer,
    core_serializers.AugmentedSerializerMixin,
):
    service = rf_serializers.HyperlinkedRelatedField(
        source='service_project_link.service',
        view_name='slurm-detail',
        read_only=True,
        lookup_field='uuid',
    )

    service_project_link = rf_serializers.HyperlinkedRelatedField(
        view_name='slurm-spl-detail',
        queryset=models.SlurmServiceProjectLink.objects.all(),
        allow_null=True,
        required=False,
    )

    username = rf_serializers.SerializerMethodField()
    gateway = rf_serializers.SerializerMethodField()
    batch_service = rf_serializers.ReadOnlyField()
    homepage = rf_serializers.ReadOnlyField(
        source='service_project_link.service.settings.homepage'
    )

    def get_username(self, allocation):
        request = self.context['request']
        try:
            profile = freeipa_models.Profile.objects.get(user=request.user)
            return profile.username
        except freeipa_models.Profile.DoesNotExist:
            return None

    def get_gateway(self, allocation):
        options = allocation.service_project_link.service.settings.options
        return options.get('gateway') or options.get('hostname')

    class Meta(structure_serializers.BaseResourceSerializer.Meta):
        model = models.Allocation
        fields = structure_serializers.BaseResourceSerializer.Meta.fields + (
            'cpu_limit',
            'cpu_usage',
            'gpu_limit',
            'gpu_usage',
            'ram_limit',
            'ram_usage',
            'deposit_limit',
            'deposit_usage',
            'username',
            'gateway',
            'is_active',
            'batch_service',
            'homepage',
        )
        read_only_fields = (
            structure_serializers.BaseResourceSerializer.Meta.read_only_fields
            + (
                'cpu_usage',
                'gpu_usage',
                'ram_usage',
                'cpu_limit',
                'gpu_limit',
                'ram_limit',
                'is_active',
                'deposit_limit',
                'deposit_usage',
            )
        )
        extra_kwargs = dict(
            url={'lookup_field': 'uuid', 'view_name': 'slurm-allocation-detail'},
            cpu_limit={'validators': [MinValueValidator(0)]},
            gpu_limit={'validators': [MinValueValidator(0)]},
            ram_limit={'validators': [MinValueValidator(0)]},
        )

    def validate(self, attrs):
        attrs = super(AllocationSerializer, self).validate(attrs)
        # Skip validation on update
        if self.instance:
            return attrs

        correct_name_regex = '^([%s]{1,63})$' % models.SLURM_ALLOCATION_REGEX
        name = attrs.get('name')
        if not re.match(correct_name_regex, name):
            raise core_serializers.ValidationError(
                _(
                    "Name '%s' must be 1-63 characters long, each of "
                    "which can only be alphanumeric or a hyphen"
                )
                % name
            )

        spl = attrs['service_project_link']
        user = self.context['request'].user
        if not _has_owner_access(user, spl.project.customer):
            raise rf_exceptions.PermissionDenied(
                _('You do not have permissions to create allocation for given project.')
            )
        return attrs


class AllocationUsageSerializer(slurm_mixins.AllocationUsageSerializerMixin):
    class Meta(slurm_mixins.AllocationUsageSerializerMixin.Meta):
        model = models.AllocationUsage
        fields = (
            'allocation',
            'year',
            'month',
        ) + slurm_mixins.AllocationUsageSerializerMixin.Meta.fields
        extra_kwargs = {
            'allocation': {
                'lookup_field': 'uuid',
                'view_name': 'slurm-allocation-detail',
            },
        }


class AllocationUserUsageSerializer(slurm_mixins.AllocationUsageSerializerMixin):
    full_name = rf_serializers.ReadOnlyField(source='user.full_name')

    class Meta(slurm_mixins.AllocationUsageSerializerMixin.Meta):
        model = models.AllocationUserUsage
        fields = (
            'allocation_usage',
            'user',
            'username',
            'full_name',
        ) + slurm_mixins.AllocationUsageSerializerMixin.Meta.fields
        extra_kwargs = {
            'allocation_usage': {'view_name': 'slurm-allocation-usage-detail',},
            'user': {'lookup_field': 'uuid', 'view_name': 'user-detail',},
        }
{'fraction_non_alphanumeric': 0.09557145031197686, 'fraction_numerical': 0.0013696545426875666, 'mean_word_length': 2.457774269928966, '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': '2467669', 'n_tokens_mistral': 3618, 'n_tokens_neox': 3599, 'n_words': 660}