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), }))
def test_dict_key_value(): _validate({ "one": 1.0, "two": 2.0, }, Dict(String(), Float()))
def test_float_max_invalid(value, max_value): with pytest.raises(InvalidValueError): _validate(value, Float(max=max_value))
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
def test_float_min_invalid(value, min_value): with pytest.raises(InvalidValueError): _validate(value, Float(min=min_value))
def test_float_min_max_valid(): _validate(7.0, Float(min=7, max=7)) _validate(7.0, Float(min=6.9, max=7.1)) _validate(7.5, Float(min=6, max=8)) _validate(7.5, Float(min=6.0, max=8.0))
def test_float_invalid_type(): error = pytest.raises(InvalidTypeError, lambda: _validate(1, Float())).value assert error.object_name == "" assert error.object_type == int
def test_float(): _validate(0.1, Float())
}, { "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: