mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	add json check before compile (#354)
* add json check before compile * do more checking on effects * add effects checking * better effects checking. * integrate schema check for default config reduce size of default configs
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -17,3 +17,4 @@ CMakeCache.txt | ||||
| /HyperionConfig.h | ||||
| /lib | ||||
| .directory | ||||
| *.pyc | ||||
|   | ||||
| @@ -16,6 +16,7 @@ SET ( HYPERION_VERSION_STABLE OFF ) | ||||
| SET ( HYPERION_VERSION_MAJOR 2 ) | ||||
| SET ( HYPERION_VERSION_MINOR 0 ) | ||||
| SET ( HYPERION_VERSION_PATCH 0 ) | ||||
| SET ( CURRENT_CONFIG_VERSION 2 ) | ||||
|  | ||||
| SET ( DEFAULT_AMLOGIC    OFF ) | ||||
| SET ( DEFAULT_DISPMANX   OFF ) | ||||
| @@ -140,6 +141,40 @@ message(STATUS "ENABLE_PROFILER = ${ENABLE_PROFILER}") | ||||
| SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto ) | ||||
| SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto ) | ||||
|  | ||||
| # check all  json files | ||||
| FILE ( GLOB_RECURSE HYPERION_SCHEMAS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc/*schema*.json ) | ||||
| SET( JSON_FILES | ||||
| 	config/hyperion.config.json.default | ||||
| 	${HYPERION_SCHEMAS} | ||||
| ) | ||||
| EXECUTE_PROCESS ( | ||||
| 	COMMAND python test/jsonchecks/checkjson.py ${JSON_FILES} | ||||
| 	WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} | ||||
| 	RESULT_VARIABLE CHECK_JSON_FAILED | ||||
| ) | ||||
| IF ( ${CHECK_JSON_FAILED} ) | ||||
| 	MESSAGE (FATAL_ERROR "check of json files failed" ) | ||||
| ENDIF () | ||||
|  | ||||
| EXECUTE_PROCESS ( | ||||
| 	COMMAND python test/jsonchecks/checkeffects.py effects effects/schema | ||||
| 	WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} | ||||
| 	RESULT_VARIABLE CHECK_EFFECTS_FAILED | ||||
| ) | ||||
| IF ( ${CHECK_EFFECTS_FAILED} ) | ||||
| 	MESSAGE (FATAL_ERROR "check of json effect files failed" ) | ||||
| ENDIF () | ||||
|  | ||||
| EXECUTE_PROCESS ( | ||||
| 	COMMAND python test/jsonchecks/checkschema.py config/hyperion.config.json.default libsrc/hyperion/schemas/hyperion.schema-${CURRENT_CONFIG_VERSION}.json | ||||
| 	WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} | ||||
| 	RESULT_VARIABLE CHECK_CONFIG_FAILED | ||||
| ) | ||||
| IF ( ${CHECK_CONFIG_FAILED} ) | ||||
| 	MESSAGE (FATAL_ERROR "check of json default config failed" ) | ||||
| ENDIF () | ||||
|  | ||||
|  | ||||
| # Createt the configuration file | ||||
|  | ||||
| # Add project specific cmake modules (find, etc) | ||||
|   | ||||
| @@ -30,6 +30,9 @@ | ||||
| // Define to enable profiler for development purpose | ||||
| #cmakedefine ENABLE_PROFILER | ||||
|  | ||||
| // Define version id of current config | ||||
| #define CURRENT_CONFIG_VERSION ${CURRENT_CONFIG_VERSION} | ||||
|  | ||||
| // the hyperion build id string | ||||
| #define HYPERION_BUILD_ID "${HYPERION_BUILD_ID}" | ||||
|  | ||||
| @@ -40,4 +43,4 @@ | ||||
|  | ||||
| #define HYPERION_JSON_VERSION "1.0.0" | ||||
|  | ||||
| #define CURRENT_CONFIG_VERSION 2 | ||||
|  | ||||
|   | ||||
| @@ -70,7 +70,7 @@ | ||||
| 	{ | ||||
| 		"imageToLedMappingType" : "multicolor_mean", | ||||
| 		"channelAdjustment_enable" : true, | ||||
| 		"channelAdjustment_v4l_only" : true, | ||||
| 		"channelAdjustment_v4l_only" : false, | ||||
| 		"channelAdjustment" : | ||||
| 		[ | ||||
| 			{ | ||||
| @@ -87,7 +87,7 @@ | ||||
| 			} | ||||
| 		], | ||||
| 		"transform_enable" : true, | ||||
| 		"transform_v4l_only" : true, | ||||
| 		"transform_v4l_only" : false, | ||||
| 		"transform" : | ||||
| 		[ | ||||
| 			{ | ||||
| @@ -382,233 +382,93 @@ | ||||
| 	[ | ||||
| 		{ | ||||
| 			"index": 0, | ||||
| 			"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.1667, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 1, | ||||
| 			"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.3332, "minimum": 0.1667 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 2, | ||||
| 			"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.5, "minimum": 0.3333 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 3, | ||||
| 			"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.6667, "minimum": 0.5 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 4, | ||||
| 			"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.8333, "minimum": 0.6667 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 5, | ||||
| 			"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.8333 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 6, | ||||
| 			"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.95 }, | ||||
| 			"vscan": { "maximum": 0.3333, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 7, | ||||
| 			"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.95 }, | ||||
| 			"vscan": { "maximum": 0.6667, "minimum": 0.3333 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 8, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.95 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.6667 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 9, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.8333 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 10, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } | ||||
| 			"hscan": { "maximum": 0.8333, "minimum": 0.6667 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 11, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } | ||||
| 			"hscan": { "maximum": 0.6667, "minimum": 0.5 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 12, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } | ||||
| 			"hscan": { "maximum": 0.5, "minimum": 0.3333 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 13, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } | ||||
| 			"hscan": { "maximum": 0.3333, "minimum": 0.1667 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 14, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } | ||||
| 			"hscan": { "maximum": 0.1667, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 15, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } | ||||
| 			"hscan": { "maximum": 0.05, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.6667 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 16, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 			"hscan": { "maximum": 0.05, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 0.6667, "minimum": 0.3333 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 17, | ||||
| 			"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 18, | ||||
| 			"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 19, | ||||
| 			"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 20, | ||||
| 			"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 21, | ||||
| 			"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 22, | ||||
| 			"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 23, | ||||
| 			"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 24, | ||||
| 			"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 25, | ||||
| 			"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 26, | ||||
| 			"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 27, | ||||
| 			"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 28, | ||||
| 			"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 29, | ||||
| 			"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 30, | ||||
| 			"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 31, | ||||
| 			"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 32, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 33, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 34, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 35, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 36, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 37, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 38, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 39, | ||||
| 			"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 40, | ||||
| 			"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 41, | ||||
| 			"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 42, | ||||
| 			"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 43, | ||||
| 			"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 44, | ||||
| 			"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 45, | ||||
| 			"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.05, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 0.3333, "minimum": 0 } | ||||
| 		} | ||||
| 	] | ||||
| } | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
| 	{ | ||||
| 		"imageToLedMappingType" : "multicolor_mean", | ||||
| 		"channelAdjustment_enable" : true, | ||||
| 		"channelAdjustment_v4l_only" : true, | ||||
| 		"channelAdjustment_v4l_only" : false, | ||||
| 		"channelAdjustment" : | ||||
| 		[ | ||||
| 			{ | ||||
| @@ -39,7 +39,7 @@ | ||||
| 			} | ||||
| 		], | ||||
| 		"transform_enable" : true, | ||||
| 		"transform_v4l_only" : true, | ||||
| 		"transform_v4l_only" : false, | ||||
| 		"transform" : | ||||
| 		[ | ||||
| 			{ | ||||
| @@ -114,7 +114,7 @@ | ||||
| 		"type"   : "auto", | ||||
| 		"width" : 80, | ||||
| 		"height" : 45, | ||||
| 		"frequency_Hz" : 10.0, | ||||
| 		"frequency_Hz" : 10, | ||||
| 		"priority" : 900 | ||||
| 	}, | ||||
|  | ||||
| @@ -194,233 +194,93 @@ | ||||
| 	[ | ||||
| 		{ | ||||
| 			"index": 0, | ||||
| 			"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.1667, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 1, | ||||
| 			"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.3332, "minimum": 0.1667 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 2, | ||||
| 			"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.5, "minimum": 0.3333 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 3, | ||||
| 			"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.6667, "minimum": 0.5 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 4, | ||||
| 			"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.8333, "minimum": 0.6667 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 5, | ||||
| 			"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.8333 }, | ||||
| 			"vscan": { "maximum": 0.0800, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 6, | ||||
| 			"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.95 }, | ||||
| 			"vscan": { "maximum": 0.3333, "minimum": 0 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 7, | ||||
| 			"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.95 }, | ||||
| 			"vscan": { "maximum": 0.6667, "minimum": 0.3333 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 8, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.95 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.6667 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 9, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 1, "minimum": 0.8333 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 10, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } | ||||
| 			"hscan": { "maximum": 0.8333, "minimum": 0.6667 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 11, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } | ||||
| 			"hscan": { "maximum": 0.6667, "minimum": 0.5 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 12, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } | ||||
| 			"hscan": { "maximum": 0.5, "minimum": 0.3333 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 13, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } | ||||
| 			"hscan": { "maximum": 0.3333, "minimum": 0.1667 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 14, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } | ||||
| 			"hscan": { "maximum": 0.1667, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.92 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 15, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } | ||||
| 			"hscan": { "maximum": 0.05, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 1, "minimum": 0.6667 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 16, | ||||
| 			"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 			"hscan": { "maximum": 0.05, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 0.6667, "minimum": 0.3333 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index": 17, | ||||
| 			"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 18, | ||||
| 			"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 19, | ||||
| 			"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 20, | ||||
| 			"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 21, | ||||
| 			"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 22, | ||||
| 			"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 23, | ||||
| 			"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 24, | ||||
| 			"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 25, | ||||
| 			"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 26, | ||||
| 			"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 27, | ||||
| 			"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 28, | ||||
| 			"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 29, | ||||
| 			"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 30, | ||||
| 			"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 31, | ||||
| 			"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 32, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 33, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 34, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 35, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 36, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 37, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 38, | ||||
| 			"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 39, | ||||
| 			"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 40, | ||||
| 			"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 41, | ||||
| 			"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 42, | ||||
| 			"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 43, | ||||
| 			"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 44, | ||||
| 			"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 		}, | ||||
| 		{ | ||||
| 			"index" : 45, | ||||
| 			"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 }, | ||||
| 			"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 } | ||||
| 			"hscan": { "maximum": 0.05, "minimum": 0 }, | ||||
| 			"vscan": { "maximum": 0.3333, "minimum": 0 } | ||||
| 		} | ||||
| 	] | ||||
| } | ||||
|   | ||||
							
								
								
									
										19
									
								
								test/jsonchecks/COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								test/jsonchecks/COPYING
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| Copyright (c) 2011 Julian Berman | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
							
								
								
									
										50
									
								
								test/jsonchecks/checkeffects.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								test/jsonchecks/checkeffects.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| #!/usr/bin/env python | ||||
| import json, sys, glob | ||||
| from os import path | ||||
| from jsonschema import Draft3Validator | ||||
|  | ||||
| print("-- validate json effect files") | ||||
|  | ||||
| jsonFiles = sys.argv[1] | ||||
| schemaFiles = sys.argv[2] | ||||
|  | ||||
| retval  = 0  | ||||
| total   = 0 | ||||
| errors  = 0 | ||||
| with open("libsrc/effectengine/EffectDefinition.schema.json") as baseSchemaFile: | ||||
| 	baseSchema = json.load(baseSchemaFile) | ||||
| 	baseValidator = Draft3Validator(baseSchema) | ||||
| 	for filename in glob.glob(jsonFiles+'/*.json'): | ||||
| 		with open(filename) as f: | ||||
| 			total += 1 | ||||
| 			msg = "   check effect %s ... " % filename | ||||
| 			try: | ||||
| 				effect = json.load(f) | ||||
| 				script = path.basename(effect['script']) | ||||
| 				if not path.exists(jsonFiles+'/'+script): | ||||
| 					raise ValueError('script file: '+script+' not found.') | ||||
|  | ||||
| 				schema = path.splitext(script)[0]+'.schema.json' | ||||
| 				if not path.exists(jsonFiles+'/schema/'+schema): | ||||
| 					raise ValueError('schema file: '+schema+' not found.') | ||||
| 				schema = jsonFiles+'/schema/'+schema | ||||
| 				 | ||||
| 				# validate against schema | ||||
| 				with open(schema) as s: | ||||
| 					effectSchema = json.load(s) | ||||
| 					Draft3Validator.check_schema(effectSchema) | ||||
| 					validator = Draft3Validator(effectSchema) | ||||
| 					baseValidator.validate(effect) | ||||
| 					validator.validate(effect['args']) | ||||
| 				 | ||||
| 				#print(msg + "ok") | ||||
|  | ||||
| 			except Exception as e: | ||||
| 				print(msg + 'error ('+str(e)+')') | ||||
| 				errors += 1 | ||||
| 				retval = 1 | ||||
| 			 | ||||
|  | ||||
| print("   checked effect files: %s success: %s errors: %s" % (total,(total-errors),errors)) | ||||
|  | ||||
| sys.exit(retval) | ||||
							
								
								
									
										23
									
								
								test/jsonchecks/checkjson.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								test/jsonchecks/checkjson.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| #!/usr/bin/env python | ||||
| import json, sys | ||||
|  | ||||
| print("-- validate json files") | ||||
|  | ||||
| retval  = 0  | ||||
| total   = 0 | ||||
| errors  = 0 | ||||
| for filename in sys.argv[1:]: | ||||
| 	with open(filename) as f: | ||||
| 		total += 1 | ||||
| 		msg = "   check json %s ... " % filename | ||||
| 		try: | ||||
| 			json.load(f) | ||||
| 			#print(msg + "ok") | ||||
| 		except ValueError as e: | ||||
| 			print(msg + 'invalid') | ||||
| 			retval = 1 | ||||
| 			errors += 1 | ||||
|  | ||||
| print("   checked files: %s success: %s errors: %s" % (total,(total-errors),errors)) | ||||
|  | ||||
| sys.exit(retval) | ||||
							
								
								
									
										21
									
								
								test/jsonchecks/checkschema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								test/jsonchecks/checkschema.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| #!/usr/bin/env python | ||||
| import json, sys, glob | ||||
| from os import path | ||||
| from jsonschema import Draft3Validator | ||||
|  | ||||
| print('-- validate json file') | ||||
|  | ||||
| jsonFileName   = sys.argv[1] | ||||
| schemaFileName = sys.argv[2] | ||||
|  | ||||
| try: | ||||
| 	with open(schemaFileName) as schemaFile: | ||||
| 		with open(jsonFileName) as jsonFile: | ||||
| 			j = json.load(jsonFile) | ||||
| 			validator = Draft3Validator(json.load(schemaFile)) | ||||
| 			validator.validate(j) | ||||
| except Exception as  e: | ||||
| 	print('validation error: '+jsonFileName + ' '+schemaFileName+' ('+str(e)+')') | ||||
| 	sys.exit(1) | ||||
|  | ||||
| sys.exit(0) | ||||
							
								
								
									
										734
									
								
								test/jsonchecks/jsonschema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										734
									
								
								test/jsonchecks/jsonschema.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,734 @@ | ||||
| """ | ||||
| An implementation of JSON Schema for Python | ||||
|  | ||||
| The main functionality is provided by the validator classes for each of the | ||||
| supported JSON Schema versions. | ||||
|  | ||||
| Most commonly, the :function:`validate` function is the quickest way to simply | ||||
| validate a given instance under a schema, and will create a validator for you. | ||||
|  | ||||
| """ | ||||
|  | ||||
| from __future__ import division, unicode_literals | ||||
|  | ||||
| import collections | ||||
| import itertools | ||||
| import operator | ||||
| import re | ||||
| import sys | ||||
| import warnings | ||||
|  | ||||
|  | ||||
| __version__ = "0.7" | ||||
|  | ||||
| FLOAT_TOLERANCE = 10 ** -15 | ||||
| PY3 = sys.version_info[0] >= 3 | ||||
|  | ||||
| if PY3: | ||||
|     basestring = unicode = str | ||||
|     iteritems = operator.methodcaller("items") | ||||
|     from urllib.parse import unquote | ||||
| else: | ||||
|     from itertools import izip as zip | ||||
|     iteritems = operator.methodcaller("iteritems") | ||||
|     from urllib import unquote | ||||
|  | ||||
|  | ||||
| class UnknownType(Exception): | ||||
|     """ | ||||
|     An unknown type was given. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|  | ||||
| class InvalidRef(Exception): | ||||
|     """ | ||||
|     An invalid reference was given. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|  | ||||
| class SchemaError(Exception): | ||||
|     """ | ||||
|     The provided schema is malformed. | ||||
|  | ||||
|     The same attributes exist for ``SchemaError``s as for ``ValidationError``s. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     validator = None | ||||
|  | ||||
|     def __init__(self, message): | ||||
|         super(SchemaError, self).__init__(message) | ||||
|         self.message = message | ||||
|         self.path = [] | ||||
|  | ||||
|  | ||||
| class ValidationError(Exception): | ||||
|     """ | ||||
|     The instance didn't properly validate with the provided schema. | ||||
|  | ||||
|     Relevant attributes are: | ||||
|         * ``message`` : a human readable message explaining the error | ||||
|         * ``path`` : a list containing the path to the offending element (or [] | ||||
|                      if the error happened globally) in *reverse* order (i.e. | ||||
|                      deepest index first). | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     # the failing validator will be set externally at whatever recursion level | ||||
|     # is immediately above the validation failure | ||||
|     validator = None | ||||
|  | ||||
|     def __init__(self, message): | ||||
|         super(ValidationError, self).__init__(message) | ||||
|         self.message = message | ||||
|  | ||||
|         # Any validator that recurses must append to the ValidationError's | ||||
|         # path (e.g., properties and items) | ||||
|         self.path = [] | ||||
|  | ||||
|  | ||||
| class Draft3Validator(object): | ||||
|     """ | ||||
|     A validator for JSON Schema draft 3. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     DEFAULT_TYPES = { | ||||
|         "array" : list, "boolean" : bool, "integer" : int, "null" : type(None), | ||||
|         "number" : (int, float), "object" : dict, "string" : basestring, | ||||
|     } | ||||
|  | ||||
|     def __init__(self, schema, types=()): | ||||
|         """ | ||||
|         Initialize a validator. | ||||
|  | ||||
|         ``schema`` should be a *valid* JSON Schema object already converted to | ||||
|         a native Python object (typically a dict via ``json.load``). | ||||
|  | ||||
|         ``types`` is a mapping (or iterable of 2-tuples) containing additional | ||||
|         types or alternate types to verify via the 'type' property. For | ||||
|         instance, the default types for the 'number' JSON Schema type are | ||||
|         ``int`` and ``float``.  To override this behavior (e.g. for also | ||||
|         allowing ``decimal.Decimal``), pass ``types={"number" : (int, float, | ||||
|         decimal.Decimal)} *including* the default types if so desired, which | ||||
|         are fairly obvious but can be accessed via the ``DEFAULT_TYPES`` | ||||
|         attribute on this class if necessary. | ||||
|  | ||||
|         """ | ||||
|  | ||||
|         self._types = dict(self.DEFAULT_TYPES) | ||||
|         self._types.update(types) | ||||
|         self._types["any"] = tuple(self._types.values()) | ||||
|  | ||||
|         self.schema = schema | ||||
|  | ||||
|     def is_type(self, instance, type): | ||||
|         """ | ||||
|         Check if an ``instance`` is of the provided (JSON Schema) ``type``. | ||||
|  | ||||
|         """ | ||||
|  | ||||
|         if type not in self._types: | ||||
|             raise UnknownType(type) | ||||
|         type = self._types[type] | ||||
|  | ||||
|         # bool inherits from int, so ensure bools aren't reported as integers | ||||
|         if isinstance(instance, bool): | ||||
|             type = _flatten(type) | ||||
|             if int in type and bool not in type: | ||||
|                 return False | ||||
|         return isinstance(instance, type) | ||||
|  | ||||
|     def is_valid(self, instance, _schema=None): | ||||
|         """ | ||||
|         Check if the ``instance`` is valid under the current schema. | ||||
|  | ||||
|         Returns a bool indicating whether validation succeeded. | ||||
|  | ||||
|         """ | ||||
|  | ||||
|         error = next(self.iter_errors(instance, _schema), None) | ||||
|         return error is None | ||||
|  | ||||
|     @classmethod | ||||
|     def check_schema(cls, schema): | ||||
|         """ | ||||
|         Validate a ``schema`` against the meta-schema to see if it is valid. | ||||
|  | ||||
|         """ | ||||
|  | ||||
|         for error in cls(cls.META_SCHEMA).iter_errors(schema): | ||||
|             s = SchemaError(error.message) | ||||
|             s.path = error.path | ||||
|             s.validator = error.validator | ||||
|             # I think we're safer raising these always, not yielding them | ||||
|             raise s | ||||
|  | ||||
|     def iter_errors(self, instance, _schema=None): | ||||
|         """ | ||||
|         Lazily yield each of the errors in the given ``instance``. | ||||
|  | ||||
|         """ | ||||
|  | ||||
|         if _schema is None: | ||||
|             _schema = self.schema | ||||
|  | ||||
|         for k, v in iteritems(_schema): | ||||
|             validator = getattr(self, "validate_%s" % (k.lstrip("$"),), None) | ||||
|  | ||||
|             if validator is None: | ||||
|                 continue | ||||
|  | ||||
|             errors = validator(v, instance, _schema) or () | ||||
|             for error in errors: | ||||
|                 # if the validator hasn't already been set (due to recursion) | ||||
|                 # make sure to set it | ||||
|                 error.validator = error.validator or k | ||||
|                 yield error | ||||
|  | ||||
|     def validate(self, *args, **kwargs): | ||||
|         """ | ||||
|         Validate an ``instance`` under the given ``schema``. | ||||
|  | ||||
|         """ | ||||
|  | ||||
|         for error in self.iter_errors(*args, **kwargs): | ||||
|             raise error | ||||
|  | ||||
|     def validate_type(self, types, instance, schema): | ||||
|         types = _list(types) | ||||
|  | ||||
|         for type in types: | ||||
|             # Ouch. Brain hurts. Two paths here, either we have a schema, then | ||||
|             # check if the instance is valid under it | ||||
|             if (( | ||||
|                 self.is_type(type, "object") and | ||||
|                 self.is_valid(instance, type) | ||||
|  | ||||
|             # Or we have a type as a string, just check if the instance is that | ||||
|             # type. Also, HACK: we can reach the `or` here if skip_types is | ||||
|             # something other than error. If so, bail out. | ||||
|  | ||||
|             ) or ( | ||||
|                 self.is_type(type, "string") and | ||||
|                 (self.is_type(instance, type) or type not in self._types) | ||||
|             )): | ||||
|                 return | ||||
|         else: | ||||
|             yield ValidationError(_types_msg(instance, types)) | ||||
|  | ||||
|     def validate_properties(self, properties, instance, schema): | ||||
|         if not self.is_type(instance, "object"): | ||||
|             return | ||||
|  | ||||
|         for property, subschema in iteritems(properties): | ||||
|             if property in instance: | ||||
|                 for error in self.iter_errors(instance[property], subschema): | ||||
|                     error.path.append(property) | ||||
|                     yield error | ||||
|             elif subschema.get("required", False): | ||||
|                 error = ValidationError( | ||||
|                     "%r is a required property" % (property,) | ||||
|                 ) | ||||
|                 error.path.append(property) | ||||
|                 error.validator = "required" | ||||
|                 yield error | ||||
|  | ||||
|     def validate_patternProperties(self, patternProperties, instance, schema): | ||||
|         for pattern, subschema in iteritems(patternProperties): | ||||
|             for k, v in iteritems(instance): | ||||
|                 if re.match(pattern, k): | ||||
|                     for error in self.iter_errors(v, subschema): | ||||
|                         yield error | ||||
|  | ||||
|     def validate_additionalProperties(self, aP, instance, schema): | ||||
|         if not self.is_type(instance, "object"): | ||||
|             return | ||||
|  | ||||
|         extras = set(_find_additional_properties(instance, schema)) | ||||
|  | ||||
|         if self.is_type(aP, "object"): | ||||
|             for extra in extras: | ||||
|                 for error in self.iter_errors(instance[extra], aP): | ||||
|                     yield error | ||||
|         elif not aP and extras: | ||||
|             error = "Additional properties are not allowed (%s %s unexpected)" | ||||
|             yield ValidationError(error % _extras_msg(extras)) | ||||
|  | ||||
|     def validate_dependencies(self, dependencies, instance, schema): | ||||
|         if not self.is_type(instance, "object"): | ||||
|             return | ||||
|  | ||||
|         for property, dependency in iteritems(dependencies): | ||||
|             if property not in instance: | ||||
|                 continue | ||||
|  | ||||
|             if self.is_type(dependency, "object"): | ||||
|                 for error in self.iter_errors(instance, dependency): | ||||
|                     yield error | ||||
|             else: | ||||
|                 dependencies = _list(dependency) | ||||
|                 for dependency in dependencies: | ||||
|                     if dependency not in instance: | ||||
|                         yield ValidationError( | ||||
|                             "%r is a dependency of %r" % (dependency, property) | ||||
|                         ) | ||||
|  | ||||
|     def validate_items(self, items, instance, schema): | ||||
|         if not self.is_type(instance, "array"): | ||||
|             return | ||||
|  | ||||
|         if self.is_type(items, "object"): | ||||
|             for index, item in enumerate(instance): | ||||
|                 for error in self.iter_errors(item, items): | ||||
|                     error.path.append(index) | ||||
|                     yield error | ||||
|         else: | ||||
|             for (index, item), subschema in zip(enumerate(instance), items): | ||||
|                 for error in self.iter_errors(item, subschema): | ||||
|                     error.path.append(index) | ||||
|                     yield error | ||||
|  | ||||
|     def validate_additionalItems(self, aI, instance, schema): | ||||
|         if not self.is_type(instance, "array"): | ||||
|             return | ||||
|         if not self.is_type(schema.get("items"), "array"): | ||||
|             return | ||||
|  | ||||
|         if self.is_type(aI, "object"): | ||||
|             for item in instance[len(schema):]: | ||||
|                 for error in self.iter_errors(item, aI): | ||||
|                     yield error | ||||
|         elif not aI and len(instance) > len(schema.get("items", [])): | ||||
|             error = "Additional items are not allowed (%s %s unexpected)" | ||||
|             yield ValidationError( | ||||
|                 error % _extras_msg(instance[len(schema.get("items", [])):]) | ||||
|             ) | ||||
|  | ||||
|     def validate_minimum(self, minimum, instance, schema): | ||||
|         if not self.is_type(instance, "number"): | ||||
|             return | ||||
|  | ||||
|         instance = float(instance) | ||||
|         if schema.get("exclusiveMinimum", False): | ||||
|             failed = instance <= minimum | ||||
|             cmp = "less than or equal to" | ||||
|         else: | ||||
|             failed = instance < minimum | ||||
|             cmp = "less than" | ||||
|  | ||||
|         if failed: | ||||
|             yield ValidationError( | ||||
|                 "%r is %s the minimum of %r" % (instance, cmp, minimum) | ||||
|             ) | ||||
|  | ||||
|     def validate_maximum(self, maximum, instance, schema): | ||||
|         if not self.is_type(instance, "number"): | ||||
|             return | ||||
|  | ||||
|         instance = float(instance) | ||||
|         if schema.get("exclusiveMaximum", False): | ||||
|             failed = instance >= maximum | ||||
|             cmp = "greater than or equal to" | ||||
|         else: | ||||
|             failed = instance > maximum | ||||
|             cmp = "greater than" | ||||
|  | ||||
|         if failed: | ||||
|             yield ValidationError( | ||||
|                 "%r is %s the maximum of %r" % (instance, cmp, maximum) | ||||
|             ) | ||||
|  | ||||
|     def validate_minItems(self, mI, instance, schema): | ||||
|         if self.is_type(instance, "array") and len(instance) < mI: | ||||
|             yield ValidationError("%r is too short" % (instance,)) | ||||
|  | ||||
|     def validate_maxItems(self, mI, instance, schema): | ||||
|         if self.is_type(instance, "array") and len(instance) > mI: | ||||
|             yield ValidationError("%r is too long" % (instance,)) | ||||
|  | ||||
|     def validate_uniqueItems(self, uI, instance, schema): | ||||
|         if uI and self.is_type(instance, "array") and not _uniq(instance): | ||||
|             yield ValidationError("%r has non-unique elements" % instance) | ||||
|  | ||||
|     def validate_pattern(self, patrn, instance, schema): | ||||
|         if self.is_type(instance, "string") and not re.match(patrn, instance): | ||||
|             yield ValidationError("%r does not match %r" % (instance, patrn)) | ||||
|  | ||||
|     def validate_minLength(self, mL, instance, schema): | ||||
|         if self.is_type(instance, "string") and len(instance) < mL: | ||||
|             yield ValidationError("%r is too short" % (instance,)) | ||||
|  | ||||
|     def validate_maxLength(self, mL, instance, schema): | ||||
|         if self.is_type(instance, "string") and len(instance) > mL: | ||||
|             yield ValidationError("%r is too long" % (instance,)) | ||||
|  | ||||
|     def validate_enum(self, enums, instance, schema): | ||||
|         if instance not in enums: | ||||
|             yield ValidationError("%r is not one of %r" % (instance, enums)) | ||||
|  | ||||
|     def validate_divisibleBy(self, dB, instance, schema): | ||||
|         if not self.is_type(instance, "number"): | ||||
|             return | ||||
|  | ||||
|         if isinstance(dB, float): | ||||
|             mod = instance % dB | ||||
|             failed = (mod > FLOAT_TOLERANCE) and (dB - mod) > FLOAT_TOLERANCE | ||||
|         else: | ||||
|             failed = instance % dB | ||||
|  | ||||
|         if failed: | ||||
|             yield ValidationError("%r is not divisible by %r" % (instance, dB)) | ||||
|  | ||||
|     def validate_disallow(self, disallow, instance, schema): | ||||
|         for disallowed in _list(disallow): | ||||
|             if self.is_valid(instance, {"type" : [disallowed]}): | ||||
|                 yield ValidationError( | ||||
|                     "%r is disallowed for %r" % (disallowed, instance) | ||||
|                 ) | ||||
|  | ||||
|     def validate_extends(self, extends, instance, schema): | ||||
|         if self.is_type(extends, "object"): | ||||
|             extends = [extends] | ||||
|         for subschema in extends: | ||||
|             for error in self.iter_errors(instance, subschema): | ||||
|                 yield error | ||||
|  | ||||
|     def validate_ref(self, ref, instance, schema): | ||||
|         if ref != "#" and not ref.startswith("#/"): | ||||
|             warnings.warn("jsonschema only supports json-pointer $refs") | ||||
|             return | ||||
|  | ||||
|         resolved = resolve_json_pointer(self.schema, ref) | ||||
|         for error in self.iter_errors(instance, resolved): | ||||
|             yield error | ||||
|  | ||||
|  | ||||
| Draft3Validator.META_SCHEMA = { | ||||
|     "$schema" : "http://json-schema.org/draft-03/schema#", | ||||
|     "id" : "http://json-schema.org/draft-03/schema#", | ||||
|     "type" : "object", | ||||
|  | ||||
|     "properties" : { | ||||
|         "type" : { | ||||
|             "type" : ["string", "array"], | ||||
|             "items" : {"type" : ["string", {"$ref" : "#"}]}, | ||||
|             "uniqueItems" : True, | ||||
|             "default" : "any" | ||||
|         }, | ||||
|         "properties" : { | ||||
|             "type" : "object", | ||||
|             "additionalProperties" : {"$ref" : "#", "type": "object"}, | ||||
|             "default" : {} | ||||
|         }, | ||||
|         "patternProperties" : { | ||||
|             "type" : "object", | ||||
|             "additionalProperties" : {"$ref" : "#"}, | ||||
|             "default" : {} | ||||
|         }, | ||||
|         "additionalProperties" : { | ||||
|             "type" : [{"$ref" : "#"}, "boolean"], "default" : {} | ||||
|         }, | ||||
|         "items" : { | ||||
|             "type" : [{"$ref" : "#"}, "array"], | ||||
|             "items" : {"$ref" : "#"}, | ||||
|             "default" : {} | ||||
|         }, | ||||
|         "additionalItems" : { | ||||
|             "type" : [{"$ref" : "#"}, "boolean"], "default" : {} | ||||
|         }, | ||||
|         "required" : {"type" : "boolean", "default" : False}, | ||||
|         "dependencies" : { | ||||
|             "type" : ["string", "array", "object"], | ||||
|             "additionalProperties" : { | ||||
|                 "type" : ["string", "array", {"$ref" : "#"}], | ||||
|                 "items" : {"type" : "string"} | ||||
|             }, | ||||
|             "default" : {} | ||||
|         }, | ||||
|         "minimum" : {"type" : "number"}, | ||||
|         "maximum" : {"type" : "number"}, | ||||
|         "exclusiveMinimum" : {"type" : "boolean", "default" : False}, | ||||
|         "exclusiveMaximum" : {"type" : "boolean", "default" : False}, | ||||
|         "minItems" : {"type" : "integer", "minimum" : 0, "default" : 0}, | ||||
|         "maxItems" : {"type" : "integer", "minimum" : 0}, | ||||
|         "uniqueItems" : {"type" : "boolean", "default" : False}, | ||||
|         "pattern" : {"type" : "string", "format" : "regex"}, | ||||
|         "minLength" : {"type" : "integer", "minimum" : 0, "default" : 0}, | ||||
|         "maxLength" : {"type" : "integer"}, | ||||
|         "enum" : {"type" : "array", "minItems" : 1, "uniqueItems" : True}, | ||||
|         "default" : {"type" : "any"}, | ||||
|         "title" : {"type" : "string"}, | ||||
|         "description" : {"type" : "string"}, | ||||
|         "format" : {"type" : "string"}, | ||||
|         "maxDecimal" : {"type" : "number", "minimum" : 0}, | ||||
|         "divisibleBy" : { | ||||
|             "type" : "number", | ||||
|             "minimum" : 0, | ||||
|             "exclusiveMinimum" : True, | ||||
|             "default" : 1 | ||||
|         }, | ||||
|         "disallow" : { | ||||
|             "type" : ["string", "array"], | ||||
|             "items" : {"type" : ["string", {"$ref" : "#"}]}, | ||||
|             "uniqueItems" : True | ||||
|         }, | ||||
|         "extends" : { | ||||
|             "type" : [{"$ref" : "#"}, "array"], | ||||
|             "items" : {"$ref" : "#"}, | ||||
|             "default" : {} | ||||
|         }, | ||||
|         "id" : {"type" : "string", "format" : "uri"}, | ||||
|         "$ref" : {"type" : "string", "format" : "uri"}, | ||||
|         "$schema" : {"type" : "string", "format" : "uri"}, | ||||
|     }, | ||||
|     "dependencies" : { | ||||
|         "exclusiveMinimum" : "minimum", "exclusiveMaximum" : "maximum" | ||||
|     }, | ||||
| } | ||||
|  | ||||
|  | ||||
| class Validator(Draft3Validator): | ||||
|     """ | ||||
|     Deprecated: Use :class:`Draft3Validator` instead. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     def __init__( | ||||
|         self, version=None, unknown_type="skip", unknown_property="skip", | ||||
|         *args, **kwargs | ||||
|     ): | ||||
|         super(Validator, self).__init__({}, *args, **kwargs) | ||||
|         warnings.warn( | ||||
|             "Validator is deprecated and will be removed. " | ||||
|             "Use Draft3Validator instead.", | ||||
|             DeprecationWarning, stacklevel=2, | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class ErrorTree(object): | ||||
|     """ | ||||
|     ErrorTrees make it easier to check which validations failed. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, errors=()): | ||||
|         self.errors = {} | ||||
|         self._contents = collections.defaultdict(self.__class__) | ||||
|  | ||||
|         for error in errors: | ||||
|             container = self | ||||
|             for element in reversed(error.path): | ||||
|                 container = container[element] | ||||
|             container.errors[error.validator] = error | ||||
|  | ||||
|     def __contains__(self, k): | ||||
|         return k in self._contents | ||||
|  | ||||
|     def __getitem__(self, k): | ||||
|         return self._contents[k] | ||||
|  | ||||
|     def __setitem__(self, k, v): | ||||
|         self._contents[k] = v | ||||
|  | ||||
|     def __iter__(self): | ||||
|         return iter(self._contents) | ||||
|  | ||||
|     def __len__(self): | ||||
|         child_errors = sum(len(tree) for _, tree in iteritems(self._contents)) | ||||
|         return len(self.errors) + child_errors | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return "<%s (%s errors)>" % (self.__class__.__name__, len(self)) | ||||
|  | ||||
|  | ||||
| def resolve_json_pointer(schema, ref): | ||||
|     """ | ||||
|     Resolve a local reference ``ref`` within the given root ``schema``. | ||||
|  | ||||
|     ``ref`` should be a local ref whose ``#`` is still present. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     if ref == "#": | ||||
|         return schema | ||||
|  | ||||
|     parts = ref.lstrip("#/").split("/") | ||||
|  | ||||
|     parts = map(unquote, parts) | ||||
|     parts = [part.replace('~1', '/').replace('~0', '~') for part in parts] | ||||
|  | ||||
|     try: | ||||
|         for part in parts: | ||||
|             schema = schema[part] | ||||
|     except KeyError: | ||||
|         raise InvalidRef("Unresolvable json-pointer %r" % ref) | ||||
|     else: | ||||
|         return schema | ||||
|  | ||||
|  | ||||
| def _find_additional_properties(instance, schema): | ||||
|     """ | ||||
|     Return the set of additional properties for the given ``instance``. | ||||
|  | ||||
|     Weeds out properties that should have been validated by ``properties`` and | ||||
|     / or ``patternProperties``. | ||||
|  | ||||
|     Assumes ``instance`` is dict-like already. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     properties = schema.get("properties", {}) | ||||
|     patterns = "|".join(schema.get("patternProperties", {})) | ||||
|     for property in instance: | ||||
|         if property not in properties: | ||||
|             if patterns and re.search(patterns, property): | ||||
|                 continue | ||||
|             yield property | ||||
|  | ||||
|  | ||||
| def _extras_msg(extras): | ||||
|     """ | ||||
|     Create an error message for extra items or properties. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     if len(extras) == 1: | ||||
|         verb = "was" | ||||
|     else: | ||||
|         verb = "were" | ||||
|     return ", ".join(repr(extra) for extra in extras), verb | ||||
|  | ||||
|  | ||||
| def _types_msg(instance, types): | ||||
|     """ | ||||
|     Create an error message for a failure to match the given types. | ||||
|  | ||||
|     If the ``instance`` is an object and contains a ``name`` property, it will | ||||
|     be considered to be a description of that object and used as its type. | ||||
|  | ||||
|     Otherwise the message is simply the reprs of the given ``types``. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     reprs = [] | ||||
|     for type in types: | ||||
|         try: | ||||
|             reprs.append(repr(type["name"])) | ||||
|         except Exception: | ||||
|             reprs.append(repr(type)) | ||||
|     return "%r is not of type %s" % (instance, ", ".join(reprs)) | ||||
|  | ||||
|  | ||||
| def _flatten(suitable_for_isinstance): | ||||
|     """ | ||||
|     isinstance() can accept a bunch of really annoying different types: | ||||
|         * a single type | ||||
|         * a tuple of types | ||||
|         * an arbitrary nested tree of tuples | ||||
|  | ||||
|     Return a flattened tuple of the given argument. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     types = set() | ||||
|  | ||||
|     if not isinstance(suitable_for_isinstance, tuple): | ||||
|         suitable_for_isinstance = (suitable_for_isinstance,) | ||||
|     for thing in suitable_for_isinstance: | ||||
|         if isinstance(thing, tuple): | ||||
|             types.update(_flatten(thing)) | ||||
|         else: | ||||
|             types.add(thing) | ||||
|     return tuple(types) | ||||
|  | ||||
|  | ||||
| def _list(thing): | ||||
|     """ | ||||
|     Wrap ``thing`` in a list if it's a single str. | ||||
|  | ||||
|     Otherwise, return it unchanged. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     if isinstance(thing, basestring): | ||||
|         return [thing] | ||||
|     return thing | ||||
|  | ||||
|  | ||||
| def _delist(thing): | ||||
|     """ | ||||
|     Unwrap ``thing`` to a single element if its a single str in a list. | ||||
|  | ||||
|     Otherwise, return it unchanged. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     if ( | ||||
|         isinstance(thing, list) and | ||||
|         len(thing) == 1 | ||||
|         and isinstance(thing[0], basestring) | ||||
|     ): | ||||
|         return thing[0] | ||||
|     return thing | ||||
|  | ||||
|  | ||||
| def _uniq(container): | ||||
|     """ | ||||
|     Check if all of a container's elements are unique. | ||||
|  | ||||
|     Successively tries first to rely that the elements are hashable, then | ||||
|     falls back on them being sortable, and finally falls back on brute | ||||
|     force. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     try: | ||||
|         return len(set(container)) == len(container) | ||||
|     except TypeError: | ||||
|         try: | ||||
|             sort = sorted(container) | ||||
|             sliced = itertools.islice(container, 1, None) | ||||
|             for i, j in zip(container, sliced): | ||||
|                 if i == j: | ||||
|                     return False | ||||
|         except (NotImplementedError, TypeError): | ||||
|             seen = [] | ||||
|             for e in container: | ||||
|                 if e in seen: | ||||
|                     return False | ||||
|                 seen.append(e) | ||||
|     return True | ||||
|  | ||||
|  | ||||
| def validate(instance, schema, cls=Draft3Validator, *args, **kwargs): | ||||
|     """ | ||||
|     Validate an ``instance`` under the given ``schema``. | ||||
|  | ||||
|     First verifies that the provided schema is itself valid, since not doing so | ||||
|     can lead to less obvious failures when validating. If you know it is or | ||||
|     don't care, use ``YourValidator(schema).validate(instance)`` directly | ||||
|     instead (e.g. ``Draft3Validator``). | ||||
|  | ||||
|     ``cls`` is a validator class that will be used to validate the instance. | ||||
|     By default this is a draft 3 validator.  Any other provided positional and | ||||
|     keyword arguments will be provided to this class when constructing a | ||||
|     validator. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|  | ||||
|     meta_validate = kwargs.pop("meta_validate", None) | ||||
|  | ||||
|     if meta_validate is not None: | ||||
|         warnings.warn( | ||||
|             "meta_validate is deprecated and will be removed. If you do not " | ||||
|             "want to validate a schema, use Draft3Validator.validate instead.", | ||||
|             DeprecationWarning, stacklevel=2, | ||||
|         ) | ||||
|  | ||||
|     if meta_validate is not False:  # yes this is needed since True was default | ||||
|         cls.check_schema(schema) | ||||
|     cls(schema, *args, **kwargs).validate(instance) | ||||
		Reference in New Issue
	
	Block a user