M. of CA
M. of CA

Reputation: 1546

Python Yaml check config file

i am using yaml to store my config data. once i load the file. i want to check if certain Key and Values exist.

yaml content:

sftp:
 host: server
 username: user
 password: pass
 path: /mnt/Storage/Folder/

filename: blah

so i need to know if these key values exists in the yaml file. since these are required in order to work properly. what is the best way to do this? i can use this method below, it i would have to manually check on by one. The required key values are going to grow, this is just the minimum.

if (key in data):
    return True

Upvotes: 0

Views: 3352

Answers (2)

mknecht
mknecht

Reputation: 1255

There are a couple of approaches. Since your input is more complex than, say, a dict with two keys, I'd go with number four, a library for path expressions, like jsonpath.

  1. Completely manual

    You navigate thru the object tree, raise an exception if something is unexpected.

    Pro/con: Maximal control, also over error messages, but minimum descriptiveness.

  2. Manual path evaluation

    You define the expected “paths” and then have a (possibly nested) loop to go thru each, and evaluate if the input object matches the path. Philips answer falls into that category.

    Questions like this one about xpath for dicts might point you a favorable direction, implementation-wise.

    Pro/con: Can be descriptive, but might be non-trivial to get the evaluation right for all corner cases.

  3. Builtin evaluation

    You define a set of functions that must evaluate to a non-None value. Python does the evaluation for you. Something along these lines:

    must_evaluate = {
        lambda o: o["sftp"]["host"],
        lambda o: o["sftp"]["username"],
        lambda o: o["sftp"]["passowrd"],
        lambda o: o["sftp"]["path"],
        lambda o: o["filename"],
    }
    
    
    def check_with_builtin_resolution(obj):
        def check_lambda_on_obj(l):
            try:
                if l(obj) is not None:
                    return True
            except AttributeError:
                pass
            except KeyError:
                pass
            return False
    
        for l in must_evaluate:
            if not check_lambda_on_obj(l):
                return False
        return True
    

    Pro/con: Quite descriptive, though not as nice as paths in 2 or 4 might be. Biggest con: No trivial way to describe, which expectation failed, since lambdas don't print well.

  4. Library for path expressions

    Use a library for path expressions, like jsonpath. Iterate over each expression and raise an exception, when it does not evaluate to what you want.

    Pro/con: Legible, and good support for decent error messages.

  5. Library for object tree checking

    Maybe some other poster is aware of existing, mature work. I myself being bothered by this problem have started to fiddle with parseobj, but can't recommend that for real usage just yet.

Upvotes: 1

Philip Massey
Philip Massey

Reputation: 1429

So in order to make sure every key you need exists, you are going to have to check for each one explicitly somehow. However, if the keys are unique, then you could use sets to make it a bit cleaner, e.g.,

needed = set(["host", "username", "password"]) #etc.

then to detect / read in the YAML file:

seen = set()
for key, value in data.iteritems():
    seen.add(key)

return needed.issubset(seen)

Upvotes: 0

Related Questions