Esempio n. 1
0
def test_dict_scheme_unknown_parameter():
    error = pytest.raises(
        UnknownParameterError, lambda: _validate({
            1: True,
            False: "value",
        }, DictScheme({1: Bool()}))).value

    assert error.object_name == "[False]"
Esempio n. 2
0
def test_dict_scheme_missing_parameter():
    error = pytest.raises(
        MissingParameterError, lambda: _validate({
            2: "value",
        }, DictScheme({
            1: Bool(),
            2: String()
        }))).value

    assert error.object_name == "[1]"
Esempio n. 3
0
        async def inner_wrapper(request, *args, **kwargs):
            try:
                data = await request.json()
            except (ValueError, TypeError):
                raise web.HTTPBadRequest(text="Could not decode JSON object.")

            if scheme:
                try:
                    data = validate("request", data, DictScheme(scheme))
                except ValidationError as e:
                    raise web.HTTPBadRequest(text=e.get_message())
            return await coro(request, data, *args, **kwargs)
Esempio n. 4
0
def test_dict_scheme_modification():
    _validate_modification({
        "1": "10",
        "2": "20",
        "3": "30"
    }, DictScheme({
        "1": ToInt(),
        "2": String(),
        "3": ToInt()
    }), {
        "1": 10,
        "2": "20",
        "3": 30
    })
Esempio n. 5
0
def test_dict_scheme_with_schema():
    _validate({
        False: "string",
        1: True,
        "integer": 10,
        4.4: 44.4,
    },
              DictScheme({
                  False: String(),
                  1: Bool(),
                  "integer": Integer(),
                  3.3: Float(optional=True),
                  4.4: Float(optional=True),
              }))
Esempio n. 6
0
    def _get_scheme(cls):
        """Returns resource scheme for proper validation.

        Attention: for internal use only!
        """

        scheme = {}
        for base in cls.mro():
            if bool(
                issubclass(base, BaseResource) and
                getattr(base, "__scheme__", None)
            ):
                scheme.update(base.__scheme__)

        return DictScheme(scheme, ignore_unknown=True)
Esempio n. 7
0
class ExportsInfo(Sequence):
    """Information about volume exports."""

    __scheme__ = List(DictScheme({
        "sdcId": String(),
        "sdcIp": String(),
        "limitIops": Integer(),
        "limitBwInMbps": Integer()
    }), optional=True)

    def __init__(self, data=None):
        self._data = data or []

    def __getitem__(self, index):
        return self._data[index]

    def __len__(self):
        return len(self._data)

    def __contains__(self, key):
        if isinstance(key, Sdc):
            return key["id"] in (e["sdcId"] for e in self._data)
        else:
            super(ExportsInfo, self).__contains__(key)
Esempio n. 8
0
def test_dict_scheme_invalid_type():
    error = pytest.raises(InvalidTypeError,
                          lambda: _validate([], DictScheme({}))).value

    assert error.object_name == ""
    assert error.object_type == list
Esempio n. 9
0
def test_dict_scheme_with_delete_unknown():
    _validate_modification({
        "known_key": 10,
        "unknown_key": 10
    }, DictScheme({"known_key": Integer()}, delete_unknown=True),
                           {"known_key": 10})
Esempio n. 10
0
def test_dict_scheme_with_ignore_unknown():
    _validate({
        "known_key": 10,
        "unknown_key": 10,
    }, DictScheme({"known_key": Integer()}, ignore_unknown=True))
Esempio n. 11
0
def test_dict_scheme_empty():
    _validate({}, DictScheme({}))
Esempio n. 12
0
class BaseResource(Mapping):
    """Base resource model."""

    __scheme__ = {
        "id": String(),
        "links": List(
            DictScheme({
                "href": String(),
                "rel": String()
            }), optional=True
        )
    }
    """Data scheme for instance validation."""

    __parents__ = None
    """
    References to parent resources by fields.

    Example:
        frozenset([
            ("parentField", "ResourceClassName")
        ])
    """

    __resource__ = None
    """
    Custom resource name that overrides default
    name based on name of resource class.
    """

    @classmethod
    def _get_name(cls):
        """Returns resource name.

        Attention: for internal use only!
        """

        resource = cls.__resource__
        if not resource:
            resource = camelize(underscore(cls.__name__))
        return resource

    @classmethod
    def _get_scheme(cls):
        """Returns resource scheme for proper validation.

        Attention: for internal use only!
        """

        scheme = {}
        for base in cls.mro():
            if bool(
                issubclass(base, BaseResource) and
                getattr(base, "__scheme__", None)
            ):
                scheme.update(base.__scheme__)

        return DictScheme(scheme, ignore_unknown=True)

    @classmethod
    def one(cls, instance_id, **kwargs):
        """Returns instance of resource.

        :param instance_id: id of resource instance

        :returns: instance of resource
        """

        return cls(instance_id, **kwargs)

    @pyscaleio.inject
    @classmethod
    def all(cls, client, instance_ids=None, **kwargs):
        """Returns list of resource instances.

        :param instance_ids: list of instance ids (optional)

        :returns: list of resource instances
        """

        if not instance_ids:
            instances = client.get_instances_of(cls._get_name())
        else:
            if isinstance(instance_ids, string_types):
                instance_ids = (instance_ids,)
            instances = client.perform_action_on_type(
                cls._get_name(), "queryBySelectedIds", {"ids": instance_ids})

        return [cls(instance=instance, client=client)
            for instance in instances
        ]

    @pyscaleio.inject
    def __init__(self, client, instance_id=None, instance=None):
        self._client = client
        self._scheme = {}

        if instance_id and instance:
            raise exceptions.ScaleIONotBothParameters("instance_id", "instance")

        if instance_id:
            instance = self._client.get_instance_of(self._get_name(), instance_id)

        self._instance = self._validate(instance or {})

    def __getitem__(self, key):
        return self._instance[key]

    def __iter__(self):
        return iter(self._instance)

    def __len__(self):
        return len(self._instance)

    @property
    def links(self):
        return self["links"]

    def _validate(self, instance):
        """Validates the instance if resource according to scheme.

        Attention: for internal use only!
        """

        try:
            return validate("instance", instance, self._get_scheme())
        except ValidationError as e:
            raise exceptions.ScaleIOValidationError(e)

    def update(self):
        """Updates resource instance."""

        instance = self._client.get_instance_of(self._get_name(), self["id"])
        instance = self._validate(instance)

        fields = set(list(instance) + list(self._instance))
        for field in fields:
            try:
                instance[field]
            except KeyError:
                del self._instance[field]
            else:
                self._instance[field] = instance[field]
Esempio n. 13
0
    def validate(cls, data):
        """Validate Car document and return the instance."""

        return cls(validate("Car", data, DictScheme(cls.__scheme__)))
Esempio n. 14
0
class Car(MutableMapping):
    __slots__ = ("_object", )
    __scheme__ = {
        "ownerName":
        OrdinaryString(),
        "serialNumber":
        Integer32(),
        "modelYear":
        Integer32(),
        # "serialNumber": Integer64(),
        # "modelYear": Integer64(),
        "code":
        OrdinaryString(),
        "vehicleCode":
        OrdinaryString(),
        "engine":
        DictScheme({
            "capacity": Integer16(),
            "numCylinders": Integer8(),
            "maxRpm": Integer16(),
            "manufacturerCode": Char(),
        }),
        "fuelFigures":
        DictScheme({
            "speed": Integer16(),
            "mpg": Float(),
            "usageDescription": OrdinaryString(),
        }),
        "performanceFigures":
        DictScheme({
            "octaneRating":
            Integer16(),
            "acceleration":
            DictScheme({
                "mph": Integer16(),
                "seconds": Float(),
            }),
        }),
        "manufacturer":
        OrdinaryString(),
        "model":
        OrdinaryString(),
        "activationCode":
        OrdinaryString(),
    }

    __database__ = "soldcars"
    __collection__ = "cars"
    __write_majority__ = WriteConcern(w="majority", wtimeout=5000)

    @classmethod
    def get_scheme(cls):
        """Return Car scheme."""

        return cls.__scheme__

    @classmethod
    def validate(cls, data):
        """Validate Car document and return the instance."""

        return cls(validate("Car", data, DictScheme(cls.__scheme__)))

    @classmethod
    def database(cls):
        """Return database instance."""

        return Motor().default()[cls.__database__]

    @classmethod
    def collection(cls, stale_ok=False, majority=False):
        """Return collection instance."""

        kwargs = {}
        if stale_ok:
            kwargs["read_preference"] = ReadPreference.SECONDARY_PREFERRED
        elif majority:
            kwargs["write_concern"] = cls.__write_majority__

        return aiomotor.AsyncIOMotorCollection(cls.database(),
                                               cls.__collection__, **kwargs)

    @classmethod
    async def ensure_index(cls):
        """Ensure collection index."""

        await cls.collection().create_index(
            [("serialNumber", pymongo.ASCENDING)], unique=True)

    @classmethod
    async def one(cls,
                  serial,
                  add_query=None,
                  fields=None,
                  required=True,
                  stale_ok=False):
        """Return a one Car document."""

        query = {"serialNumber": serial}
        if add_query:
            query.update(add_query)

        car = await cls.collection(stale_ok=stale_ok
                                   ).find_one(query, projection=fields)

        if not car and required:
            raise CarNotFound(serial)

        if car:
            car.pop("_id")
        return cls(car)

    @classmethod
    def get_mocked(cls, override=None):
        """Mock a one Car document.

        Attention: use only in tests and cli tools to fake documents!
        """
        def randstr(length):
            letters = string.ascii_lowercase
            return ''.join(random.choice(letters) for i in range(length))

        def _mock(part):
            d = {}
            for key, value in part.items():
                # NOTE: using mangled attributes is not a good way
                #       but object_validator library was not intend to
                #       convert or generate new data by the scheme.
                if isinstance(value, DictScheme):
                    d[key] = _mock(value._DictScheme__scheme)
                elif isinstance(value, Integer):
                    d[key] = random.randint(value._BasicNumber__min or 0,
                                            value._BasicNumber__max or 100)
                elif isinstance(value, Float):
                    d[key] = random.uniform(value._BasicNumber__min or 0,
                                            value._BasicNumber__max or 100)
                    d[key] = round(d[key], 2)
                elif isinstance(value, String):
                    d[key] = randstr(
                        random.randint(value._String__min_length,
                                       value._String__max_length))
            return d

        mocked = _mock(cls.get_scheme())
        mocked.update(override or {})
        return cls(mocked)

    def __init__(self, data):
        self._object = data or {}

    def __getitem__(self, key):
        return self._object[key]

    def __setitem__(self, key, value):
        self._object[key] = value

    def __delitem__(self, key):
        self._object.pop(key)

    def __iter__(self):
        return iter(self._object)

    def __len__(self):
        return len(self._object)

    def asdict(self):
        """Return Car document as dictionary."""

        return copy.deepcopy(self._object)

    def asjson(self):
        """Return Car document as JSON."""

        return json.dumps(self._object)

    async def insert(self, majority=True):
        """Insert Car document in collection."""

        try:
            document_id = self["_id"] = \
                await self.collection(majority=majority).insert_one(self)
        except pymongo.errors.WTimeoutError:
            # FIXME: add retry on write timeout
            raise
        except pymongo.errors.DuplicateKeyError:
            raise CarAlreadyExists(self["serialNumber"])

        return document_id
Esempio n. 15
0
    def _get_scheme(cls):
        """Returns config scheme."""

        return DictScheme(cls.__scheme__)
Esempio n. 16
0
}, {
    "id": 2,
    "name": "two",
    "value": 2.0,
    "zero": False,
    "dividers": [1, 2],
    "dividers_map": {
        1: 1.0,
        2: 2.0,
    },
}]

SCHEME = List(DictScheme({
    "id": Integer(choices=(0, 2)),
    "name": String(),
    "value": Float(),
    "zero": Bool(),
    "dividers": List(Integer()),
    "dividers_map": Dict(Integer(), Float()),
}))


def test_validate():
    _validate("items", copy.deepcopy(ITEMS), SCHEME)


def test_validate_invalid_type():
    items = copy.deepcopy(ITEMS)
    items[1]["id"] = "string"

    error = pytest.raises(InvalidTypeError, lambda:
        _validate("items", items, SCHEME)