def _is_valid(self, log_file: Optional[Union[Logger, TextIO]] = None) -> bool: log = Logger() if log_file is None else log_file if isinstance( log_file, Logger) else Logger(log_file) nerrors = log.nerrors if self._context.TYPE and getattr(self, self._context.TYPE, "") != self._class_name \ and self._class_name not in self._context.TYPE_EXCEPTIONS: if log.log("Type mismatch - Expected: {} Actual: {}".format( self._class_name, getattr(self, self._context.TYPE))): return False for name in self._members.keys(): entry = getattr(self, name) if not self._is_valid_element(log, name, entry): return False if self._strict: # Test each attribute against the schema for k, v in self._strip_nones(self.__dict__).items(): if k not in self._members and k != self._context.TYPE \ and k not in self._context.IGNORE and k != "@context": if not self._is_valid_element(log, k, v): if log.log("Extra element: {}: {}".format(k, v)): return False return log.nerrors == nerrors
def _is_valid_element(self, log: Logger, name: str, val: Type[JSGValidateable]) -> bool: if name not in self._members: return any(e._is_valid_element for e in self._reference_types) else: etype = self._members[name] if etype is JSGNull: return val is JSGNull or val is None if val is None and type(etype) is type(AnyType): return False if val is not None and val is not Empty and isinstance( val, JSGArray): if not val._validate(cast(list, val), log)[0] and not log.logging: return False elif not conforms(val, etype, self._context.NAMESPACE ): # Note: None and absent are equivalent if val is None or val is Empty: if log.log("{}: Missing required field: '{}'".format( self.__class__.__name__, name)): return False else: if log.log( "{}: Type mismatch for {}. Expecting: {} Got: {}". format(self.__class__.__name__, name, etype, type(val))): return False elif val is not None and not self._test( val, log): # Make sure that entry conforms to its own type return False return True
def _is_valid(self, log_file: Optional[Union[Logger, TextIO]] = None) -> bool: log = Logger() if log_file is None else log_file if isinstance(log_file, Logger) else Logger(log_file) nerrors = log.nerrors nitems = len(self._strip_nones(self.__dict__)) if nitems < self._min: if log.log(f"Number of elements is {nitems} which is less than the minimum number ({self._min})"): return False if self._max is not None and nitems > self._max: if log.log(f"Number of elements is {nitems} which is greater than the minimum number ({self._max})"): return False super()._is_valid(log) return nerrors == log.nerrors
def _is_valid_element(self, log: Logger, name: str, entry: Type[JSGValidateable]) -> bool: if self._name_filter is not None: if not self._name_filter.matches(name): #if log.log(f"Illegal Object Map key: {name}={entry}"): if log.log("Illegal Object Map key: " + name + "=" + entry): return False return super()._is_valid_element(log, name, entry)
class JSGReadMeTestCase(unittest.TestCase): log = Logger(sys.stdout) def eval_for_error(self, fn: str, mod, error: str): fn_in_json = json_load(fn) expected = fn_in_json._ERROR del fn_in_json._ERROR with self.assertRaises(ValueError) as context: r = load(fn, mod) self.assertEqual(expected, str(context.exception)) def eval_python(self, cwd: str, dirpath: str, fn: str) -> None: basefile = fn.rsplit('.', 1)[0] outfile = os.path.abspath(os.path.join(cwd, "py", basefile + ".py")) self.assertEqual( 0, generate([ os.path.relpath(os.path.join(dirpath, fn)), "-o", outfile, "-nh" ])) mod = import_module("tests_standalone.test_jsg_readme.py." + basefile) num_evaluated = 0 for dirpath, _, filenames in os.walk(os.path.join(cwd, "json")): for filename in filenames: if filename.startswith(basefile) and filename.endswith( ".json"): num_evaluated += 1 full_fn = os.path.join(dirpath, filename) if "_f" not in os.path.basename(full_fn): r = load(full_fn, mod) self.assertTrue(r._is_valid(log)) else: self.eval_for_error( full_fn, mod, "ValueError: Unknown attribute: text=left in 2017") # TODO: complete this test # self.assertTrue(num_evaluated > 0, f"{fn} has no json equivalents") @unittest.skipIf( False, "This test has to be run alone -- namespace conflicts otherwise ") def test_jsg_readme(self): cwd = os.path.abspath(os.path.dirname(__file__)) num_evaluated = 0 for dirpath, _, filenames in os.walk(os.path.join(cwd, "jsg")): for fn in filenames: if fn.endswith(".jsg"): num_evaluated += 1 self.eval_python(cwd, dirpath, fn) self.assertEqual(6, num_evaluated) @unittest.skipIf(True, "Outsdanding issue here on get") def test_gsg_1(self): # TODO: Fix this problem! self.assertTrue(False, "Rename ge1_f1.json to get.json")
def _jsg_type_for(self, name: str, element: Any, poss_types: Union[type, Tuple[type]]) -> JSGValidateable: et = self._map_jsg_type(name, element, poss_types) if et is not None: return et #raise ValueError(f"Wrong type for {name}: {Logger.json_repr(element)} - expected:" # f" {poss_types} got {type(element).__name__}") raise ValueError("Wrong type for " + name + ": " + Logger.json_repr(element) + " - expected: " + poss_types + " got " + type(element.__name__))
import sys import os import unittest from importlib import import_module from pyjsg.jsglib.loader import load from pyjsg.jsglib.logger import Logger from pyjsg.parser_impl.generate_python import generate from jsonasobj import load as json_load log = Logger(sys.stdout) class JSGReadMeTestCase(unittest.TestCase): log = Logger(sys.stdout) def eval_for_error(self, fn: str, mod, error: str): fn_in_json = json_load(fn) expected = fn_in_json._ERROR del fn_in_json._ERROR with self.assertRaises(ValueError) as context: r = load(fn, mod) self.assertEqual(expected, str(context.exception)) def eval_python(self, cwd: str, dirpath: str, fn: str) -> None: basefile = fn.rsplit('.', 1)[0] outfile = os.path.abspath(os.path.join(cwd, "py", basefile + ".py")) self.assertEqual( 0,