#!/usr/local/bin/python2.3 """check_data Read in an Grouch schema and use it to type-check a Python object graph. The source of the data is currently limited to either a ZODB database or a pickle file. """ # created 2001/08/17, Greg Ward (from MEMS Exchange-specific check_db) __revision__ = "$Id: check_data 21022 2003-03-10 20:02:59Z gward $" import sys, os import getopt from cPickle import load from grouch.context import TypecheckContext from grouch.script_util import announce, warn def get_root_object (data_source, format, storage): """Open the data source according to format and storage. Return the root of the object graph. """ if format == "pickle": file = open(data_source) return load(file) elif format == "zodb": import ZODB from ZODB import DB if storage == "file": from ZODB.FileStorage import FileStorage storage = FileStorage(data_source) elif storage == "client": from ZEO.ClientStorage import ClientStorage (host, port) = data_source.split(":") storage = ClientStorage((host, port), var="/tmp") db = DB(storage) conn = db.open() return conn.root() else: raise RuntimeError, \ ("this can't happen (format = %r, storage = %r)" % (format, storage)) # get_root_object () def main (): global VERBOSITY prog = os.path.basename(sys.argv[0]) args = sys.argv[1:] usage = """\ usage: %s [options] schema_file data_source options: -f FMT, --format=FMT specify the format of the data source (currently: \"pickle\", \"zodb\") -s STG, --storage=STG specify the storage of a ZODB (currently: \"file\", \"client\") -n NAME, --root-name=NAME set the name of the root object (to make error messages more readable) [default: "root"] -t TYPE, --root-type=TYPE set the type of the root object [default: the type of the root isn't enforced, only the type of objects reachable from it] schema_file must be a pickled Grouch schema as created by gen_schema. data_source depends on FMT and STG. For \"pickle\" and ZODB FileStorage, it should just be a filename. For ZODB ClientStorage (ZEO), it should be the host:port of the ZEO server. """ % prog try: (opts, args) = getopt.getopt(args, "f:s:n:t:vq", ["format=", "storage=", "root-name=", "root-type=",]) except getopt.error, msg: sys.exit(usage + str(msg)) format = "pickle" storage = None # only applicable for ZODB root_name = "root" root_type = None VERBOSITY = 1 for (opt, val) in opts: if opt in ("-f", "--format"): format = val elif opt in ("-s", "--storage"): storage = val elif opt in ("-n", "--root-name"): root_name = val elif opt in ("-t", "--root-type"): root_type = val elif opt == "-v": VERBOSITY += 1 elif opt == "-q": VERBOSITY = 0 if format not in ("pickle", "zodb"): sys.exit(usage + "bad format %r: must be pickle or zodb" % format) if format != "zodb" and storage: warn("storage ignored for non-ZODB formats") storage = None if format == "zodb" and storage is None: warn("using default file storage for ZODB database") storage = "file" if len(args) != 2: sys.exit(usage + "wrong number of arguments") (schema_filename, data_source) = args announce("Loading schema...") file = open(schema_filename) schema = load(file) announce("\n") if root_type: try: root_type = schema.parse_type(root_type) except ValueError, err: sys.exit("invalid root type: %s" % err) root_object = get_root_object(data_source, format, storage) if format == "zodb": mode = "zodb" else: mode = "memory" context = TypecheckContext(mode=mode, start_name=root_name) announce("Checking object graph...\n") if root_type: root_type.check_value(root_object, context) else: schema.check_value(root_object, context) announce("found %d error(s)\n" % context.num_errors()) sys.exit(context.num_errors() > 0) # main () if __name__ == "__main__": try: main() except KeyboardInterrupt: sys.exit("interrupted")