<commit_before>"""
    Extensible validation for Python dictionaries.
    This module implements Cerberus Validator class

    :copyright: 2012-2013 by Nicola Iarocci.
    :license: ISC, see LICENSE for more details.

    Full documentation is available at http://cerberus.readthedocs.org/
"""

import sys
from datetime import datetime
from . import errors

if sys.version_info[0] == 3:
    _str_type = str
    _int_types = (int,)
else:
    _str_type = basestring
    _int_types = (int, long)

class ValidationError(ValueError):
    """ Raised when the target dictionary is missing or has the wrong format
    """
    pass

class SchemaError(ValueError):
    """ Raised when the validation schema is missing, has the wrong format or
    contains errors.
    """
    pass

class Validator(object):
    """ Validator class. Validates any Python dict against a validation schema,
    which is provided as an argument at class instantiation, or upon calling
    the :func:`validate` method.

    :param schema: optional validation schema.
    :param transparent_schema_rules: if ``True`` unknown schema rules will be
                                 ignored (no SchemaError will be raised).
                                 Defaults to ``False``. Useful you need to
                                 extend the schema grammar beyond Cerberus'
                                 domain.
    :param ignore_none_values: If ``True`` it will ignore None values for type
                               checking. (no UnknowType error will be added).
                               Defaults to ``False``. Useful if your document
                               is composed from function kwargs with defaults.
    :param allow_unknown: if ``True`` unknown key/value pairs (not present in
                          the schema) will be ignored, and validation will
                          pass. Defaults to ``False``, returning an 'unknown
                          field error' un validation.

    .. versionchanged:: 0.4.1
       ``validator.errors`` returns a dict where keys are document fields and
       values are validation errors.

    .. versionchanged:: 0.4.0
       :func:`validate_update` is deprecated. Use :func:`validate` with
       ``update=True`` instead.
       Type validation is always performed first (only exception being
       ``nullable``). On failure, it blocks other rules on the same field.
       Closes #18.

    .. versionadded:: 0.2.0
       `self.errors` returns an empty list when validate() has not been called.
       Option so allow nullable field values.
       Option to allow unknown key/value pairs.

    .. versionadded:: 0.1.0
       Option to ignore None values for type checking.

    .. versionadded:: 0.0.3
       Support for transparent schema rules.
       Added new 'empty' rule for string fields.

    .. versionadded:: 0.0.2
        Support for addition and validation of custom data types.
    """

    def __init__(self, schema=None, transparent_schema_rules=False,
                 ignore_none_values=False, allow_unknown=False):
        self.schema = schema
        self.transparent_schema_rules = transparent_schema_rules
        self.ignore_none_values = ignore_none_values
        self.allow_unknown = allow_unknown
        self._errors = {}

    def __call__(self, *args, **kwargs):
        return self.validate(*args, **kwargs)

    @property
    def errors(self):
        """
        :rtype: a list of validation errors. Will be empty if no errors
                were found during. Resets after each call to :func:`validate`.
        """
        return self._errors

    def validate_update(self, document, schema=None):
        """ Validates a Python dicitionary against a validation schema. The
        difference with :func:`validate` is that the ``required`` rule will be
        ignored here.

        :param schema: optional validation schema. Defaults to ``None``. If not
                       provided here, the schema must have been provided at
                       class instantation.
        :return: True if validation succeeds, False otherwise. Check the
                 :func:`errors` property for a list of validation errors.

        .. deprecated:: 0.4.0
           Use :func:`validate` with ``update=True`` instead.
        """
        return self._validate(document, schema, update=True)

    def validate(self, document, schema=None, update=False):
        """ Validates a Python dictionary against a validation schema.

        :param document: the dict to validate.
        :param schema: the validation schema. Defaults to ``None``. If not
                       provided here, the schema must have been provided at
                       class instantation.
        :param update: If ``True`` validation of required fields won't be
                       performed.

        :return: True if validation succeeds, False otherwise. Check the
                 :func:`errors` property for a list of validation errors.

        .. versionchanged:: 0.4.0
           Support for update mode.
        """
        return self._validate(document, schema, update=update)

    def _validate(self, document, schema=None, update=False):

        self._errors = {}
        self.update = update

        if schema is not None:
            self.schema = schema
        elif self.schema is None:
            raise SchemaError(errors.ERROR_SCHEMA_MISSING)
        if not isinstance(self.schema, dict):
            raise SchemaError(errors.ERROR_SCHEMA_FORMAT % str(self.schema))

        if document is None:
            raise ValidationError(errors.ERROR_DOCUMENT_MISSING)
        if not isinstance(document, dict):
            raise ValidationError(errors.ERROR_DOCUMENT_FORMAT % str(document))
        self.document = document

        special_rules = ["required", "nullable", "type"]
        for field, value in self.document.items():

            if self.ignore_none_values and value is None:
                continue

            definition = self.schema.get(field)
            if definition:
                if isinstance(definition, dict):

                    if definition.get("nullable", False) == True \
                       and value is None:  # noqa
                        continue

                    if 'type' in definition:
                        self._validate_type(definition['type'], field, value)
                        if self.errors:
                            continue

                    definition_rules = [rule for rule in definition.keys()
                                        if rule not in special_rules]
                    for rule in definition_rules:
                        validatorname = "_validate_" + rule.replace(" ", "_")
                        validator = getattr(self, validatorname, None)
                        if validator:
                            validator(definition[rule], field, value)
                        elif not self.transparent_schema_rules:
                            raise SchemaError(errors.ERROR_UNKNOWN_RULE %
                                              (rule, field))
                else:
                    raise SchemaError(errors.ERROR_DEFINITION_FORMAT % field)

            else:
                if not self.allow_unknown:
                    self._error(field, errors.ERROR_UNKNOWN_FIELD)

        if not self.update:
            self._validate_required_fields()

        return len(self._errors) == 0

    def _error(self, field, _error):
        field_errors = self._errors.get(field, [])
        if not isinstance(field_errors, list):
            field_errors = [field_errors]
        if isinstance(_error, _str_type):
            field_errors.append(_error)
        elif isinstance(_error, dict):
            field_errors.append(_error)
        else:
            field_errors.extend(_error)
        if len(field_errors) == 1:
            field_errors = field_errors.pop()
        self._errors[field] = field_errors

    def _validate_required_fields(self):
        required = list(field for field, definition in self.schema.items()
                        if definition.get('required') is True)
        missing = set(required) - set(key for key in self.document.keys()
                                      if self.document.get(key) is not None
                                      or not self.ignore_none_values)
        for field in missing:
            self._error(field, errors.ERROR_REQUIRED_FIELD)

    def _validate_readonly(self, read_only, field, value):
        if read_only:
            self._error(field, errors.ERROR_READONLY_FIELD)

    def _validate_type(self, data_type, field, value):
        validator = getattr(self, "_validate_type_" + data_type, None)
        if validator:
            validator(field, value)
        else:
            raise SchemaError(errors.ERROR_UNKNOWN_TYPE % data_type)

    def _validate_type_string(self, field, value):
        if not isinstance(value, _str_type):
            self._error(field, errors.ERROR_BAD_TYPE % "string")

    def _validate_type_integer(self, field, value):
        if not isinstance(value, _int_types):
            self._error(field, errors.ERROR_BAD_TYPE % "integer")

    def _validate_type_float(self, field, value):
        if not isinstance(value, float):
            self._error(field, errors.ERROR_BAD_TYPE % "float")

    def _validate_type_boolean(self, field, value):
        if not isinstance(value, bool):
            self._error(field, errors.ERROR_BAD_TYPE % "boolean")

    def _validate_type_datetime(self, field, value):
        if not isinstance(value, datetime):
            self._error(field, errors.ERROR_BAD_TYPE % "datetime")

    def _validate_type_dict(self, field, value):
        if not isinstance(value, dict):
            self._error(field, errors.ERROR_BAD_TYPE % "dict")

    def _validate_type_list(self, field, value):
        if not isinstance(value, list):
            self._error(field, errors.ERROR_BAD_TYPE % "list")

    def _validate_maxlength(self, max_length, field, value):
        if isinstance(value, (_str_type, list)):
            if len(value) > max_length:
                self._error(field, errors.ERROR_MAX_LENGTH % max_length)

    def _validate_minlength(self, min_length, field, value):
        if isinstance(value, (_str_type, list)):
            if len(value) < min_length:
                self._error(field, errors.ERROR_MIN_LENGTH % min_length)

    def _validate_max(self, max_value, field, value):
        if isinstance(value, _int_types):
            if value > max_value:
                self._error(field, errors.ERROR_MAX_VALUE % max_value)

    def _validate_min(self, min_value, field, value):
        if isinstance(value, _int_types):
            if value < min_value:
                self._error(field, errors.ERROR_MIN_VALUE % min_value)

    def _validate_allowed(self, allowed_values, field, value):
        if isinstance(value, _str_type):
            if value not in allowed_values:
                self._error(field, errors.ERROR_UNALLOWED_VALUE % value)
        elif isinstance(value, list):
            disallowed = set(value) - set(allowed_values)
            if disallowed:
                self._error(field,
                            errors.ERROR_UNALLOWED_VALUES % list(disallowed))
        elif isinstance(value, int):
            if value not in allowed_values:
                self._error(field, errors.ERROR_UNALLOWED_VALUE % value)

    def _validate_empty(self, empty, field, value):
        if isinstance(value, _str_type) and len(value) == 0 and not empty:
            self._error(field, errors.ERROR_EMPTY_NOT_ALLOWED)

    def _validate_schema(self, schema, field, value):
        if isinstance(value, list):
            list_errors = {}
            for i in range(len(value)):
                validator = self.__class__({i: schema})
                validator.validate({i: value[i]})
                list_errors.update(validator.errors)
            if len(list_errors):
                self._error(field, list_errors)
        elif isinstance(value, dict):
            validator = self.__class__(schema)
            validator.validate(value)
            if len(validator.errors):
                self._error(field, validator.errors)
        else:
            self._error(field, errors.ERROR_BAD_TYPE % "dict")

    def _validate_items(self, items, field, value):
        if isinstance(items, dict):
            self._validate_items_schema(items, field, value)
        elif isinstance(items, list):
            self._validate_items_list(items, field, value)

    def _validate_items_list(self, schema, field, values):
        if len(schema) != len(values):
            self._error(field, errors.ERROR_ITEMS_LIST % len(schema))
        else:
            for i in range(len(schema)):
                validator = self.__class__({i: schema[i]})
                validator.validate({i: values[i]})
                self.errors.update(validator.errors)

    def _validate_items_schema(self, schema, field, value):
        validator = self.__class__(schema)
        for item in value:
            validator.validate(item)
            for field, error in validator.errors.items():
                self._error(field, error)
<commit_msg>More precise error msg in rule `schema` validation<commit_after>"""
    Extensible validation for Python dictionaries.
    This module implements Cerberus Validator class

    :copyright: 2012-2013 by Nicola Iarocci.
    :license: ISC, see LICENSE for more details.

    Full documentation is available at http://cerberus.readthedocs.org/
"""

import sys
from datetime import datetime
from . import errors

if sys.version_info[0] == 3:
    _str_type = str
    _int_types = (int,)
else:
    _str_type = basestring
    _int_types = (int, long)

class ValidationError(ValueError):
    """ Raised when the target dictionary is missing or has the wrong format
    """
    pass

class SchemaError(ValueError):
    """ Raised when the validation schema is missing, has the wrong format or
    contains errors.
    """
    pass

class Validator(object):
    """ Validator class. Validates any Python dict against a validation schema,
    which is provided as an argument at class instantiation, or upon calling
    the :func:`validate` method.

    :param schema: optional validation schema.
    :param transparent_schema_rules: if ``True`` unknown schema rules will be
                                 ignored (no SchemaError will be raised).
                                 Defaults to ``False``. Useful you need to
                                 extend the schema grammar beyond Cerberus'
                                 domain.
    :param ignore_none_values: If ``True`` it will ignore None values for type
                               checking. (no UnknowType error will be added).
                               Defaults to ``False``. Useful if your document
                               is composed from function kwargs with defaults.
    :param allow_unknown: if ``True`` unknown key/value pairs (not present in
                          the schema) will be ignored, and validation will
                          pass. Defaults to ``False``, returning an 'unknown
                          field error' un validation.

    .. versionchanged:: 0.4.1
       ``validator.errors`` returns a dict where keys are document fields and
       values are validation errors.

    .. versionchanged:: 0.4.0
       :func:`validate_update` is deprecated. Use :func:`validate` with
       ``update=True`` instead.
       Type validation is always performed first (only exception being
       ``nullable``). On failure, it blocks other rules on the same field.
       Closes #18.

    .. versionadded:: 0.2.0
       `self.errors` returns an empty list when validate() has not been called.
       Option so allow nullable field values.
       Option to allow unknown key/value pairs.

    .. versionadded:: 0.1.0
       Option to ignore None values for type checking.

    .. versionadded:: 0.0.3
       Support for transparent schema rules.
       Added new 'empty' rule for string fields.

    .. versionadded:: 0.0.2
        Support for addition and validation of custom data types.
    """

    def __init__(self, schema=None, transparent_schema_rules=False,
                 ignore_none_values=False, allow_unknown=False):
        self.schema = schema
        self.transparent_schema_rules = transparent_schema_rules
        self.ignore_none_values = ignore_none_values
        self.allow_unknown = allow_unknown
        self._errors = {}

    def __call__(self, *args, **kwargs):
        return self.validate(*args, **kwargs)

    @property
    def errors(self):
        """
        :rtype: a list of validation errors. Will be empty if no errors
                were found during. Resets after each call to :func:`validate`.
        """
        return self._errors

    def validate_update(self, document, schema=None):
        """ Validates a Python dicitionary against a validation schema. The
        difference with :func:`validate` is that the ``required`` rule will be
        ignored here.

        :param schema: optional validation schema. Defaults to ``None``. If not
                       provided here, the schema must have been provided at
                       class instantation.
        :return: True if validation succeeds, False otherwise. Check the
                 :func:`errors` property for a list of validation errors.

        .. deprecated:: 0.4.0
           Use :func:`validate` with ``update=True`` instead.
        """
        return self._validate(document, schema, update=True)

    def validate(self, document, schema=None, update=False):
        """ Validates a Python dictionary against a validation schema.

        :param document: the dict to validate.
        :param schema: the validation schema. Defaults to ``None``. If not
                       provided here, the schema must have been provided at
                       class instantation.
        :param update: If ``True`` validation of required fields won't be
                       performed.

        :return: True if validation succeeds, False otherwise. Check the
                 :func:`errors` property for a list of validation errors.

        .. versionchanged:: 0.4.0
           Support for update mode.
        """
        return self._validate(document, schema, update=update)

    def _validate(self, document, schema=None, update=False):

        self._errors = {}
        self.update = update

        if schema is not None:
            self.schema = schema
        elif self.schema is None:
            raise SchemaError(errors.ERROR_SCHEMA_MISSING)
        if not isinstance(self.schema, dict):
            raise SchemaError(errors.ERROR_SCHEMA_FORMAT % str(self.schema))

        if document is None:
            raise ValidationError(errors.ERROR_DOCUMENT_MISSING)
        if not isinstance(document, dict):
            raise ValidationError(errors.ERROR_DOCUMENT_FORMAT % str(document))
        self.document = document

        special_rules = ["required", "nullable", "type"]
        for field, value in self.document.items():

            if self.ignore_none_values and value is None:
                continue

            definition = self.schema.get(field)
            if definition:
                if isinstance(definition, dict):

                    if definition.get("nullable", False) == True \
                       and value is None:  # noqa
                        continue

                    if 'type' in definition:
                        self._validate_type(definition['type'], field, value)
                        if self.errors:
                            continue

                    definition_rules = [rule for rule in definition.keys()
                                        if rule not in special_rules]
                    for rule in definition_rules:
                        validatorname = "_validate_" + rule.replace(" ", "_")
                        validator = getattr(self, validatorname, None)
                        if validator:
                            validator(definition[rule], field, value)
                        elif not self.transparent_schema_rules:
                            raise SchemaError(errors.ERROR_UNKNOWN_RULE %
                                              (rule, field))
                else:
                    raise SchemaError(errors.ERROR_DEFINITION_FORMAT % field)

            else:
                if not self.allow_unknown:
                    self._error(field, errors.ERROR_UNKNOWN_FIELD)

        if not self.update:
            self._validate_required_fields()

        return len(self._errors) == 0

    def _error(self, field, _error):
        field_errors = self._errors.get(field, [])
        if not isinstance(field_errors, list):
            field_errors = [field_errors]
        if isinstance(_error, _str_type):
            field_errors.append(_error)
        elif isinstance(_error, dict):
            field_errors.append(_error)
        else:
            field_errors.extend(_error)
        if len(field_errors) == 1:
            field_errors = field_errors.pop()
        self._errors[field] = field_errors

    def _validate_required_fields(self):
        required = list(field for field, definition in self.schema.items()
                        if definition.get('required') is True)
        missing = set(required) - set(key for key in self.document.keys()
                                      if self.document.get(key) is not None
                                      or not self.ignore_none_values)
        for field in missing:
            self._error(field, errors.ERROR_REQUIRED_FIELD)

    def _validate_readonly(self, read_only, field, value):
        if read_only:
            self._error(field, errors.ERROR_READONLY_FIELD)

    def _validate_type(self, data_type, field, value):
        validator = getattr(self, "_validate_type_" + data_type, None)
        if validator:
            validator(field, value)
        else:
            raise SchemaError(errors.ERROR_UNKNOWN_TYPE % data_type)

    def _validate_type_string(self, field, value):
        if not isinstance(value, _str_type):
            self._error(field, errors.ERROR_BAD_TYPE % "string")

    def _validate_type_integer(self, field, value):
        if not isinstance(value, _int_types):
            self._error(field, errors.ERROR_BAD_TYPE % "integer")

    def _validate_type_float(self, field, value):
        if not isinstance(value, float):
            self._error(field, errors.ERROR_BAD_TYPE % "float")

    def _validate_type_boolean(self, field, value):
        if not isinstance(value, bool):
            self._error(field, errors.ERROR_BAD_TYPE % "boolean")

    def _validate_type_datetime(self, field, value):
        if not isinstance(value, datetime):
            self._error(field, errors.ERROR_BAD_TYPE % "datetime")

    def _validate_type_dict(self, field, value):
        if not isinstance(value, dict):
            self._error(field, errors.ERROR_BAD_TYPE % "dict")

    def _validate_type_list(self, field, value):
        if not isinstance(value, list):
            self._error(field, errors.ERROR_BAD_TYPE % "list")

    def _validate_maxlength(self, max_length, field, value):
        if isinstance(value, (_str_type, list)):
            if len(value) > max_length:
                self._error(field, errors.ERROR_MAX_LENGTH % max_length)

    def _validate_minlength(self, min_length, field, value):
        if isinstance(value, (_str_type, list)):
            if len(value) < min_length:
                self._error(field, errors.ERROR_MIN_LENGTH % min_length)

    def _validate_max(self, max_value, field, value):
        if isinstance(value, _int_types):
            if value > max_value:
                self._error(field, errors.ERROR_MAX_VALUE % max_value)

    def _validate_min(self, min_value, field, value):
        if isinstance(value, _int_types):
            if value < min_value:
                self._error(field, errors.ERROR_MIN_VALUE % min_value)

    def _validate_allowed(self, allowed_values, field, value):
        if isinstance(value, _str_type):
            if value not in allowed_values:
                self._error(field, errors.ERROR_UNALLOWED_VALUE % value)
        elif isinstance(value, list):
            disallowed = set(value) - set(allowed_values)
            if disallowed:
                self._error(field,
                            errors.ERROR_UNALLOWED_VALUES % list(disallowed))
        elif isinstance(value, int):
            if value not in allowed_values:
                self._error(field, errors.ERROR_UNALLOWED_VALUE % value)

    def _validate_empty(self, empty, field, value):
        if isinstance(value, _str_type) and len(value) == 0 and not empty:
            self._error(field, errors.ERROR_EMPTY_NOT_ALLOWED)

    def _validate_schema(self, schema, field, value):
        if isinstance(value, list):
            list_errors = {}
            for i in range(len(value)):
                validator = self.__class__({i: schema})
                validator.validate({i: value[i]})
                list_errors.update(validator.errors)
            if len(list_errors):
                self._error(field, list_errors)
        elif isinstance(value, dict):
            validator = self.__class__(schema)
            validator.validate(value)
            if len(validator.errors):
                self._error(field, validator.errors)
        else:
            self._error(field, errors.ERROR_BAD_TYPE % "dict or list")

    def _validate_items(self, items, field, value):
        if isinstance(items, dict):
            self._validate_items_schema(items, field, value)
        elif isinstance(items, list):
            self._validate_items_list(items, field, value)

    def _validate_items_list(self, schema, field, values):
        if len(schema) != len(values):
            self._error(field, errors.ERROR_ITEMS_LIST % len(schema))
        else:
            for i in range(len(schema)):
                validator = self.__class__({i: schema[i]})
                validator.validate({i: values[i]})
                self.errors.update(validator.errors)

    def _validate_items_schema(self, schema, field, value):
        validator = self.__class__(schema)
        for item in value:
            validator.validate(item)
            for field, error in validator.errors.items():
                self._error(field, error)
<|endoftext|>


<commit_before>"""
Provides a JSON API for common components.
"""

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import json
import hmac
import hashlib
import base64
from secrets import compare_digest

from django.utils.decorators import method_decorator
from django.urls import path
from django.views.decorators.csrf import csrf_exempt

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import PermissionDenied, NotFound, NotAcceptable

from .models import WebhookEndpoint

class CsrfExemptMixin(object):
    """
    Exempts the view from CSRF requirements.
    """

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(CsrfExemptMixin, self).dispatch(*args, **kwargs)

class VerificationMethod:
    NONE = 0
    TOKEN = 1
    HMAC = 2

class WebhookView(CsrfExemptMixin, APIView):
    """
    Endpoint for receiving webhoks.
    """
    authentication_classes = []
    permission_classes = []
    model_class = WebhookEndpoint

    # Token
    TOKEN_NAME = "Token"
    VERIFICATION_METHOD = VerificationMethod.NONE

    MESSAGE_OK = "Message was received."
    MESSAGE_TOKEN_ERROR = "Incorrect token in header."

    def post(self, request, endpoint, *args, **kwargs):
        self.init(request, *args, **kwargs)
        # get webhook definition
        self.get_webhook(endpoint, *args, **kwargs)

        # check headers
        headers = request.headers
        try:
            payload = json.loads(request.body)
        except json.decoder.JSONDecodeError as error:
            raise NotAcceptable(error.msg)

        # validate
        self.validate_token(payload, headers)
        # process data
        self.save_data(payload, headers, request)
        self.process_payload(payload, headers, request)

        # return results
        return_kwargs = self.get_result(payload, headers, request)
        return Response(**return_kwargs)

    # To be overridden
    def init(self, request, *args, **kwargs):
        self.token = ''
        self.secret = ''
        self.verify = self.VERIFICATION_METHOD

    def get_webhook(self, endpoint):
        try:
            webhook = self.model_class.objects.get(endpoint_id=endpoint)
            self.webhook = webhook
            return self.process_webhook()
        except self.model_class.DoesNotExist:
            raise NotFound()

    def process_webhook(self):
        if self.webhook.token:
            self.token = self.webhook.token
            self.verify = VerificationMethod.TOKEN
            # TODO make a object-setting
        if self.webhook.secret:
            self.secret = self.webhook.secret
            self.verify = VerificationMethod.HMAC
            # TODO make a object-setting
        return True

    def validate_token(self, payload, headers):
        token = headers.get(self.TOKEN_NAME, "")

        # no token
        if self.verify == VerificationMethod.NONE:
            pass

        # static token
        elif self.verify == VerificationMethod.TOKEN:
            if not compare_digest(token, self.token):
                raise PermissionDenied(self.MESSAGE_TOKEN_ERROR)

        # hmac token
        elif self.verify == VerificationMethod.HMAC:
            digest = hmac.new(self.secret, payload.encode('utf-8'), hashlib.sha256).digest()
            computed_hmac = base64.b64encode(digest)
            if not hmac.compare_digest(computed_hmac, token.encode('utf-8')):
                raise PermissionDenied(self.MESSAGE_TOKEN_ERROR)

        return True

    def save_data(self, payload, headers=None, request=None):
        # TODO safe data
        return

    def process_payload(self, payload, headers=None, request=None):
        return

    def get_result(self, payload, headers=None, request=None):
        context = {}
        context['data'] = {'message': self.MESSAGE_OK}
        context['status'] = 200
        return context

common_api_urls = [
    path('webhook/<slug:endpoint>/', WebhookView.as_view(), name='api-webhook'),
]
<commit_msg>fix hmac<commit_after>"""
Provides a JSON API for common components.
"""

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import json
import hmac
import hashlib
import base64
from secrets import compare_digest

from django.utils.decorators import method_decorator
from django.urls import path
from django.views.decorators.csrf import csrf_exempt

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import PermissionDenied, NotFound, NotAcceptable

from .models import WebhookEndpoint

class CsrfExemptMixin(object):
    """
    Exempts the view from CSRF requirements.
    """

    @method_decorator(csrf_exempt)
    def dispatch(self, *args, **kwargs):
        return super(CsrfExemptMixin, self).dispatch(*args, **kwargs)

class VerificationMethod:
    NONE = 0
    TOKEN = 1
    HMAC = 2

class WebhookView(CsrfExemptMixin, APIView):
    """
    Endpoint for receiving webhoks.
    """
    authentication_classes = []
    permission_classes = []
    model_class = WebhookEndpoint

    # Token
    TOKEN_NAME = "Token"
    VERIFICATION_METHOD = VerificationMethod.NONE

    MESSAGE_OK = "Message was received."
    MESSAGE_TOKEN_ERROR = "Incorrect token in header."

    def post(self, request, endpoint, *args, **kwargs):
        self.init(request, *args, **kwargs)
        # get webhook definition
        self.get_webhook(endpoint, *args, **kwargs)

        # check headers
        headers = request.headers
        try:
            payload = json.loads(request.body)
        except json.decoder.JSONDecodeError as error:
            raise NotAcceptable(error.msg)

        # validate
        self.validate_token(payload, headers, request)
        # process data
        self.save_data(payload, headers, request)
        self.process_payload(payload, headers, request)

        # return results
        return_kwargs = self.get_result(payload, headers, request)
        return Response(**return_kwargs)

    # To be overridden
    def init(self, request, *args, **kwargs):
        self.token = ''
        self.secret = ''
        self.verify = self.VERIFICATION_METHOD

    def get_webhook(self, endpoint):
        try:
            webhook = self.model_class.objects.get(endpoint_id=endpoint)
            self.webhook = webhook
            return self.process_webhook()
        except self.model_class.DoesNotExist:
            raise NotFound()

    def process_webhook(self):
        if self.webhook.token:
            self.token = self.webhook.token
            self.verify = VerificationMethod.TOKEN
            # TODO make a object-setting
        if self.webhook.secret:
            self.secret = self.webhook.secret
            self.verify = VerificationMethod.HMAC
            # TODO make a object-setting
        return True

    def validate_token(self, payload, headers, request):
        token = headers.get(self.TOKEN_NAME, "")

        # no token
        if self.verify == VerificationMethod.NONE:
            pass

        # static token
        elif self.verify == VerificationMethod.TOKEN:
            if not compare_digest(token, self.token):
                raise PermissionDenied(self.MESSAGE_TOKEN_ERROR)

        # hmac token
        elif self.verify == VerificationMethod.HMAC:
            digest = hmac.new(self.secret.encode('utf-8'), request.body, hashlib.sha256).digest()
            computed_hmac = base64.b64encode(digest)
            if not hmac.compare_digest(computed_hmac, token.encode('utf-8')):
                raise PermissionDenied(self.MESSAGE_TOKEN_ERROR)

        return True

    def save_data(self, payload, headers=None, request=None):
        # TODO safe data
        return

    def process_payload(self, payload, headers=None, request=None):
        return

    def get_result(self, payload, headers=None, request=None):
        context = {}
        context['data'] = {'message': self.MESSAGE_OK}
        context['status'] = 200
        return context

common_api_urls = [
    path('webhook/<slug:endpoint>/', WebhookView.as_view(), name='api-webhook'),
]
<|endoftext|>


<commit_before>import datetime
import pytz
from django.conf import settings
from salesforce import models, models_extend

tzinfo = pytz.utc if settings.USE_TZ else None

def now_aware_or_naive():
    if settings.USE_TZ:
        return pytz.utc.localize(datetime.datetime.utcnow())
    return datetime.datetime.utcnow()

class Account(models_extend.SalesforceModel):
    name = models.CharField(max_length=255)

class Contact(models_extend.SalesforceModel):
    last_name = models.CharField(max_length=80)
    first_name = models.CharField(max_length=40, blank=True)
    account = models.ForeignKey(Account, on_delete=models.DO_NOTHING)

    class Meta:
        db_table = 'Contact'

def get_default_account() -> Account:
    return Account.objects.order_by('pk')[0]

class TryDefaults(models.SalesforceModel):
    # this model doesn't exist in Salesforce, but it should be valid
    # it is only for coverage of code by tests
    example_str = models.CharField(default=models.DefaultedOnCreate('client'), max_length=50)
    example_bool = models.BooleanField(default=models.DefaultedOnCreate(True), db_column='ExampleBool__c')
    example_bool_2 = models.BooleanField(db_column='ExampleBool2__c', default=models.DefaultedOnCreate(False))
    example_bool_3 = models.BooleanField(db_column='ExampleBool3__c', default=models.DEFAULTED_ON_CREATE)
    example_datetime = models.DateTimeField(default=models.DefaultedOnCreate(now_aware_or_naive),
                                            db_column='ExampleDatetime__c')
    example_datetime_2 = models.DateTimeField(
        default=models.DefaultedOnCreate(datetime.datetime(2021, 3, 31, 23, 59)))
    example_date = models.DateField(default=datetime.date.today)
    example_date_2 = models.DateField(default=models.DefaultedOnCreate(datetime.date(2021, 3, 31)))
    example_foreign_key = models.ForeignKey(Account, on_delete=models.DO_NOTHING,
                                            default=models.DefaultedOnCreate(get_default_account))
    example_time = models.TimeField(default=models.DefaultedOnCreate(datetime.time(23, 59)))
<commit_msg>Fix test USE_TZ=False #221<commit_after>import datetime
import pytz
from django.conf import settings
from salesforce import models, models_extend

tzinfo = pytz.utc if settings.USE_TZ else None

def now_aware_or_naive():
    if settings.USE_TZ:
        return pytz.utc.localize(datetime.datetime.utcnow())
    return datetime.datetime.utcnow()

class Account(models_extend.SalesforceModel):
    name = models.CharField(max_length=255)

class Contact(models_extend.SalesforceModel):
    last_name = models.CharField(max_length=80)
    first_name = models.CharField(max_length=40, blank=True)
    account = models.ForeignKey(Account, on_delete=models.DO_NOTHING)

    class Meta:
        db_table = 'Contact'

def get_default_account() -> Account:
    return Account.objects.order_by('pk')[0]

class TryDefaults(models.SalesforceModel):
    # this model doesn't exist in Salesforce, but it should be valid
    # it is only for coverage of code by tests
    example_str = models.CharField(default=models.DefaultedOnCreate('client'), max_length=50)
    example_bool = models.BooleanField(default=models.DefaultedOnCreate(True), db_column='ExampleBool__c')
    example_bool_2 = models.BooleanField(db_column='ExampleBool2__c', default=models.DefaultedOnCreate(False))
    example_bool_3 = models.BooleanField(db_column='ExampleBool3__c', default=models.DEFAULTED_ON_CREATE)
    example_datetime = models.DateTimeField(default=models.DefaultedOnCreate(now_aware_or_naive),
                                            db_column='ExampleDatetime__c')
    example_datetime_2 = models.DateTimeField(
        default=models.DefaultedOnCreate(datetime.datetime(2021, 3, 31, 23, 59, tzinfo=tzinfo)))
    example_date = models.DateField(default=datetime.date.today)
    example_date_2 = models.DateField(default=models.DefaultedOnCreate(datetime.date(2021, 3, 31)))
    example_foreign_key = models.ForeignKey(Account, on_delete=models.DO_NOTHING,
                                            default=models.DefaultedOnCreate(get_default_account))
    example_time = models.TimeField(default=models.DefaultedOnCreate(datetime.time(23, 59)))
<|endoftext|>


<commit_before>#
# Copyright (c) 2006 rPath, Inc.
#
# All Rights Reserved
#
"""A handful of functions useful inside kid templates."""

import time
from mint import userlevels

def downloadTracker(cfg, url):
    if cfg.googleAnalyticsTracker:
        return {"onclick": "javascript:urchinTracker('%s');" % url}
    else:
        return {}

def injectVersion(version):
    parts = version.split('/')
    parts[-1] = str(time.time()) + ':' + parts[-1]
    return '/'.join(parts)

def isRMakeLegal(rMakeBuild, userLevel, trove):
    """Returns True if 'trove' is legal to add to an rMake build."""
    return rMakeBuild and not rMakeBuild.status and userLevel in userlevels.WRITERS and ':' not in trove.getName()

def isGroupBuilderLegal(groupTrove, trove):
    """Returns True if 'trove' is legal to add to a group builder project."""
    return groupTrove and not groupTrove.troveInGroup(trove.getName())
<commit_msg>tweak rMakeBuild legality logic. tweak name collision with trove module<commit_after>#
# Copyright (c) 2006 rPath, Inc.
#
# All Rights Reserved
#
"""A handful of functions useful inside kid templates."""

import time
from mint import userlevels

def downloadTracker(cfg, url):
    if cfg.googleAnalyticsTracker:
        return {"onclick": "javascript:urchinTracker('%s');" % url}
    else:
        return {}

def injectVersion(version):
    parts = version.split('/')
    parts[-1] = str(time.time()) + ':' + parts[-1]
    return '/'.join(parts)

def isRMakeLegal(rMakeBuild, userLevel, trv):
    """Returns True if 'trv' is legal to add to an rMake build."""
    return rMakeBuild and not rMakeBuild.status and userLevel in userlevels.WRITERS and (':' not in trv.getName() or trv.getName().endswith(':source'))

def isGroupBuilderLegal(groupTrove, trv):
    """Returns True if 'trv' is legal to add to a group builder project."""
    return groupTrove and not groupTrove.troveInGroup(trv.getName())
<|endoftext|>


<commit_before>import torch
from torch import Tensor
from torch import nn
from typing import Union, Tuple, List, Iterable, Dict
import os
import json

class Pooling(nn.Module):
    """Performs pooling (max or mean) on the token embeddings.

    Using pooling, it generates from a variable sized sentence a fixed sized sentence embedding. This layer also allows to use the CLS token if it is returned by the underlying word embedding model.
    You can concatenate multiple poolings together.

    :param word_embedding_dimension: Dimensions for the word embeddings
    :param pooling_mode_cls_token: Use the first token (CLS token) as text representations
    :param pooling_mode_max_tokens: Use max in each dimension over all tokens.
    :param pooling_mode_mean_tokens: Perform mean-pooling
    :param pooling_mode_mean_sqrt_len_tokens: Perform mean-pooling, but devide by sqrt(input_length).
    """
    def __init__(self,
                 word_embedding_dimension: int,
                 pooling_mode_cls_token: bool = False,
                 pooling_mode_max_tokens: bool = False,
                 pooling_mode_mean_tokens: bool = True,
                 pooling_mode_mean_sqrt_len_tokens: bool = False,
                 ):
        super(Pooling, self).__init__()

        self.config_keys = ['word_embedding_dimension',  'pooling_mode_cls_token', 'pooling_mode_mean_tokens', 'pooling_mode_max_tokens', 'pooling_mode_mean_sqrt_len_tokens']

        self.word_embedding_dimension = word_embedding_dimension
        self.pooling_mode_cls_token = pooling_mode_cls_token
        self.pooling_mode_mean_tokens = pooling_mode_mean_tokens
        self.pooling_mode_max_tokens = pooling_mode_max_tokens
        self.pooling_mode_mean_sqrt_len_tokens = pooling_mode_mean_sqrt_len_tokens

        pooling_mode_multiplier = sum([pooling_mode_cls_token, pooling_mode_max_tokens, pooling_mode_mean_tokens, pooling_mode_mean_sqrt_len_tokens])
        self.pooling_output_dimension = (pooling_mode_multiplier * word_embedding_dimension)

    def forward(self, features: Dict[str, Tensor]):
        token_embeddings = features['token_embeddings']
        cls_token = features['cls_token_embeddings']
        attention_mask = features['attention_mask']

        ## Pooling strategy
        output_vectors = []
        if self.pooling_mode_cls_token:
            output_vectors.append(cls_token)
        if self.pooling_mode_max_tokens:
            input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
            token_embeddings[input_mask_expanded == 0] = -1e9  # Set padding tokens to large negative value
            max_over_time = torch.max(token_embeddings, 1)[0]
            output_vectors.append(max_over_time)
        if self.pooling_mode_mean_tokens or self.pooling_mode_mean_sqrt_len_tokens:
            input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
            sum_embeddings = torch.sum(token_embeddings * input_mask_expanded, 1)

            #If tokens are weighted (by WordWeights layer), feature 'token_weights_sum' will be present
            if 'token_weights_sum' in features:
                sum_mask = features['token_weights_sum'].unsqueeze(-1).expand(sum_embeddings.size())
            else:
                sum_mask = input_mask_expanded.sum(1)

            sum_mask = torch.clamp(sum_mask, min=1e-9)

            if self.pooling_mode_mean_tokens:
                output_vectors.append(sum_embeddings / sum_mask)
            if self.pooling_mode_mean_sqrt_len_tokens:
                output_vectors.append(sum_embeddings / torch.sqrt(sum_mask))

        output_vector = torch.cat(output_vectors, 1)
        features.update({'sentence_embedding': output_vector})
        return features

    def get_sentence_embedding_dimension(self):
        return self.pooling_output_dimension

    def get_config_dict(self):
        return {key: self.__dict__[key] for key in self.config_keys}

    def save(self, output_path):
        with open(os.path.join(output_path, 'config.json'), 'w') as fOut:
            json.dump(self.get_config_dict(), fOut, indent=2)

    @staticmethod
    def load(input_path):
        with open(os.path.join(input_path, 'config.json')) as fIn:
            config = json.load(fIn)

        return Pooling(**config)
<commit_msg>add string option to pooling layer<commit_after>import torch
from torch import Tensor
from torch import nn
from typing import Union, Tuple, List, Iterable, Dict
import os
import json

class Pooling(nn.Module):
    """Performs pooling (max or mean) on the token embeddings.

    Using pooling, it generates from a variable sized sentence a fixed sized sentence embedding. This layer also allows to use the CLS token if it is returned by the underlying word embedding model.
    You can concatenate multiple poolings together.

    :param word_embedding_dimension: Dimensions for the word embeddings
    :param pooling_mode: Can be a string: mean/max/cls. If set, overwrites the other pooling_mode_* settings
    :param pooling_mode_cls_token: Use the first token (CLS token) as text representations
    :param pooling_mode_max_tokens: Use max in each dimension over all tokens.
    :param pooling_mode_mean_tokens: Perform mean-pooling
    :param pooling_mode_mean_sqrt_len_tokens: Perform mean-pooling, but devide by sqrt(input_length).
    """
    def __init__(self,
                 word_embedding_dimension: int,
                 pooling_mode: str = None,
                 pooling_mode_cls_token: bool = False,
                 pooling_mode_max_tokens: bool = False,
                 pooling_mode_mean_tokens: bool = True,
                 pooling_mode_mean_sqrt_len_tokens: bool = False,
                 ):
        super(Pooling, self).__init__()

        self.config_keys = ['word_embedding_dimension',  'pooling_mode_cls_token', 'pooling_mode_mean_tokens', 'pooling_mode_max_tokens', 'pooling_mode_mean_sqrt_len_tokens']

        if pooling_mode is not None:        #Set pooling mode by string
            pooling_mode = pooling_mode.lower()
            assert pooling_mode in ['mean', 'max', 'cls']
            pooling_mode_cls_token = (pooling_mode == 'cls')
            pooling_mode_max_tokens = (pooling_mode == 'max')
            pooling_mode_mean_tokens = (pooling_mode == 'mean')

        self.word_embedding_dimension = word_embedding_dimension
        self.pooling_mode_cls_token = pooling_mode_cls_token
        self.pooling_mode_mean_tokens = pooling_mode_mean_tokens
        self.pooling_mode_max_tokens = pooling_mode_max_tokens
        self.pooling_mode_mean_sqrt_len_tokens = pooling_mode_mean_sqrt_len_tokens

        pooling_mode_multiplier = sum([pooling_mode_cls_token, pooling_mode_max_tokens, pooling_mode_mean_tokens, pooling_mode_mean_sqrt_len_tokens])
        self.pooling_output_dimension = (pooling_mode_multiplier * word_embedding_dimension)

    def forward(self, features: Dict[str, Tensor]):
        token_embeddings = features['token_embeddings']
        cls_token = features['cls_token_embeddings']
        attention_mask = features['attention_mask']

        ## Pooling strategy
        output_vectors = []
        if self.pooling_mode_cls_token:
            output_vectors.append(cls_token)
        if self.pooling_mode_max_tokens:
            input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
            token_embeddings[input_mask_expanded == 0] = -1e9  # Set padding tokens to large negative value
            max_over_time = torch.max(token_embeddings, 1)[0]
            output_vectors.append(max_over_time)
        if self.pooling_mode_mean_tokens or self.pooling_mode_mean_sqrt_len_tokens:
            input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
            sum_embeddings = torch.sum(token_embeddings * input_mask_expanded, 1)

            #If tokens are weighted (by WordWeights layer), feature 'token_weights_sum' will be present
            if 'token_weights_sum' in features:
                sum_mask = features['token_weights_sum'].unsqueeze(-1).expand(sum_embeddings.size())
            else:
                sum_mask = input_mask_expanded.sum(1)

            sum_mask = torch.clamp(sum_mask, min=1e-9)

            if self.pooling_mode_mean_tokens:
                output_vectors.append(sum_embeddings / sum_mask)
            if self.pooling_mode_mean_sqrt_len_tokens:
                output_vectors.append(sum_embeddings / torch.sqrt(sum_mask))

        output_vector = torch.cat(output_vectors, 1)
        features.update({'sentence_embedding': output_vector})
        return features

    def get_sentence_embedding_dimension(self):
        return self.pooling_output_dimension

    def get_config_dict(self):
        return {key: self.__dict__[key] for key in self.config_keys}

    def save(self, output_path):
        with open(os.path.join(output_path, 'config.json'), 'w') as fOut:
            json.dump(self.get_config_dict(), fOut, indent=2)

    @staticmethod
    def load(input_path):
        with open(os.path.join(input_path, 'config.json')) as fIn:
            config = json.load(fIn)

        return Pooling(**config)
<|endoftext|>


<commit_before># this only exists for the docs and is not really used

class Client(object):

    def __init__(self, *args, **kwargs):
        raise AssertionError("this class %s should never be called" % self.__class__)<commit_msg>forgot to remove awapi<commit_after><|endoftext|>


<commit_before>
# coding=UTF8
"""Annotate.io demo to show how we learn a transformation sequence for data cleaning"""
from __future__ import print_function, unicode_literals
import requests
import json

# Tested on:
# Python 3.4, 2.7 (the unicode examples work but looks a bit odd when
# printed on 2.7)

# To learn more go to: http://annotate.io

root_url = "http://api.annotate.io"  # API URL

# show the docstring for this module as a bit of help for the user
print(__doc__)

# call / with a GET and confirm a 200 'OK' status code to confirm that the
# site it running
resp = requests.get(root_url)
assert resp.status_code == 200, "If we don't get a 200 OK then maybe the server is down?"

# Use a POST to call /learn with examples of
# the desired inputs and outputs
root_url = root_url
query = {'inputs': ["To 53K w/benefits",
                    "30000 OTE plus bonus",
                    "£55000 salary",
                    "Forty two thousand GBP"],
         'outputs': ["53000",
                     "30000",
                     "55000",
                     "42000"]}
print()
print("Training phase - we use `inputs` to learn a transformation to get to the desired `outputs`:")
print("inputs:", query['inputs'])
print("outputs:", query['outputs'])
print("Calling Annotate.io...")
resp = requests.post(root_url + "/learn",
                     data=json.dumps(query),
                     headers={'Content-Type': 'application/json'})
assert resp.status_code == 200

# store the code that we're sent
transforms = resp.json()['transforms']
print("Training phase complete, now we have a `transforms` code")

# Use a POST to call /transform with the code
# and new inputs, we'll receive outputs back
query = {'inputs': [
                    "90k",
                    "120,000 + bonus",
                    "Seventy thousand"
                    ],
         'transforms': transforms}
print()
print("Data cleaning phase - we use the `transforms` that we've learned on previously unseen `inputs` items to generate new `outputs`:")
print("inputs:", query['inputs'])

resp = requests.post(root_url + "/transform",
                     data=json.dumps(query),
                     headers={'Content-Type': 'application/json'})
assert resp.status_code == 200
result = resp.json()
print("We now have a transformed result:")
print("outputs:", result['outputs'])

print("\nPretty printed:")
print("{inp:>30}    {out:>30}".format(
    inp="Previously unseen input:", out="Annotate's output:"))
for (inp, out) in zip(query['inputs'], result['outputs']):
    print("{inp:>30} -> {out:>30}".format(inp=inp, out=out))
<commit_msg>more training data<commit_after>
# coding=UTF8
"""Annotate.io demo to show how we learn a transformation sequence for data cleaning"""
from __future__ import print_function, unicode_literals
import requests
import json

# Tested on:
# Python 3.4, 2.7 (the unicode examples work but looks a bit odd when
# printed on 2.7)

# To learn more go to: http://annotate.io

root_url = "http://api.annotate.io"  # API URL

# show the docstring for this module as a bit of help for the user
print(__doc__)

# call / with a GET and confirm a 200 'OK' status code to confirm that the
# site it running
resp = requests.get(root_url)
assert resp.status_code == 200, "If we don't get a 200 OK then maybe the server is down?"

training_inputs = [
    "To 53K w/benefits",
    "25k",
    "30000 OTE plus bonus",
    "£55000 salary",
    "£90,000 salary",
    "Forty two thousand GBP"
]

training_outputs = [
    "53000",
    "25000",
    "30000",
    "55000",
    "90000",
    "42000"
]

# Use a POST to call /learn with examples of
# the desired inputs and outputs
root_url = root_url
query = {'inputs': training_inputs,
         'outputs': training_outputs}
print()
print("Training phase - we use `inputs` to learn a transformation to get to the desired `outputs`:")
print("inputs:", query['inputs'])
print("outputs:", query['outputs'])
print("Calling Annotate.io...")
resp = requests.post(root_url + "/learn",
                     data=json.dumps(query),
                     headers={'Content-Type': 'application/json'})
assert resp.status_code == 200

# store the code that we're sent
transforms = resp.json()['transforms']
print("Training phase complete, now we have a `transforms` code")

# Use a POST to call /transform with the code
# and new inputs, we'll receive outputs back
query = {'inputs': [
                    "90k",
                    "120,000 + bonus",
                    "Seventy thousand"
                    ],
         'transforms': transforms}
print()
print("Data cleaning phase - we use the `transforms` that we've learned on previously unseen `inputs` items to generate new `outputs`:")
print("inputs:", query['inputs'])

resp = requests.post(root_url + "/transform",
                     data=json.dumps(query),
                     headers={'Content-Type': 'application/json'})
assert resp.status_code == 200
result = resp.json()
print("We now have a transformed result:")
print("outputs:", result['outputs'])

print("\nPretty printed:")
print("{inp:>30}    {out:>30}".format(
    inp="Previously unseen input:", out="Annotate's output:"))
for (inp, out) in zip(query['inputs'], result['outputs']):
    print("{inp:>30} -> {out:>30}".format(inp=inp, out=out))
<|endoftext|>


<commit_before># This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import random
import socket
from furl import furl

import requests
from requests import RequestException

from flask import current_app
from relengapi.lib.celery import task
from relengapi.blueprints.slaveloan import slave_mappings
from relengapi.blueprints.slaveloan.model import Machines, Humans, Loans, History
from redo import retry
import datetime

@task()
def init_loan(loanid, loan_class):
    print "Init Loan2", datetime.datetime.utcnow().isoformat(sep=" ")
    print "Loan Class = %s" % loan_class
    if slave_mappings.is_aws_serviceable(loan_class):
        print "aws host"
        # do_aws_loan.delay()
    else:
        print "physical host: %s" % loan_class
        choose_inhouse_machine.delay(loanid, loan_class)

@task(bind=True)
def choose_inhouse_machine(self, loanid, loan_class):
    print "Choosing inhouse machine"
    url = furl("http://slavealloc.pvt.build.mozilla.org/api/slaves")
    url.args["enabled"] = 1
    try:
        all_slaves = requests.get(str(url)).json()
    except RequestException as exc:
        print "Exception"
        self.retry(exc=exc)
    print "Got all slaves"
    # pylint silence
    # available_slaves = filter(slave_mappings.slave_filter(loan_class), all_slaves)
    available_slaves = [slave for slave in all_slaves
                        if slave_mappings.slave_filter(loan_class)(slave)]
    chosen = random.choice(available_slaves)
    print "Chosen Slave = %s" % chosen
    fixup_machine.delay(loanid, chosen['name'])
    start_disable_slave.delay(loanid, chosen['name'])

@task(bind=True, max_retries=None)
def fixup_machine(self, loanid, machine):
    try:
        print "FIXUP MACHINE"
        fqdn = socket.getfqdn("%s.build.mozilla.org" % machine)
        print "FIXUP MACHINE = hostname: %s" % fqdn
        ipaddr = socket.gethostbyname("%s.build.mozilla.org" % machine)
        print "FIXUP MACHINE = ipaddr: %s" % ipaddr
        session = current_app.db.session('relengapi')
        m = Machines.as_unique(session,
                               fqdn=fqdn,
                               ipaddr=ipaddr)
        print "FIXUP MACHINE = machine.to_json(): %s" % m.to_json()
        l = session.query(Loans).get(loanid)
        print "FIXUP MACHINE = loan.to_json(): %s" % l.to_json()
        l.machine = m
        session.commit()
        l = session.query(Loans).get(loanid)
        print "FIXUP MACHINE = loan.to_json(): %s" % l.to_json()
    except Exception as exc:  # pylint: disable=W0703
        print "FIXUP MACHINE (FAILED)"
        print exc
        self.retry(exc=exc)

@task(bind=True, max_retries=None)
def start_disable_slave(self, loanid, machine):
    try:
        print "START DISABLE SLAVE"
        slaveapi = "http://slaveapi-dev1.build.mozilla.org:8080/slaves/"
        url = furl(slaveapi)
        url.path.add(machine).add("actions").add("disable")
        print "START DISABLE SLAVE = url: %s" % str(url)
        postdata = dict(reason="Being loaned on slaveloan %s" % loanid)
        r = retry(requests.post, args=(str(url),), kwargs=dict(data=postdata)).json()
        print "START DISABLE SLAVE = r: %s" % str(r)
        raise
    except Exception as exc:  # pylint: disable=W0703
        self.retry(exc=exc)

if __name__ == "__main__":
    temporary_silence_pylint = History
    temporary_silence_pylint = Humans
<commit_msg>Add Basic Task History (still includes debug info)<commit_after># This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import random
import socket
from furl import furl

import requests
from requests import RequestException

from flask import current_app
from relengapi.lib.celery import task
from relengapi.blueprints.slaveloan import slave_mappings
from relengapi.blueprints.slaveloan.model import Machines, Humans, Loans, History
from redo import retry
import datetime
from functools import wraps
from relengapi.util import tz

from celery import signals
import celery

def add_task_to_history(loanid, msg):
    session = current_app.db.session('relengapi')
    l = session.query(Loans).get(loanid)
    history = History(for_loan=l,
                      timestamp=tz.utcnow(),
                      msg=msg)
    session.add(history)
    session.commit()
    print "DEBUG:", repr(l.to_json())
    print "DEBUG:", repr(history.to_json())
    print "DEBUG: Log_line: %s" % msg

def add_to_history(before=None, after=None):
    def decorator(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            bound_task = None
            loanid = None
            if isinstance(args[0], celery.Task):
                bound_task = args[0]
                loanid = args[1]
            else:
                loanid = args[0]
            if before:
                print "DEBUG: Locals: %s" % repr(locals())
                print "DEBUG: Log_line: %s" % before.format(**locals())
                add_task_to_history(loanid, before.format(**locals()))
            retval = f(*args, **kwargs)
            if after:
                print "DEBUG: Locals: %s" % repr(locals())
                print "DEBUG: AFTER: Log_line: %s" % after.format(**locals())
                add_task_to_history(loanid, after.format(**locals()))
            return retval
        return wrapper
    return decorator

@task()
@add_to_history(
    before="Initialising Loan for slaveclass {args[1]!s}",
    after="Initialising Loan Process Complete for slaveclass {args[1]!s}, using flow {retval!s}")
def init_loan(loanid, loan_class):
    print "Init Loan2", datetime.datetime.utcnow().isoformat(sep=" ")
    print "Loan Class = %s" % loan_class
    if slave_mappings.is_aws_serviceable(loan_class):
        print "aws host"
        # do_aws_loan.delay()
        return "AWS"
    else:
        print "physical host: %s" % loan_class
        choose_inhouse_machine.delay(loanid, loan_class)
        return "inhouse"

@task(bind=True)
@add_to_history(
    before="Choosing an inhouse machine based on slavealloc",
    after="Chose inhouse machine {retval!s}")
def choose_inhouse_machine(self, loanid, loan_class):
    print "Choosing inhouse machine"
    url = furl("http://slavealloc.pvt.build.mozilla.org/api/slaves")
    url.args["enabled"] = 1
    try:
        all_slaves = requests.get(str(url)).json()
    except RequestException as exc:
        print "Exception"
        self.retry(exc=exc)
    print "Got all slaves"
    # pylint silence
    # available_slaves = filter(slave_mappings.slave_filter(loan_class), all_slaves)
    available_slaves = [slave for slave in all_slaves
                        if slave_mappings.slave_filter(loan_class)(slave)]
    chosen = random.choice(available_slaves)
    print "Chosen Slave = %s" % chosen
    fixup_machine.delay(loanid, chosen['name'])
    start_disable_slave.delay(loanid, chosen['name'])
    return chosen['name']

@task(bind=True, max_retries=None)
@add_to_history(
    before="Identifying FQDN and IP of {args[2]}",
    after="Aquired FQDN and IP")
def fixup_machine(self, loanid, machine):
    try:
        print "FIXUP MACHINE"
        fqdn = socket.getfqdn("%s.build.mozilla.org" % machine)
        print "FIXUP MACHINE = hostname: %s" % fqdn
        ipaddr = socket.gethostbyname("%s.build.mozilla.org" % machine)
        print "FIXUP MACHINE = ipaddr: %s" % ipaddr
        session = current_app.db.session('relengapi')
        m = Machines.as_unique(session,
                               fqdn=fqdn,
                               ipaddr=ipaddr)
        print "FIXUP MACHINE = machine.to_json(): %s" % m.to_json()
        l = session.query(Loans).get(loanid)
        print "FIXUP MACHINE = loan.to_json(): %s" % l.to_json()
        l.machine = m
        session.commit()
        l = session.query(Loans).get(loanid)
        print "FIXUP MACHINE = loan.to_json(): %s" % l.to_json()
    except Exception as exc:  # pylint: disable=W0703
        print "FIXUP MACHINE (FAILED)"
        print exc
        self.retry(exc=exc)

@task(bind=True, max_retries=None)
@add_to_history(
    before="Calling slaveapi's disable method",
    after="Disable request sent")
def start_disable_slave(self, loanid, machine):
    try:
        print "START DISABLE SLAVE"
        slaveapi = "http://slaveapi-dev1.build.mozilla.org:8080/slaves/"
        url = furl(slaveapi)
        url.path.add(machine).add("actions").add("disable")
        print "START DISABLE SLAVE = url: %s" % str(url)
        postdata = dict(reason="Being loaned on slaveloan %s" % loanid)
        r = retry(requests.post, args=(str(url),), kwargs=dict(data=postdata)).json()
        print "START DISABLE SLAVE = r: %s" % str(r)
        raise
    except Exception as exc:  # pylint: disable=W0703
        self.retry(exc=exc)

if __name__ == "__main__":
    temporary_silence_pylint = History
    temporary_silence_pylint = Humans
<|endoftext|>


<commit_before>"""
Django Forms for interacting with Part objects
"""

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from InvenTree.forms import HelperForm

from django import forms

from .models import Part, PartCategory, PartAttachment
from .models import BomItem
from .models import PartParameterTemplate, PartParameter

class PartImageForm(HelperForm):
    """ Form for uploading a Part image """

    class Meta:
        model = Part
        fields = [
            'image',
        ]

class BomValidateForm(HelperForm):
    """ Simple confirmation form for BOM validation.
    User is presented with a single checkbox input,
    to confirm that the BOM for this part is valid
    """

    validate = forms.BooleanField(required=False, initial=False, help_text='Confirm that the BOM is correct')

    class Meta:
        model = Part
        fields = [
            'validate'
        ]

class BomUploadSelectFile(HelperForm):
    """ Form for importing a BOM. Provides a file input box for upload """

    bom_file = forms.FileField(label='BOM file', required=True, help_text="Select BOM file to upload")

    class Meta:
        model = Part
        fields = [
            'bom_file',
        ]

class EditPartAttachmentForm(HelperForm):
    """ Form for editing a PartAttachment object """

    class Meta:
        model = PartAttachment
        fields = [
            'part',
            'attachment',
            'comment'
        ]

class EditPartForm(HelperForm):
    """ Form for editing a Part object """

    deep_copy = forms.BooleanField(required=False,
                                   initial=True,
                                   help_text="Perform 'deep copy' which will duplicate all BOM data for this part",
                                   widget=forms.HiddenInput())

    confirm_creation = forms.BooleanField(required=False,
                                          initial=False,
                                          help_text='Confirm part creation',
                                          widget=forms.HiddenInput())

    class Meta:
        model = Part
        fields = [
            'deep_copy',
            'confirm_creation',
            'category',
            'name',
            'IPN',
            'description',
            'revision',
            'keywords',
            'variant_of',
            'is_template',
            'URL',
            'default_location',
            'default_supplier',
            'units',
            'minimum_stock',
            'notes',
            'active',
        ]

class EditPartParameterTemplateForm(HelperForm):
    """ Form for editing a PartParameterTemplate object """

    class Meta:
        model = PartParameterTemplate
        fields = [
            'name',
            'units'
        ]

class EditPartParameterForm(HelperForm):
    """ Form for editing a PartParameter object """

    class Meta:
        model = PartParameter
        fields = [
            'part',
            'template',
            'data'
        ]

class EditCategoryForm(HelperForm):
    """ Form for editing a PartCategory object """

    class Meta:
        model = PartCategory
        fields = [
            'parent',
            'name',
            'description',
            'default_location',
            'default_keywords',
        ]

class EditBomItemForm(HelperForm):
    """ Form for editing a BomItem object """

    class Meta:
        model = BomItem
        fields = [
            'part',
            'sub_part',
            'quantity',
            'reference',
            'overage',
            'note'
        ]

        # Prevent editing of the part associated with this BomItem
        widgets = {'part': forms.HiddenInput()}

class PartPriceForm(forms.Form):
    """ Simple form for viewing part pricing information """

    quantity = forms.IntegerField(
        required=True,
        initial=1,
        help_text='Input quantity for price calculation'
    )

    class Meta:
        model = Part
        fields = [
            'quantity'
        ]
<commit_msg>Add currency selection field for price calculation form<commit_after>"""
Django Forms for interacting with Part objects
"""

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from InvenTree.forms import HelperForm

from django import forms
from django.utils.translation import ugettext as _

from .models import Part, PartCategory, PartAttachment
from .models import BomItem
from .models import PartParameterTemplate, PartParameter

from common.models import Currency

class PartImageForm(HelperForm):
    """ Form for uploading a Part image """

    class Meta:
        model = Part
        fields = [
            'image',
        ]

class BomValidateForm(HelperForm):
    """ Simple confirmation form for BOM validation.
    User is presented with a single checkbox input,
    to confirm that the BOM for this part is valid
    """

    validate = forms.BooleanField(required=False, initial=False, help_text=_('Confirm that the BOM is correct'))

    class Meta:
        model = Part
        fields = [
            'validate'
        ]

class BomUploadSelectFile(HelperForm):
    """ Form for importing a BOM. Provides a file input box for upload """

    bom_file = forms.FileField(label='BOM file', required=True, help_text=_("Select BOM file to upload"))

    class Meta:
        model = Part
        fields = [
            'bom_file',
        ]

class EditPartAttachmentForm(HelperForm):
    """ Form for editing a PartAttachment object """

    class Meta:
        model = PartAttachment
        fields = [
            'part',
            'attachment',
            'comment'
        ]

class EditPartForm(HelperForm):
    """ Form for editing a Part object """

    deep_copy = forms.BooleanField(required=False,
                                   initial=True,
                                   help_text=_("Perform 'deep copy' which will duplicate all BOM data for this part"),
                                   widget=forms.HiddenInput())

    confirm_creation = forms.BooleanField(required=False,
                                          initial=False,
                                          help_text=_('Confirm part creation'),
                                          widget=forms.HiddenInput())

    class Meta:
        model = Part
        fields = [
            'deep_copy',
            'confirm_creation',
            'category',
            'name',
            'IPN',
            'description',
            'revision',
            'keywords',
            'variant_of',
            'is_template',
            'URL',
            'default_location',
            'default_supplier',
            'units',
            'minimum_stock',
            'notes',
            'active',
        ]

class EditPartParameterTemplateForm(HelperForm):
    """ Form for editing a PartParameterTemplate object """

    class Meta:
        model = PartParameterTemplate
        fields = [
            'name',
            'units'
        ]

class EditPartParameterForm(HelperForm):
    """ Form for editing a PartParameter object """

    class Meta:
        model = PartParameter
        fields = [
            'part',
            'template',
            'data'
        ]

class EditCategoryForm(HelperForm):
    """ Form for editing a PartCategory object """

    class Meta:
        model = PartCategory
        fields = [
            'parent',
            'name',
            'description',
            'default_location',
            'default_keywords',
        ]

class EditBomItemForm(HelperForm):
    """ Form for editing a BomItem object """

    class Meta:
        model = BomItem
        fields = [
            'part',
            'sub_part',
            'quantity',
            'reference',
            'overage',
            'note'
        ]

        # Prevent editing of the part associated with this BomItem
        widgets = {'part': forms.HiddenInput()}

class PartPriceForm(forms.Form):
    """ Simple form for viewing part pricing information """

    quantity = forms.IntegerField(
        required=True,
        initial=1,
        help_text=_('Input quantity for price calculation')
    )

    currency = forms.ChoiceField(label='Currency', help_text=_('Select currency for price calculation'))

    def get_currency_choices(self):
        """ Create options for Currency """

        currencies = Currency.objects.all()
        choices = [(None, '---------')]

        for c in currencies:
            choices.append((c.pk, str(c)))

        return choices

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['currency'].choices = self.get_currency_choices()

    class Meta:
        model = Part
        fields = [
            'quantity',
            'currency',
        ]
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
###############################################################################
#
#    Copyright (C) 2001-2014 Micronaet SRL (<http://www.micronaet.it>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import os
import sys
import logging
import openerp
import openerp.netsvc as netsvc
import openerp.addons.decimal_precision as dp
from openerp.osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID, api
from openerp import tools
from openerp.tools.translate import _
from openerp.tools.float_utils import float_round as round
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class ProductProductStartHistory(orm.Model):
    """ Model name: ProductProductStartHistory
    """

    _name = 'product.product.start.history'
    _description = 'Start history'
    _rec_name = 'product_id'

    def history_start_elements(self, cr, uid, mx_start_date=False,
            context=None):
        ''' Save current history
        '''
        if not mx_start_date:
            _logger.error('Cannoy history without start date!')
            return True

        # Remove previous history values:
        product_pool = self.pool.get('product.product')
        product_ids = product_pool.search(cr, uid, [
            ('mx_start_date', '=', mx_start_date),
            ], context=context)
        _logger.warning('Delete previous record: %s' % len(product_ids))
        product_pool.unlink(cr, uid, product_ids, context=context)

        # Update with current:
        product_ids = product_pool.search(cr, uid, [], context=context)
        total = len(product_ids)
        i = 0
        for product in product_pool.browse(
                cr, uid, product_ids, context=context):
            i += 1
            if i % 100 == 0:
                _logger.warning('Updated %s of %s' % (
                    i, total,
                    ))

            self.create(cr, uid, {
                'product_id': product.id,
                'mx_start_date': product.mx_start_date,
                'mx_start_qty': product.mx_start_qty,
                }, context=context)

    _columns = {
        'product_id': fields.many2one(
            'product.product', 'Product', required=True),

        'mx_start_date': fields.date('Start date'),
        'mx_start_qty': fields.float('Inventory start qty',
            digits=(16, 2), # TODO parametrize
            help='Inventory at 1/1 for current year'),
    }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>generic bugfix (fast message)<commit_after># -*- coding: utf-8 -*-
###############################################################################
#
#    Copyright (C) 2001-2014 Micronaet SRL (<http://www.micronaet.it>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import os
import sys
import logging
import openerp
import openerp.netsvc as netsvc
import openerp.addons.decimal_precision as dp
from openerp.osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from openerp import SUPERUSER_ID, api
from openerp import tools
from openerp.tools.translate import _
from openerp.tools.float_utils import float_round as round
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class ProductProductStartHistory(orm.Model):
    """ Model name: ProductProductStartHistory
    """

    _name = 'product.product.start.history'
    _description = 'Start history'
    _rec_name = 'product_id'

    def history_start_elements(self, cr, uid, mx_start_date=False,
            context=None):
        ''' Save current history
        '''
        if not mx_start_date:
            _logger.error('Cannoy history without start date!')
            return True

        # Remove previous history values:
        import pdb; pdb.set_trace()
        history_ids = self.search(cr, uid, [
            ('mx_start_date', '=', mx_start_date),
            ], context=context)
        _logger.warning('Delete previous record: %s' % len(product_ids))
        self.unlink(cr, uid, history_ids, context=context)

        import pdb; pdb.set_trace()
        # Update with current:
        product_ids = product_pool.search(cr, uid, [], context=context)
        total = len(product_ids)
        i = 0
        for product in product_pool.browse(
                cr, uid, product_ids, context=context):
            i += 1
            if i % 100 == 0:
                _logger.warning('Updated %s of %s' % (
                    i, total,
                    ))

            self.create(cr, uid, {
                'product_id': product.id,
                'mx_start_date': product.mx_start_date,
                'mx_start_qty': product.mx_start_qty,
                }, context=context)

    _columns = {
        'product_id': fields.many2one(
            'product.product', 'Product', required=True),

        'mx_start_date': fields.date('Start date'),
        'mx_start_qty': fields.float('Inventory start qty',
            digits=(16, 2), # TODO parametrize
            help='Inventory at 1/1 for current year'),
    }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>import tests.data.german.german
import milk.supervised.defaultclassifier
data = tests.data.german.german.load()
features = data['data']
labels = data['label']
def test_defaultclassifier():
    C = milk.supervised.defaultclassifier.defaultclassifier()
    C.train(features,labels)
    assert C.apply(features[0]) in (0,1)
test_defaultclassifier.slow = True

<commit_msg>New interface. More testing.<commit_after>import tests.data.german.german
import milk.supervised.defaultclassifier
data = tests.data.german.german.load()
features = data['data']
labels = data['label']
def test_defaultclassifier():
    C = milk.supervised.defaultclassifier()
    C.train(features,labels)
    for f in features:
        assert C.apply(f) in (0,1)
test_defaultclassifier.slow = True

<|endoftext|>


<commit_before>#!/usr/bin/python
#
# Copyright (c) 2005-2008 rPath, Inc.
#

import testsuite
testsuite.setup()

import fixtures

from mint import buildtypes
from mint.lib.data import RDT_BOOL

# arbitrary sha1 is trhe sha1 of nothing for when it doesn't matter
fakeSha1 = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'

class VwsTest(fixtures.FixturedUnitTest):
    @fixtures.fixture('Full')
    def testGetAllVwsBuilds(self, db, data):
        client = self.getClient("admin")
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})
        cu = db.cursor()
        buildId = data['buildId']
        cu.execute('UPDATE BuildFiles SET sha1=?', fakeSha1)
        # now set the build type to raw filesystem image
        # this is still a no-go test, we need XEN_DOMU
        cu.execute('UPDATE Builds SET buildType=? WHERE buildId=?',
                buildtypes.RAW_FS_IMAGE, buildId)
        db.commit()
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})
        build = client.getBuild(buildId)
        build.setDataValue('XEN_DOMU', True, RDT_BOOL, validate = False)
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x.pop('sha1'), x) for x in buildList)
        self.assertEquals(buildList,
                {fakeSha1: {'productDescription': '',
                    'buildId': 1,
                    'projectId': 1,
                    'isPublished': 0,
                    'buildDescription': '',
                    'productName': 'Foo',
                    'isPrivate': 0,
                    'role': '',
                    'createdBy': 'owner',
                    'buildName': 'Test Build',
                    'buildPageUrl':
                            'http://test.rpath.local/project/foo/build?id=1',
                    'downloadUrl':
                            'http://test.rpath.local/downloadImage?fileId=1',
                    'baseFileName': 'foo-1.1-x86_64' }})

        client = self.getClient("owner")
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList[fakeSha1]['role'], 'Product Owner')

    @fixtures.fixture('Full')
    def testHiddenVisibility(self, db, data):
        client = self.getClient("admin")
        client.hideProject(data['projectId'])
        buildId = data['buildId']
        cu = db.cursor()
        cu.execute('UPDATE BuildFiles SET sha1=?', fakeSha1)
        cu.execute('UPDATE Builds SET buildType=? WHERE buildId=?',
                buildtypes.RAW_FS_IMAGE, buildId)
        db.commit()
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})
        build = client.getBuild(buildId)
        build.setDataValue('XEN_DOMU', True, RDT_BOOL, validate = False)
        db.commit()
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.failIf(len(buildList) != 1)
        client = self.getClient('nobody')
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})

if __name__ == '__main__':
    testsuite.main()
<commit_msg>Fixed test expectation (RBL-6208)<commit_after>#!/usr/bin/python
#
# Copyright (c) 2005-2008 rPath, Inc.
#

import testsuite
testsuite.setup()

import fixtures

from mint import buildtypes
from mint.lib.data import RDT_BOOL

# arbitrary sha1 is trhe sha1 of nothing for when it doesn't matter
fakeSha1 = 'da39a3ee5e6b4b0d3255bfef95601890afd80709'

class VwsTest(fixtures.FixturedUnitTest):
    @fixtures.fixture('Full')
    def testGetAllVwsBuilds(self, db, data):
        client = self.getClient("admin")
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})
        cu = db.cursor()
        buildId = data['buildId']
        cu.execute('UPDATE BuildFiles SET sha1=?', fakeSha1)
        # now set the build type to raw filesystem image
        # this is still a no-go test, we need XEN_DOMU
        cu.execute('UPDATE Builds SET buildType=? WHERE buildId=?',
                buildtypes.RAW_FS_IMAGE, buildId)
        db.commit()
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})
        build = client.getBuild(buildId)
        build.setDataValue('XEN_DOMU', True, RDT_BOOL, validate = False)
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x.pop('sha1'), x) for x in buildList)
        self.assertEquals(buildList,
                {fakeSha1: {'productDescription': '',
                    'buildId': 1,
                    'projectId': 1,
                    'isPublished': 0,
                    'buildDescription': '',
                    'productName': 'Foo',
                    'isPrivate': 0,
                    'role': '',
                    'createdBy': 'owner',
                    'buildName': 'Test Build',
                    'files': [
                         {'downloadUrl': 'http://test.rpath.local/downloadImage?fileId=1',
                          'sha1': 'da39a3ee5e6b4b0d3255bfef95601890afd80709',
                          'filename': 'file', 'idx': 0, 'size': '0'}
                        ],
                    'buildPageUrl':
                            'http://test.rpath.local/project/foo/build?id=1',
                    'downloadUrl':
                            'http://test.rpath.local/downloadImage?fileId=1',
                    'baseFileName': 'foo-1.1-x86_64' }})

        client = self.getClient("owner")
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList[fakeSha1]['role'], 'Product Owner')

    @fixtures.fixture('Full')
    def testHiddenVisibility(self, db, data):
        client = self.getClient("admin")
        client.hideProject(data['projectId'])
        buildId = data['buildId']
        cu = db.cursor()
        cu.execute('UPDATE BuildFiles SET sha1=?', fakeSha1)
        cu.execute('UPDATE Builds SET buildType=? WHERE buildId=?',
                buildtypes.RAW_FS_IMAGE, buildId)
        db.commit()
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})
        build = client.getBuild(buildId)
        build.setDataValue('XEN_DOMU', True, RDT_BOOL, validate = False)
        db.commit()
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.failIf(len(buildList) != 1)
        client = self.getClient('nobody')
        buildList = client.getAllBuildsByType('VWS')
        buildList = dict((x['sha1'], x) for x in buildList)
        self.assertEquals(buildList, {})

if __name__ == '__main__':
    testsuite.main()
<|endoftext|>