Initial import
[py-rsbac] / rsbac / _flags.py
1 # -*- coding:utf-8 -*-
2
3 # py-rsbac - RSBAC Python bindings
4 # Copyright (C) 2006  Frederic Jolliton <pyrsbac@tuxee.net>
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 import operator
21
22 def buildFlagsClass( className , bases , bits ) :
23     dbits = dict( bits )
24     rdbits = dict( map( reversed , bits ) )
25     attrs = {}
26     def add( fun ) :
27         attrs[ fun.__name__ ] = fun
28         return fun
29     def addTo( cls ) :
30         def f( fun ) :
31             setattr( cls , fun.__name__ , fun )
32             return fun
33         return f
34     def init( value ) :
35         if isinstance( value , basestring ) :
36             if value not in rdbits :
37                 raise RuntimeError , 'Unknown flag named %r in class %s' % ( value , className )
38             return 1 << rdbits[ value ]
39         elif isinstance( value , ( tuple , list ) ) :
40             return reduce( operator.__or__ , map( init , value ) , 0 )
41         else :
42             return int( value )
43     @add
44     def __init__( self , *value ) :
45         self.value = init( value )
46     @add
47     def __iter__( self ) :
48         assert self.value >= 0
49         left = self.value
50         for bit , name in bits :
51             b = 1 << bit
52             if self.value & b :
53                 yield name
54                 left &= ~b
55         if left :
56             bit = 0
57             b = 1
58             while left :
59                 if left & b :
60                     yield bit
61                     left &= ~b
62                 bit += 1
63                 b <<= 1
64     @add
65     def __repr__( self ) :
66         r = []
67         for bit in self :
68             if isinstance( bit , str ) :
69                 r.append( `bit` )
70             else :
71                 r.append( '2**%d' % bit )
72         return '%s(%s)' % ( className , ', '.join( r ) )
73     @add
74     def __int__( self ) :
75         return int( self.value )
76     @add
77     def __long__( self ) :
78         return long( self.value )
79     @add
80     def __cmp__( self , other ) :
81         return cmp( self.value , other.value )
82     def addAttribute( bit , name ) :
83         mask = 1 << bit
84         def get( self ) :
85             return bool( self.value & mask )
86         #attrs[ 'get_' + name ] = get
87         attrs[ name ] = property( get )
88     mask = 0
89     for bit , name in bits :
90         addAttribute( bit , name )
91         mask |= 1 << bit
92     t = type( className , bases , attrs )
93     @addTo( t )
94     def __or__( self , v ) :
95         return t( self.value | init( v ) )
96     @addTo( t )
97     def __xor__( self , v ) :
98         return t( self.value ^ init( v ) )
99     @addTo( t)
100     def __and__( self , v ) :
101         return t( self.value & init( v ) )
102     @addTo( t )
103     def __invert__( self ) :
104         return t( self.value ^ mask )
105     return t
106
107 # Local Variables:
108 # indent-tabs-mode: nil
109 # python-indent: 4
110 # End: