1 ############################################################################
2 # Copyright (C) 2005 by Reithinger GmbH
5 # This file is part of metapie.
7 # metapie is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # pyplan is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the
19 # Free Software Foundation, Inc.,
20 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 ############################################################################
28 from ZODB
import FileStorage
, DB
29 from BTrees
import OOBTree
30 from BTrees
.IOBTree
import IOBTree
, multiunion
31 from BTrees
.IFBTree
import intersection
32 from BTrees
.OIBTree
import OIBTree
34 import BTrees
.IIBTree
as iib
43 def __init__(self
, storage
, dbname
="application"):
44 DB
.__init
__(self
, storage
)
45 self
.connection
= self
.open()
46 dbroot
= self
.connection
.root()
48 self
.application
= dbroot
.setdefault(dbname
, OOBTree
.OOBTree())
49 IdGenerator
.instance
= dbroot
.setdefault("ids", IdGenerator())
52 def make_entrance(self
, entrance_class
):
53 entrance
= self
.application
.get("entrance", None)
55 entrance
= self
.application
["entrance"] = entrance_class()
58 entrance
.set_instance()
63 class FileDatabase(Database
):
64 def __init__(self
, filename
, dbname
="application"):
65 Database
.__init
__(self
, FileStorage
.FileStorage(filename
), dbname
)
69 """Lazily accessed set of objects."""
71 def __init__(self
, uids
, uidutil
):
73 self
.uidutil
= uidutil
80 def __delitem__(self
, imodel
):
82 self
.uids
.remove(imodel
.id())
83 except AttributeError:
85 self
.uids
= multiunion(self
.uids
)
86 self
.uids
.remove(imodel
.id())
89 def __getitem__(self
, index
):
90 return self
.uidutil
[self
.uids
[index
]]
93 class SetContainer(object):
95 SetContainer is like a IITreeSet but
96 it support the operators & | -
99 def __init__(self
, set):
100 self
.set = iib
.IISet(set)
102 def __and__(self
, other
):
103 return SetContainer(iib
.intersection(self
.set, other
.set))
105 def __or__(self
, other
):
106 return SetContainer(iib
.union(self
.set, other
.set))
108 def __sub__(self
, other
):
109 return SetContainer(iib
.difference(self
.set, other
.set))
118 class Container(persistent
.Persistent
, peer
.Peer
):
119 def __init__(self
, imodel
, peer_class
, name_to_me
, name_to_peer
, index
):
120 self
._container
= IOBTree()
121 self
._imodel
= imodel
122 self
._peer
_class
= peer_class
123 self
._name
_to
_me
= name_to_me
124 self
._name
_to
_peer
= name_to_peer
126 self
._length
= BTrees
.Length
.Length()
129 prop_to_attrib
= dict(map(lambda kv
: (kv
[1]._get
_value
, kv
[1]),
130 peer_class
.__attributes
_map
__.iteritems()))
132 for attrib
, index_type
in index
:
133 if isinstance(attrib
, property):
134 attrib
= prop_to_attrib
[attrib
.fget
].name
136 self
._keys
[attrib
] = index_type()
137 setattr(self
, attrib
, self
._keys
[attrib
])
140 def check_peer(self
, imodel
):
141 if not isinstance(imodel
, self
._peer
_class
):
142 raise ValueError("'%s' is not of type '%s'"%
143 (str(obj
), self
.contained_class
.__name
__))
147 self
._imodel
.fire(self
._name
_to
_peer
, self
._name
_to
_peer
)
148 self
._imodel
.fire("default", self
._name
_to
_peer
)
151 def insert(self
, imodel
, fire
=True):
152 self
.check_peer(imodel
)
153 if self
._insert
_item
(imodel
):
154 self
._add
_to
_peer
(imodel
, self
._imodel
)
158 def delete(self
, imodel
, fire
=True):
159 if self
._del
_item
(imodel
):
160 self
._remove
_from
_peer
(imodel
, self
._imodel
)
163 raise KeyError("model does not exist in container", imodel
)
166 def recatalog(self
, obj
):
167 if self
._container
.has_key(obj
.id()):
168 self
._remove
_from
_index
(obj
)
169 self
._add
_to
_index
(obj
)
176 return _ResultSet(self
._container
.keys(), self
._container
)
179 def subset(self
, idset
):
182 except ttributeError
: pass
183 return _ResultSet(idset
, self
._container
)
186 def __nonzero__(self
): return self
._length
() > 0
187 def __len__(self
): return self
._length
()
188 def __iter__(self
): return self
._container
.itervalues()
189 def __contains__(self
, y
): return self
._container
.has_key(y
.id())
190 def __getitem__(self
, key
): return self
._container
[key
]
191 def __delitem__(self
, imodel
): self
.delete(imodel
)
194 def _insert_item(self
, obj
):
196 if self
._container
.has_key(id_
):
199 self
._length
.change(1)
200 self
._container
.insert(id_
, obj
)
201 self
._add
_to
_index
(obj
)
205 def _del_item(self
, obj
):
207 if not self
._container
.has_key(id_
):
210 self
._length
.change(-1)
211 del self
._container
[id_
]
212 self
._remove
_from
_index
(obj
)
216 def _add_to_index(self
, obj
):
218 for k
, v
in self
._keys
.iteritems():
219 v
.index_id(id_
, getattr(obj
, k
))
222 def _remove_from_index(self
, obj
):
224 for v
in self
._keys
.values():
228 class IdGenerator(persistent
.Persistent
):
231 def get_id(cls
, type="default"):
232 if not cls
.instance
: cls
.instance
= cls()
234 counter
= getattr(cls
.instance
, type, 0)
235 setattr(cls
.instance
, type, counter
+ 1)
239 get_id
= classmethod(get_id
)
243 class _PersistentBase(persistent
.Persistent
, object):
247 #generate a unique long lasting id
248 self
.__id
= IdGenerator
.get_id(self
.__id
_type
__ \
249 or self
.__class
__.__name
__)
250 #self.__id = int(time.time()) % 100000 + (id(self) % 10000) * 100000
253 def id(self
): return self
.__id
255 metapie
._init
_db
_module
("zodb", _PersistentBase
, Container
, transaction
.commit
)
257 from dblayout
import *