~lifeless/storm/bug-620615

« back to all changes in this revision

Viewing changes to storm/info.py

Merging fixes from James.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
# You should have received a copy of the GNU Lesser General Public License
19
19
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
20
#
21
 
from weakref import ref
 
21
from weakref import ref, WeakKeyDictionary
22
22
 
23
23
from storm.exceptions import ClassInfoError
24
24
from storm.expr import Expr, FromExpr, Column, Desc, TABLE
25
25
from storm.expr import SQLToken, CompileError, compile
26
26
from storm.event import EventSystem
27
 
from storm import Undef, psycer
 
27
from storm import Undef, has_cextensions
28
28
 
29
29
 
30
30
__all__ = ["get_obj_info", "set_obj_info", "get_cls_info",
194
194
        for variable in self.variables.itervalues():
195
195
            variable.checkpoint()
196
196
 
197
 
try:
 
197
 
 
198
if has_cextensions:
198
199
    from storm.cextensions import ObjectInfo, get_obj_info
199
 
except ImportError, e:
200
 
    if "cextensions" not in str(e):
201
 
        raise
 
200
 
202
201
 
203
202
 
204
203
class ClassAlias(FromExpr):
 
204
    """Create a named alias for a Storm class for use in queries.
 
205
 
 
206
    This is useful basically when the SQL 'AS' feature is desired in code using
 
207
    Storm queries.
 
208
 
 
209
    ClassAliases which are explicitly named (i.e., when 'name' is passed) are
 
210
    cached for as long as the class exists, such that the alias returned from
 
211
    C{ClassAlias(Foo, 'foo_alias')} will be the same object no matter how many
 
212
    times it's called.
 
213
 
 
214
    @param cls: The class to create the alias of.
 
215
    @param name: If provided, specify the name of the alias to create.
 
216
    """
205
217
 
206
218
    alias_count = 0
207
219
 
208
220
    def __new__(self_cls, cls, name=Undef):
209
221
        if name is Undef:
 
222
            use_cache = False
210
223
            ClassAlias.alias_count += 1
211
224
            name = "_%x" % ClassAlias.alias_count
 
225
        else:
 
226
            use_cache = True
 
227
            cache = cls.__dict__.get("_storm_alias_cache")
 
228
            if cache is None:
 
229
                cls._storm_alias_cache = {}
 
230
            elif name in cache:
 
231
                return cache[name]
212
232
        cls_info = get_cls_info(cls)
213
233
        alias_cls = type(cls.__name__+"Alias", (self_cls,),
214
234
                         {"__storm_table__": name})
215
235
        alias_cls.__bases__ = (cls, self_cls)
216
236
        alias_cls_info = get_cls_info(alias_cls)
217
237
        alias_cls_info.cls = cls
 
238
        if use_cache:
 
239
            cls._storm_alias_cache[name] = alias_cls
218
240
        return alias_cls
219
241
 
220
242
 
225
247
    if state.context is TABLE and issubclass(expr, ClassAlias):
226
248
        return "%s AS %s" % (compile(cls_info.cls, state), table)
227
249
    return table
228
 
 
229
 
 
230
 
psycer.bind(ObjectInfo, 0)