better support for sqlalchemy storage
[tiramisu.git] / tiramisu / storage / __init__.py
1 # Copyright (C) 2013-2014 Team tiramisu (see AUTHORS for all contributors)
2 #
3 # This program is free software: you can redistribute it and/or modify it
4 # under the terms of the GNU Lesser General Public License as published by the
5 # Free Software Foundation, either version 3 of the License, or (at your
6 # option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but WITHOUT
9 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
11 # details.
12 #
13 # You should have received a copy of the GNU Lesser General Public License
14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 # ____________________________________________________________
16
17 """Config's informations are, by default, volatiles. This means, all values and
18 settings changes will be lost.
19
20 The storage is the system Tiramisu uses to communicate with various DB.
21 You can specified a persistent storage.
22
23 Storage is basic components used to set Config informations in DB.
24 The primary "entry point" class is the StorageType and it's public
25 configurator ``set_storage()``.
26 """
27
28
29 from time import time
30 import os
31 from tiramisu.error import ConfigError
32 from tiramisu.i18n import _
33
34
35 class StorageType(object):
36     """Object to store storage's type. If a Config is already set,
37     default storage is store as selected storage. You cannot change it
38     after.
39     """
40     default_storage = os.environ.get('TIRAMISU_STORAGE', 'dictionary')
41     storage_type = None
42     mod = None
43
44     def set(self, name):  # pragma: optional cover
45         if self.storage_type is not None:
46             if self.storage_type == name:
47                 return
48             raise ConfigError(_('storage_type is already set, cannot rebind it'))
49         self.storage_type = name
50
51     def get(self):
52         if self.storage_type is None:
53             self.storage_type = self.default_storage
54         if self.mod is None:
55             modulepath = 'tiramisu.storage.{0}'.format(self.storage_type)
56             try:
57                 mod = __import__(modulepath)
58             except ImportError:
59                 raise SystemError(_('cannot import the storage {0}').format(
60                     self.default_storage))
61             for token in modulepath.split(".")[1:]:
62                 mod = getattr(mod, token)
63             self.mod = mod
64         return self.mod
65
66
67 storage_type = StorageType()
68 storage_option_type = StorageType()
69
70
71 def set_storage(type_, name, **kwargs):  # pragma: optional cover
72     """Change storage's configuration
73
74     :params name: is the storage name. If storage is already set, cannot
75         reset storage name
76
77     Other attributes are differents according to the selected storage's name
78     """
79     if type_ == 'option':
80         storage_option_type.set(name)
81         setting = storage_option_type.get().setting
82     else:
83         storage_type.set(name)
84         setting = storage_type.get().setting
85     for option, value in kwargs.items():
86         try:
87             getattr(setting, option)
88             setattr(setting, option, value)
89         except AttributeError:
90             raise ValueError(_('option {0} not already exists in storage {1}'
91                                '').format(option, name))
92
93
94 def _impl_getstate_setting():
95     setting = storage_type.get().setting
96     state = {'name': storage_type.storage_type}
97     for var in dir(setting):
98         if not var.startswith('_'):
99             state[var] = getattr(setting, var)
100     return state
101
102
103 def get_storage(type_, session_id, persistent, test):  # pragma: optional cover
104     """all used when __setstate__ a Config
105     """
106     if type_ == 'option':
107         return storage_option_type.get().Storage(session_id, persistent, test)
108     else:
109         return storage_type.get().Storage(session_id, persistent, test)
110
111
112 def get_storages(context, session_id, persistent):
113     def gen_id(config):
114         return str(id(config)) + str(time())
115
116     if session_id is None:
117         session_id = gen_id(context)
118     imp = storage_type.get()
119     storage = imp.Storage(session_id, persistent)
120     try:
121         return imp.Settings(storage), imp.Values(storage)
122     except:
123         import traceback
124         traceback.print_exc()
125         raise Exception('rah')
126
127
128 def get_storages_option(type_):
129     imp = storage_option_type.get()
130     if type_ == 'base':
131         return imp.StorageBase
132     else:
133         return imp.StorageOptionDescription
134
135
136 def list_sessions(type_):  # pragma: optional cover
137     """List all available session (persistent or not persistent)
138     """
139     if type_ == 'option':
140         return storage_option_type.get().list_sessions()
141     else:
142         return storage_type.get().list_sessions()
143
144
145 def delete_session(type_, session_id):  # pragma: optional cover
146     """Delete a selected session, be careful, you can deleted a session
147     use by an other instance
148     :params session_id: id of session to delete
149     """
150     if type_ == 'option':
151         return storage_option_type.get().delete_session(session_id)
152     else:
153         return storage_type.get().delete_session(session_id)
154
155
156 __all__ = (set_storage, list_sessions, delete_session)