Source code encoding is now utf8. Added experimental XPath style query for configurat...
authorFrederic Jolliton <frederic@jolliton.com>
Sun, 26 Jun 2005 03:29:12 +0000 (03:29 +0000)
committerFrederic Jolliton <frederic@jolliton.com>
Sun, 26 Jun 2005 03:29:12 +0000 (03:29 +0000)
* Converted all source code to utf8 encoding (instead of iso-8859-1.)

* Added module confparser_ext that include stuff to query (retrieve)
  nodes in a configuration tree from a string describing what to get.
git-archimport-id: frederic@jolliton.com--2005-private/confparser--main--0.1--patch-11

basicparser.py
basicvalidator.py
confparser.py
confparser_ext.py [new file with mode: 0644]
install
install_conf.py

index b1d9273..5952f4a 100644 (file)
@@ -1,8 +1,8 @@
-# -*- coding: iso-8859-1 -*-
+# -*- coding: utf-8 -*-
 
 #
 # Basic parser
-# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
+# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -138,3 +138,8 @@ class Parser :
                r += prefix + self.text[ lineStart : lineEnd ].replace( '\t' , ' ' ) + '\n'
                r += prefix + ' ' * ( self.pos - lineStart ) + '^' + '\n'
                return r
+
+# Local Variables:
+# tab-width: 4
+# python-indent: 4
+# End:
index eeb0965..641cbc4 100644 (file)
@@ -1,8 +1,8 @@
-# -*- coding: iso-8859-1 -*-
+# -*- coding: utf-8 -*-
 
 #
 # Basic validator
-# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
+# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -80,3 +80,8 @@ def validate( node , validator ) :
                meta = validate.lastNode[ 3 ]
                raise Error( 'at line %d, column %d, %s' 
                        % ( meta[ 0 ] , meta[ 1 ] , str( e ) ) )
+
+# Local Variables:
+# tab-width: 4
+# python-indent: 4
+# End:
index e1fbb3d..b583bb3 100644 (file)
@@ -1,8 +1,8 @@
-# -*- coding: iso-8859-1 -*-
+# -*- coding: utf-8 -*-
 
 #
 # Configuration parser
-# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
+# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -198,13 +198,21 @@ def readConfiguration( filename , validator = None ) :
                raise Exception( 'While reading file %s:\n%s' % ( filename , str( e ) ) )
        return conf
 
+def readConfigurationExt( filename , validator = None ) :
+
+       conf = readConfiguration( filename , validator )
+       if conf is not None :
+               import confparser_ext
+               conf = confparser_ext.confToNodeset( conf )
+       return conf
+
 #--[ Dump configuration tree ]------------------------------------------------
 
 def printTreeInner( t , prt = sys.stdout.write , prefix = '' , verbose = False ) :
 
        prt( prefix )
        prt( t[ 0 ] )
-       for kw in t[ 1 ] :
+       for kw in t[ 1 ] or [] :
                prt( ' ' + str( kw ) )
        if t[ 2 ] :
                prt( ' {' )
@@ -227,3 +235,8 @@ def printTree( t , prt = sys.stdout.write , prefix = '' , verbose = False ) :
 
        for sub in t[ 2 ] or [] :
                printTreeInner( sub , prt , prefix , verbose )
+
+# Local Variables:
+# tab-width: 4
+# python-indent: 4
+# End:
diff --git a/confparser_ext.py b/confparser_ext.py
new file mode 100644 (file)
index 0000000..a49846e
--- /dev/null
@@ -0,0 +1,262 @@
+# -*- coding: utf-8 -*-
+
+#
+# Configuration parser extension
+# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+
+#
+# This module is sort of prototype to support xpath-like
+# way to fetch certain nodes from a configuration tree.
+#
+# Code is absolutely not nice.. It's really just for experimentation
+# and need to be rewritten completely.
+#
+
+import re
+
+def flatten( lst ) :
+
+       '''Flatten a list or tuple.
+       
+       [[1,2],[3,[4,5]]] => [1,2,3,4,5]'''
+
+       if isinstance( lst , list ) :
+               r = []
+               for item in lst :
+                       r += flatten( item )
+       elif isinstance( lst , tuple ) :
+               r = ()
+               for item in lst :
+                       r += tuple( flatten( item ) )
+       else :
+               r = ( lst , )
+       return r
+
+def quote( s ) :
+
+       s = str( s )
+       if re.search( r'^(?:\d+|[a-z_][a-z0-9_-]*)$' , s , re.I ) is None :
+               s = '"%s"' % s.replace( '\\' , '\\\\' ).replace( '"' , '\\"' )
+       return s
+
+class NodeSet :
+
+       def __init__( self , *nodes ) :
+
+               self.__nodes = []
+               self.__iadd__( flatten( nodes ) )
+
+       def __iadd__( self , *others ) :
+
+               others = flatten( others )
+               for item in others :
+                       assert isinstance( item , ( Node , NodeSet ) )
+               for item in others :
+                       if isinstance( item , NodeSet ) :
+                               self.__nodes += item.__nodes
+                       else :
+                               self.__nodes.append( item )
+               return self
+
+       def __getitem__( self , place ) :
+
+               if isinstance( place , str ) :
+                       return select( self , place )
+               return self.__nodes[ place ]
+
+       def __len__( self ) :
+
+               return len( self.__nodes )
+
+       def pstr( self , indent = '' ) :
+
+               return '\n'.join( [ node.pstr( indent ) for node in self.__nodes ] )
+
+       def __repr__( self ) :
+
+               return '<NodeSet with %d elements>' % len( self.__nodes )
+
+class Node :
+
+       def __init__( self , name , *values ) :
+
+               self.__name = name
+               self.__values = flatten( values )
+               self.__subs = NodeSet()
+
+       def __iadd__( self , *others ) :
+
+               self.__subs += others
+               return self
+
+       def __getName( self ) :
+
+               return self.__name
+
+       name = property( __getName )
+
+       def __getSubs( self ) :
+
+               return self.__subs
+
+       subs = property( __getSubs )
+
+       def __getValues( self ) :
+
+               return self.__values
+
+       values = property( __getValues )
+
+       def pstr( self , indent = '' ) :
+
+               r = indent + quote( self.__name ) + ' '
+               if self.__values :
+                       r += ' '.join( map( quote , self.__values ) ) + ' '
+               if len( self.__subs ) != 0 :
+                       r += '{\n' + self.__subs.pstr( indent + '  ' ) + '\n' + indent + '}'
+               else :
+                       r += ';'
+               return r
+
+       def __getitem__( self , place ) :
+
+               if isinstance( place , str ) :
+                       return select( self , place )
+               return self.subs[ place ]
+
+       def __repr__( self ) :
+
+               return '<Node :name %r>' % ( self.__name , )
+
+def confToNodeset( node ) :
+
+       def confToNodeset_( node ) :
+
+               if isinstance( node , tuple ) :
+                       result = Node( node[ 0 ] , node[ 1 ] or [] )
+                       result += confToNodeset_( node[ 2 ] )
+               elif isinstance( node , list ) :
+                       result = NodeSet( [ confToNodeset_( sub ) for sub in node or () ] )
+               else :
+                       result = None
+               return result
+
+       return NodeSet( confToNodeset_( node ) )
+
+#
+# FIXME: UGLY
+#
+def select( ns , path ) :
+
+       def select_( ns , path ) :
+
+               result = NodeSet( ns )
+               while path :
+                       ns = result
+                       recPath = path
+                       part , path = path[ 0 ] , path[ 1 : ]
+                       recurse = False
+                       if part == '' :
+                               recurse = True
+                               part , path = path[ 0 ] , path[ 1 : ]
+                       #
+                       # Build predicates
+                       #
+                       if ':' in part :
+                               part = part.split( ':' )
+                               def matcher( sub ) :
+                                       result = ( part[ 0 ] in [ sub.name , '*' ] and len( sub.values ) == len( part ) - 1 )
+                                       if result :
+                                               for v1 , v2 in zip( sub.values , part[ 1 : ] ) :
+                                                       if re.match( v2
+                                                               .replace( '.' , '\\.' )
+                                                               .replace( '*' , '.*' )
+                                                               .replace( '?' , '. ') , v1 , re.I ) is None :
+                                                               result = False
+                                                               break
+                                       return result
+                       else :
+                               def matcher( sub ) :
+                                       return part in [ sub.name , '*' ]
+                       #
+                       # Select subnodes according to the predicate
+                       #
+                       result = NodeSet()
+                       for item in ns :
+                               for sub in item.subs :
+                                       if matcher( sub ) :
+                                               result += sub
+                                       if recurse :
+                                               result += select_( sub , recPath )
+               return result
+
+       path = path.split( '/' )
+       if path and path[ 0 ] == '' :
+               # assume // at beginning.. BAD BAD BAD
+               del path[ 0 ]
+       if not path :
+               result = ns
+       else :
+               if path[ -1 ] == '@@' :
+                       def finally_( result ) :
+                               return [ node.values for node in result ]
+                       path.pop()
+               elif path[ -1 ] == '@' :
+                       def finally_( result ) :
+                               return sum( [ node.values for node in result ] , () )
+                       path.pop()
+               elif path[ -1 ] == '?' :
+                       def finally_( result ) :
+                               if len( result ) :
+                                       return ' '.join( [ str( s ) for node in result for s in node.values ] )
+                       path.pop()
+               else :
+                       def finally_( result ) :
+                               return result
+               result = select_( ns , path )
+               result = finally_( result )
+
+       return result
+
+def test() :
+
+       filename = 'vserver.conf'
+
+       import confparser
+       n = confparser.readConfigurationExt( filename )
+       if n is not None :
+               print n[ 'default/unhide' ].pstr()
+               print '--'
+               print n[ 'default/unhide' ] # the nodeset
+               print n[ 'default/unhide/?' ] # the string for the whole nodesets
+               print n[ 'default/unhide/@' ] # the flatten list of text
+               print n[ 'default/unhide/@@' ] # the list of list of text
+               print n[ 'server/@' ]
+               print n[ 'server:m*/rootdev/@' ]
+               print n[ '*/@@' ]
+               print n[ '//*/@@' ]
+       else :
+               print 'Unable to parse %r' % filename
+
+if __name__ == '__main__' :
+       test()
+
+# Local Variables:
+# tab-width: 4
+# python-indent: 4
+# End:
diff --git a/install b/install
index e67d224..8fdf481 100755 (executable)
--- a/install
+++ b/install
@@ -1,9 +1,9 @@
 #!/bin/env python
-# -*- coding: iso-8859-1 -*-
+# -*- coding: utf-8 -*-
 
 #
 # TuxeeNet installer
-# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
+# Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -159,3 +159,8 @@ def main() :
 
 if __name__ == '__main__' :
        main()
+
+# Local Variables:
+# tab-width: 4
+# python-indent: 4
+# End:
index e8b8526..f67b52e 100644 (file)
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
 #
 # Modules to install.
 #
@@ -16,3 +18,8 @@ g_globalModule = 'tuxeenet'
 # Target directory.
 #
 g_targetPrefix = '/opt/tuxeenet/python'
+
+# Local Variables:
+# tab-width: 4
+# python-indent: 4
+# End: