mirror of
https://github.com/netbox-community/devicetype-library.git
synced 2024-11-22 00:13:36 +01:00
Fix float validation using decimal.Decimal (#1073)
* Fix float validation using decimal.Decimal * Force string repr of the float when loading yaml --------- Co-authored-by: Jonathan Senecal <jonathan.senecal@metrooptic.com>
This commit is contained in:
parent
0b6299aa3d
commit
1a4447a075
@ -605,7 +605,7 @@
|
||||
"value": {
|
||||
"type": "number",
|
||||
"minimum": 0,
|
||||
"multipleOfPrecision": 0.01
|
||||
"multipleOf": 0.01
|
||||
},
|
||||
"unit": {
|
||||
"type": "string",
|
||||
|
@ -1,11 +1,14 @@
|
||||
import decimal
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
from urllib.request import urlopen
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
from jsonschema import RefResolver, Draft4Validator
|
||||
from jsonschema import Draft4Validator, RefResolver
|
||||
from jsonschema.exceptions import ValidationError
|
||||
|
||||
from yaml_loader import DecimalSafeLoader
|
||||
|
||||
SCHEMAS = (
|
||||
('device-types', 'devicetype.json'),
|
||||
@ -35,7 +38,7 @@ def _get_definition_files():
|
||||
|
||||
# Initialize the schema
|
||||
with open(f"schema/{schema}") as schema_file:
|
||||
schema = json.loads(schema_file.read())
|
||||
schema = json.loads(schema_file.read(), parse_float=decimal.Decimal)
|
||||
|
||||
# Validate that the schema exists
|
||||
assert schema, f"Schema definition for {path} is empty!"
|
||||
@ -51,6 +54,12 @@ definition_files = _get_definition_files()
|
||||
known_slugs = set()
|
||||
|
||||
|
||||
def _decimal_file_handler(uri):
|
||||
with urlopen(uri) as url:
|
||||
result = json.loads(url.read().decode("utf-8"), parse_float=decimal.Decimal)
|
||||
return result
|
||||
|
||||
|
||||
def test_environment():
|
||||
"""
|
||||
Run basic sanity checks on the environment to ensure tests are running correctly.
|
||||
@ -75,11 +84,15 @@ def test_definitions(file_path, schema):
|
||||
assert content.endswith('\n'), "Missing trailing newline"
|
||||
|
||||
# Load YAML data from file
|
||||
definition = yaml.load(content, Loader=yaml.SafeLoader)
|
||||
definition = yaml.load(content, Loader=DecimalSafeLoader)
|
||||
|
||||
# Validate YAML definition against the supplied schema
|
||||
try:
|
||||
resolver = RefResolver(f'file://{os.getcwd()}/schema/devicetype.json', schema)
|
||||
resolver = RefResolver(
|
||||
f"file://{os.getcwd()}/schema/devicetype.json",
|
||||
schema,
|
||||
handlers={"file": _decimal_file_handler},
|
||||
)
|
||||
Draft4Validator(schema, resolver=resolver).validate(definition)
|
||||
except ValidationError as e:
|
||||
pytest.fail(f"{file_path} failed validation: {e}", False)
|
||||
|
34
tests/yaml_loader.py
Normal file
34
tests/yaml_loader.py
Normal file
@ -0,0 +1,34 @@
|
||||
import decimal
|
||||
|
||||
from yaml.composer import Composer
|
||||
from yaml.constructor import SafeConstructor
|
||||
from yaml.parser import Parser
|
||||
from yaml.reader import Reader
|
||||
from yaml.resolver import Resolver
|
||||
from yaml.scanner import Scanner
|
||||
|
||||
|
||||
class DecimalSafeConstructor(SafeConstructor):
|
||||
"""Special constructor to override construct_yaml_float() in order to cast "Decimal" types to the value"""
|
||||
|
||||
def construct_yaml_float(self, node):
|
||||
value = super().construct_yaml_float(node)
|
||||
# We force the string representation of the float here to avoid things like:
|
||||
# In [11]: decimal.Decimal(10.11)
|
||||
# Out[11]: Decimal('10.1099999999999994315658113919198513031005859375')
|
||||
return decimal.Decimal(f"{value}")
|
||||
|
||||
|
||||
DecimalSafeConstructor.add_constructor(
|
||||
"tag:yaml.org,2002:float", DecimalSafeConstructor.construct_yaml_float
|
||||
)
|
||||
|
||||
|
||||
class DecimalSafeLoader(Reader, Scanner, Parser, Composer, DecimalSafeConstructor, Resolver):
|
||||
def __init__(self, stream):
|
||||
Reader.__init__(self, stream)
|
||||
Scanner.__init__(self)
|
||||
Parser.__init__(self)
|
||||
Composer.__init__(self)
|
||||
DecimalSafeConstructor.__init__(self)
|
||||
Resolver.__init__(self)
|
Loading…
Reference in New Issue
Block a user