From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org) by finch.gentoo.org with esmtp (Exim 4.60) (envelope-from ) id 1SfdFS-00026v-7V for garchives@archives.gentoo.org; Fri, 15 Jun 2012 20:36:02 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 1DDC5E09E2; Fri, 15 Jun 2012 20:34:39 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id CA94AE09E2 for ; Fri, 15 Jun 2012 20:34:33 +0000 (UTC) Received: from hornbill.gentoo.org (hornbill.gentoo.org [94.100.119.163]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id D53261B4064 for ; Fri, 15 Jun 2012 20:34:32 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by hornbill.gentoo.org (Postfix) with ESMTP id 432A7E5448 for ; Fri, 15 Jun 2012 20:34:30 +0000 (UTC) From: "André Erdmann" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "André Erdmann" Message-ID: <1339791371.b556769cc6a68d3dfc77e66d1ee5cf498177e56a.dywi@gentoo> Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/ X-VCS-Repository: proj/R_overlay X-VCS-Files: roverlay/config.py X-VCS-Directories: roverlay/ X-VCS-Committer: dywi X-VCS-Committer-Name: André Erdmann X-VCS-Revision: b556769cc6a68d3dfc77e66d1ee5cf498177e56a X-VCS-Branch: master Date: Fri, 15 Jun 2012 20:34:30 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: fb4a3045-6320-4780-8bf1-dcc5b5d6a4e6 X-Archives-Hash: c8f6edba61fc646a509b90079d33923f commit: b556769cc6a68d3dfc77e66d1ee5cf498177e56a Author: Andr=C3=A9 Erdmann mailerd de> AuthorDate: Fri Jun 15 20:16:11 2012 +0000 Commit: Andr=C3=A9 Erdmann mailerd de> CommitDate: Fri Jun 15 20:16:11 2012 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/R_overlay.git= ;a=3Dcommit;h=3Db556769c config: fixes/enhancements * config_path simpler now * added ConfigTree.visualize() which can be used to print/output the config tree * added fs_abs modified: roverlay/config.py --- roverlay/config.py | 108 +++++++++++++++++++++++++++++++++++++++++++---= ------ 1 files changed, 90 insertions(+), 18 deletions(-) diff --git a/roverlay/config.py b/roverlay/config.py index b1710f9..dbcdfe7 100644 --- a/roverlay/config.py +++ b/roverlay/config.py @@ -25,6 +25,15 @@ def access(): return ConfigTree() if ConfigTree.instance is None else ConfigTree.inst= ance # --- end of access (...) --- =20 +def get_config_path ( key ): + """Creates a config path for key.""" + _path =3D key.split ( '.' ) if isinstance ( key, str ) else key + if isinstance ( _path, ( list, tuple ) ): + # config paths are [ CAPSLOCK, CAPSLOCK,.... , lowercase item ] + return [ x.lower() if x =3D=3D _path [-1] else x.upper() for x in _pat= h ] + else: + return _path +# --- end of get_config_path (...) --- =20 def get ( key, fallback_value=3DNone, fail_if_unset=3DFalse ): """Searches for key in the ConfigTree and returns its value if possible= , @@ -87,15 +96,17 @@ class ConfigTree ( object ): # ** int -- integer # ** yesno -- value must evaluate to 'yes' or 'no' (on,off,y,n,1,0...= ) # ** fs_path -- ~ will be expanded - # ** fs_dir -- fs_path and value must be a dir if it exists - # ** fs_file -- fs_path and value must be a file if it exists + # ** fs_abs -- fs_path and path will be converted into an absolute one + # (pwd + path) + # ** fs_dir -- fs_abs and value must be a dir if it exists + # ** fs_file -- fs_abs and value must be a file if it exists # TODO** fs_prog -- fs_file (and fs_path) and value must be executable = (TODO) # ** regex -- value is a regex and will be compiled (re.compile(..)) # # multiple types are generally not supported ('this is an int or a st= r'), - # but subtypes are (list of yesno), which can be specified by either + # but subtypes are ('list of yesno'), which can be specified by eithe= r # using a list of types ['list', 'yesno'] or by separating the types - # with a colon list:yesno, which is parsed in a left-to-right order. + # with a colon 'list:yesno', which is parsed in a left-to-right order= . # Nested subtypes such as list:slist:int:fs_file:list may lead to err= ors. # CONFIG_ENTRY_MAP =3D dict ( @@ -105,7 +116,7 @@ class ConfigTree ( object ): ), log_file =3D dict ( # setting path to LOG.FILE.main to avoid collision with LOG.FILE.* - path =3D [ 'LOG', 'FILE', 'main' ], + path =3D [ 'LOG', 'FILE', 'Main' ], value_type =3D 'fs_file', ), log_file_resolved =3D dict ( @@ -160,7 +171,9 @@ class ConfigTree ( object ): # --- end of __init__ (...) --- =20 =20 - def _findpath ( self, path, root=3DNone, create=3DFalse, value=3DNone )= : + def _findpath ( self, path, + root=3DNone, create=3DFalse, value=3DNone, forcepath=3DFalse, forceval= =3DFalse + ): """All-in-one method that searches for a config path. It is able to create the path if non-existent and to assign a value to it. @@ -173,11 +186,16 @@ class ConfigTree ( object ): * value -- assign value to the last path element an empty dict will be created if this is None and create is True + * forcepath -- if set and True: do not 'normalize' path if path is a l= ist + * forceval -- if set and True: accept None as value """ if path is None: return root - elif isinstance ( path, str ): - path =3D path.split ( '.' ) if path else [] + elif isinstance ( path, ( list, tuple ) ) and forcepath: + pass + else: + path =3D get_config_path ( path ) + =20 config_position =3D self._config if root is None else root =20 @@ -186,7 +204,7 @@ class ConfigTree ( object ): for k in path: if len (k) =3D=3D 0: continue - if k =3D=3D path [-1] and not value is None: + if k =3D=3D path [-1] and ( forceval or not value is None ): # overwrite entry config_position [k] =3D value elif not k in config_position: @@ -201,7 +219,7 @@ class ConfigTree ( object ): =20 # --- end of _findpath (...) --- =20 - def inject ( self, key, value, suppress_log=3DFalse ): + def inject ( self, key, value, suppress_log=3DFalse, **kw_extra ): """This method offer direct write access to the ConfigTree. No checks will be performed, so make sure you know what you're doing. =20 @@ -211,6 +229,7 @@ class ConfigTree ( object ): if a path component is missing ('.. create= s root, new and entry if required) * value -- value to be assigned + * **kw_extra -- extra keywords for _findpath, e.g. forceval=3DTrue =20 returns: None (implicit) """ @@ -223,7 +242,7 @@ class ConfigTree ( object ): else: self.logger.debug ( msg ) =20 - self._findpath ( key, create=3DTrue, value=3Dvalue ) + self._findpath ( key, create=3DTrue, value=3Dvalue, **kw_extra ) # --- end of inject (...) --- =20 def get ( self, key, fallback_value=3DNone, fail_if_unset=3DFalse ): @@ -320,6 +339,14 @@ class ConfigTree ( object ): return os.path.expanduser ( val ) if val else None # --- end of fs_path (...) --- =20 + def fs_abs ( val ): + """val is a filesystem path - returns absolute + expanded path.""" + if val: + return os.path.abspath ( os.path.expanduser ( val ) ) + else: + return None + + def fs_file ( val ): """"val is a file - returns expanded path if it is an existent file or it does not exist. @@ -327,8 +354,8 @@ class ConfigTree ( object ): arguments: * val -- """ - if val: - retval =3D os.path.expanduser ( val ) + retval =3D fs_abs ( val ) + if retval: if os.path.isfile ( retval ) or not os.path.exists ( retval ): return retval =20 @@ -342,8 +369,8 @@ class ConfigTree ( object ): arguments: * val -- """ - if val: - retval =3D os.path.expanduser ( val ) + retval =3D fs_abs ( val ) + if retval: if os.path.isdir ( retval ) or not os.path.exists ( retval ): return retval =20 @@ -439,9 +466,9 @@ class ConfigTree ( object ): if 'path' in cref: path =3D cref ['path'] else: - path =3D low_option.split ( '_' ) - for n in range ( len ( path ) - 1 ): - path [n] =3D path [n].upper() + path =3D option.split ( '_' ) + + path =3D get_config_path ( path ) =20 # need a valid path if path: @@ -630,3 +657,48 @@ class ConfigTree ( object ): return fdef =20 # --- end of _make_field_definition (...) --- + + + def _tree_to_str ( self, root, name, level=3D0 ): + """Returns string representation of a config tree rooted at root. + Uses recursion (DFS). + + arguments: + * root -- config 'root', is a value (config 'leaf') or a dict ('tree'= ) + * name -- + * level -- + + returns: string representation of the given root + """ + + indent =3D level * ' ' + var_indent =3D indent + '* ' + if root is None: + return "%s%s is unset\n" % ( var_indent, name ) + elif len ( root ) =3D=3D 0: + return "%s%s is empty\n" % ( var_indent, name ) + elif isinstance ( root, dict ): + extra =3D ''.join ( [ + self._tree_to_str ( n, r, level+1 ) for r, n in root.items() + ] ) + return "%s%s {\n%s%s}\n" % ( indent, name, extra, indent ) + else: + return "%s%s =3D '%s'\n" % ( var_indent, name, root ) + # --- end of _tree_to_str (...) --- + + def visualize ( self, into=3DNone ): + """Visualizes the ConfigTree, + either into a file-like object or as return value. + + arguments: + * into -- if not None: write into file + + returns: string if into is None, else None (implicit) + """ + _vis =3D self._tree_to_str ( self._config, 'ConfigTree', level=3D0 ) + if into is None: + return _vis + else: + into.write ( _vis ) + # --- end of visualize (...) --- +