Repository: cwacek/python-jsonschema-objects

Issue:
Unprecise comparizon with zero of float values
Consider the following schema (this is an extract from Walmart)
```
              "ShippingWeight": {
                "type": "number",
                "title": "Shipping Weight (lbs)",
                "minimum": 0,
                "maximum": 1000000000,
                "exclusiveMaximum": false,
                "multipleOf": 0.001
              },
```
While evaluating the `multipleOf` constraint the result will never be exact 0 therefore the validation will always fail.

https://github.com/cwacek/python-jsonschema-objects/blob/2a5aeb29a953cff3d4fd82f19c0d46342af1da36/python_jsonschema_objects/validators.py#L44C8-L44C11

Discussion:

Patch:
diff --git a/python_jsonschema_objects/validators.py b/python_jsonschema_objects/validators.py
index 5cd9c94..92a792d 100644
--- a/python_jsonschema_objects/validators.py
+++ b/python_jsonschema_objects/validators.py
@@ -1,3 +1,4 @@
+import decimal
 import logging
 
 import six
@@ -40,8 +41,14 @@ registry = ValidatorRegistry()
 
 @registry.register()
 def multipleOf(param, value, _):
-    quot, rem = divmod(value, param)
-    if rem != 0:
+    # This conversion to string is intentional because floats are imprecise.
+    # >>> decimal.Decimal(33.069)
+    # Decimal('33.0690000000000026147972675971686840057373046875')
+    # >>> decimal.Decimal('33.069')
+    # Decimal('33.069')
+    value = decimal.Decimal(str(value))
+    divisor = decimal.Decimal(str(param))
+    if value % divisor != 0:
         raise ValidationError("{0} is not a multiple of {1}".format(value, param))
 
 


Test patch:
diff --git a/test/test_pytest.py b/test/test_pytest.py
index 6fc0775..9fe2950 100644
--- a/test/test_pytest.py
+++ b/test/test_pytest.py
@@ -41,7 +41,7 @@ def test_schema_validation():
         "$id": "test",
         "type": "object",
         "properties": {
-            "name": "string",  #  <-- this is invalid
+            "name": "string",  # <-- this is invalid
             "email": {"oneOf": [{"type": "string"}, {"type": "integer"}]},
         },
         "required": ["email"],
@@ -531,3 +531,24 @@ def test_justareference_example(markdown_examples):
     )
     ns = builder.build_classes()
     ns.JustAReference("Hello")
+
+
+def test_number_multiple_of_validation():
+    schema = {
+        "$schema": "http://json-schema.org/schema#",
+        "$id": "test",
+        "type": "object",
+        "title": "Base",
+        "properties": {
+            "sample": {
+                "type": "number",
+                "minimum": 0,
+                "maximum": 1000000000,
+                "multipleOf": 0.001,
+            },
+        },
+    }
+
+    builder = pjs.ObjectBuilder(schema)
+    ns = builder.build_classes()
+    ns.Base(sample=33.069)