Fixed / overloading when enabling true division.
[tx] / sequence.py
1 # -*- coding:utf-8 -*-
2
3 # Sequence
4 # Copyright (C) 2005  Frédéric Jolliton <frederic@jolliton.com>
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 __all__ = [
21         'Sequence' ,
22         'SEQUENCE_EMPTY' ,
23         'SEQUENCE_NODES' ,
24         'SEQUENCE_ATOMICS' ,
25         'SEQUENCE_MIXED'
26 ]
27
28 from nodes import Node
29 from types import GeneratorType
30
31 # Sequence types
32 SEQUENCE_EMPTY   = 0
33 SEQUENCE_ATOMICS = 1
34 SEQUENCE_NODES   = 2
35 SEQUENCE_MIXED   = 3
36
37 def _checkSequenceType( sequence ) :
38
39         '''Check a sequence (tuple or Sequence) type and return either
40         SEQUENCE_EMPTY, SEQUENCE_ATOMICS, SEQUENCE_NODES or
41         SEQUENCE_MIXED.'''
42
43         if isinstance( sequence , Sequence ) :
44                 type = sequence.type
45         else :
46                 type = SEQUENCE_EMPTY
47                 for item in sequence :
48                         if isinstance( item , Node ) :
49                                 type |= SEQUENCE_NODES
50                         else :
51                                 type |= SEQUENCE_ATOMICS
52                         if type == SEQUENCE_MIXED :
53                                 break
54         return type
55
56 class Sequence( tuple ) :
57
58         '''XPath/XQuery sequence type'''
59
60         def __new__( cls , *items , **kwargs ) :
61
62                 unionType = kwargs.get( 'type' )
63                 if unionType is not None :
64                         normalizedItems = []
65                         for item in items :
66                                 if isinstance( item , Sequence ) :
67                                         normalizedItems += item
68                                 elif isinstance( item , ( tuple , list , GeneratorType ) ) :
69                                         normalizedItems += tuple( item )
70                                 else :
71                                         normalizedItems.append( item )
72                 else :
73                         unionType = SEQUENCE_EMPTY
74                         normalizedItems = []
75                         for item in items :
76                                 if isinstance( item , Sequence ) :
77                                         unionType |= item.type
78                                         normalizedItems += item
79                                 elif isinstance( item , GeneratorType ) :
80                                         item = tuple( item )
81                                         unionType |= _checkSequenceType( item )
82                                         normalizedItems += item
83                                 elif isinstance( item , ( tuple , list ) ) :
84                                         item = Sequence( *item )
85                                         unionType |= _checkSequenceType( item )
86                                         normalizedItems += item
87                                 else :
88                                         if isinstance( item , Node ) :
89                                                 unionType |= SEQUENCE_NODES
90                                         else :
91                                                 unionType |= SEQUENCE_ATOMICS
92                                         normalizedItems.append( item )
93                 if not normalizedItems :
94                         unionType = SEQUENCE_EMPTY
95                 instance = tuple.__new__( cls , normalizedItems )
96                 instance.type = unionType
97                 return instance
98
99         def __eq__( self , other ) :
100
101                 if not isinstance( other , Sequence ) :
102                         return len( self ) == 1 and self[ 0 ] == other
103                 else :
104                         return self.type == other.type and super( Sequence , self ).__eq__( other )
105
106         def __contains__( self , other ) :
107
108                 if isinstance( other , Node ) :
109                         for item in self :
110                                 if item is other :
111                                         return True
112                 else :
113                         return super( Sequence , self ).__contains__( other )
114
115         def __add__( self , other , type = None ) :
116
117                 if type is None :
118                         type = _checkSequenceType( other )
119                 return Sequence( self , other , type = self.type | type )
120
121         def __getitem__( self , n ) :
122
123                 if not isinstance( n , slice ) :
124                         return tuple.__getitem__( self , n )
125                 else :
126                         return Sequence( tuple.__getitem__( self , n ) , type = self.type )
127
128         def __getslice__( self , a , b ) :
129
130                 return Sequence( tuple.__getslice__( self , a , b ) , type = self.type )
131
132         def __str__( self ) :
133
134                 s = 'Sequence('
135                 if self :
136                         s += ', '.join( map( repr , self ) )
137                 s += ')'
138                 return s
139
140         def __repr__( self ) :
141
142                 return '<Sequence [%s] of %d items>' % ( self.type , len( self ) )
143
144 _Empty = Sequence()
145 _False = Sequence( False )
146 _True  = Sequence( True )
147 _EmptyString = Sequence( '' ) # FIXME: or u'' ?
148 _Boolean = ( _False , _True )
149
150 # Local Variables:
151 # tab-width: 4
152 # python-indent: 4
153 # End: