Package: uplook
What?An opinionated Python module to handle configuration values with support for
external data sources.How?TheUpLookclass takes an arbitrary number of key/values. These variables
are stored and accessible as regular object attributes. Values of type
<<dict>> can be accessed in dotted format.A value can also be alookup functionby using a special syntax:+-> The name of the funtion.  1 tilde means the function is a static lookup.
    |   2 tildes means a lookup is done every time the attribute is accessed.
    |
    |         +------------+------> An optional pair of values.  The first value is the <key>
    |         |         |           to lookup.  The second value is a default value to return
    |         |         |           in case the key lookup fails.
~~function("key", "default value")
                     |
                     |
                     +-> The default value can also be JSON.  In that case you should not use
                         quotes around the value.An actual example would look like:>>>>u=UpLook(servers='~~consul("first", [])')For this to work you first need to register the function responsible for
retrieving the data.  Depending what is required to lookup the desired value
you could feed a <key> value to the function.An (silly) example lookup function looks like:defshow_members(cluster_name):ifcluster_name=="first"return["one","two","three"]else:raiseException("Unknown cluster")>>>>u.registerLookup("consul",show_members)Accessing valueu.value.serverwill then trigger the the registeredlookupfunction and return its value:>>>>u.value.servers["one","two","three"]When the registered function return an Exception, the default value is returned:>>>>u=UpLook(servers='~~consul("blahblahblah", [])')>>>>u.value.servers[]RemarksWhen executing the lookup function fails and a default value has been
defined, no error is raised and the default value is returned.When executing the lookup function fails andnodefault value has been
defined an error is raised.When the default value is between single or double quotes, it is returned
literally.  When thedefault valueisnotbetween quotes, it is
considered to be JSON.  When The JSON is invalid, an error is returned.More examplesProvided kwargs are accessible as attributes>>>>fromuplookimportUpLook>>>>u=UpLook(one=1,two=2)>>>>uUpLook({'two':2,'one':1})>>>>u.value.one1Dict argument values are recursively mapped to attributes>>>>fromuplookimportUpLook>>>>u=UpLook(levels={"level1":{"level2":{"level3":"hello"}}})>>>>uUpLook({'levels':{'level1':{'level2':{'level3':'hello'}}}})>>>>u.value.levels.level1.level2.level3'hello'Get the data portion without all helper methods>>>>fromuplookimportUpLook>>>>u=UpLook(one=1,two=2)>>>>uUpLook({'two':2,'one':1})>>>>data=u.get()>>>>data.one1Get a simple dict representation of the data>>>>fromuplookimportUpLook>>>>u=UpLook(one=1,two=2)>>>>uUpLook({'two':2,'one':1})>>>>data=u.dump(){'two':2,'one':1}Iterate over key/value pairs of a data container>>>>fromuplookimportUpLook>>>>u=UpLook(one=1,two=2)>>>>uUpLook({'two':2,'one':1})>>>>forkey,valueinu.get():....print"key:%s, value:%s"%(key,value)....key:two,value:2key:one,value:1External lookup valuesSome value lookup functionfromuplookimportUpLookfromuplook.errorsimportNoSuchValuedefsomeLookupFunction(key):data={"value.number.one":"hi","value.number.two":"this","value.number.three":"is","value.number.four":"a","value.number.five":"silly","value.number.six":"demo"}try:returndata[key]exceptKeyError:raiseNoSuchValue("%sis an unknown value."%(key))defrandomInt(max):returnrandom.randint(0,max)Initialize an Uplook instance with a dynamic and static lookup>>>instance=UpLook(static='~fubar("value.number.one", "unknown")',>>>dynamic='~~random(100)',>>>normal='hello')List all user defined lookup functions>>>forfunctionininstance.listfunctions():printfunctionfubarrandom>>>Register lookup functions>>>instance.registerLookup("fubar",someLookupFunction)>>>instance.registerLookup("random",randomInt)Access a static lookup value>>>printtest.value.statichi>>>printtest.value.statichiAccess a dynamic lookup value>>>printtest.value.dynamic>>>81>>>printtest.value.dynamic>>>16