⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expr.py

📁 Python的一个ORM,现在很火
💻 PY
📖 第 1 页 / 共 3 页
字号:
## Copyright (c) 2006, 2007 Canonical## Written by Gustavo Niemeyer <gustavo@niemeyer.net>## This file is part of Storm Object Relational Mapper.## Storm is free software; you can redistribute it and/or modify# it under the terms of the GNU Lesser General Public License as# published by the Free Software Foundation; either version 2.1 of# the License, or (at your option) any later version.## Storm is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU Lesser General Public License for more details.## You should have received a copy of the GNU Lesser General Public License# along with this program.  If not, see <http://www.gnu.org/licenses/>.#from datetime import datetime, date, time, timedeltafrom copy import copyimport sysfrom storm.exceptions import CompileError, NoTableError, ExprErrorfrom storm.variables import (    Variable, CharsVariable, UnicodeVariable, LazyValue,    DateTimeVariable, DateVariable, TimeVariable, TimeDeltaVariable,    BoolVariable, IntVariable, FloatVariable)from storm import Undef# --------------------------------------------------------------------# Basic compiler infrastructureclass Compile(object):    """Compiler based on the concept of generic functions."""    def __init__(self, parent=None):        self._local_dispatch_table = {}        self._local_precedence = {}        self._dispatch_table = {}        self._precedence = {}        self._hash = None        self._parents_hash = None        self._parents = []        if parent:            self._parents.extend(parent._parents)            self._parents.append(parent)    def _check_parents(self):        parents_hash = hash(tuple(parent._hash for parent in self._parents))        if parents_hash != self._parents_hash:            self._parents_hash = parents_hash            for parent in self._parents:                self._dispatch_table.update(parent._local_dispatch_table)                self._precedence.update(parent._local_precedence)            self._dispatch_table.update(self._local_dispatch_table)            self._precedence.update(self._local_precedence)    def _update(self):        self._dispatch_table.update(self._local_dispatch_table)        self._precedence.update(self._local_precedence)        self._hash = hash(tuple(sorted(self._local_dispatch_table.items() +                                       self._local_precedence.items())))    def fork(self):        return self.__class__(self)    def when(self, *types):        def decorator(method):            for type in types:                self._local_dispatch_table[type] = method            self._update()            return method        return decorator    def get_precedence(self, type):        self._check_parents()        return self._precedence.get(type, MAX_PRECEDENCE)    def set_precedence(self, precedence, *types):        for type in types:            self._local_precedence[type] = precedence        self._update()    def _compile_single(self, state, expr, outer_precedence):        cls = expr.__class__        for class_ in cls.__mro__:            handler = self._dispatch_table.get(class_)            if handler is not None:                inner_precedence = state.precedence = \                                   self._precedence.get(cls, MAX_PRECEDENCE)                statement = handler(self._compile, state, expr)                if inner_precedence < outer_precedence:                    statement = "(%s)" % statement                return statement        else:            raise CompileError("Don't know how to compile type %r of %r"                               % (expr.__class__, expr))    def _compile(self, state, expr, join=", ", raw=False):        # This docstring is in a pretty crappy place; where could it        # go that would be more discoverable?        """        @type state: L{State}.        @param expr: The expression to compile.        @param join: The string token to use to put between                     subexpressions. Defaults to ", ".        @param raw: If true, any string or unicode expression or                    subexpression will not be further compiled.        """        outer_precedence = state.precedence        expr_type = type(expr)        if (expr_type is SQLRaw or            expr_type is SQLToken or            raw and (expr_type is str or expr_type is unicode)):            return expr        if expr_type in (tuple, list):            compiled = []            for subexpr in expr:                subexpr_type = type(subexpr)                if (subexpr_type is SQLRaw or                    subexpr_type is SQLToken or                    raw and (subexpr_type is str or subexpr_type is unicode)):                    statement = subexpr                elif subexpr_type in (tuple, list):                    state.precedence = outer_precedence                    statement = self._compile(state, subexpr, join, raw)                else:                    statement = self._compile_single(state, subexpr,                                                     outer_precedence)                compiled.append(statement)            statement = join.join(compiled)        else:            statement = self._compile_single(state, expr, outer_precedence)        state.precedence = outer_precedence        return statement    def __call__(self, expr):        self._check_parents()        state = State()        return self._compile(state, expr), state.parametersclass CompilePython(Compile):    def get_expr(self, expr):        return self._compile(State(), expr)    def __call__(self, expr):        exec ("def match(get_column): return bool(%s)" %              self._compile(State(), expr))        return matchclass State(object):    """All the data necessary during compilation of an expression.    @ivar aliases: Dict of L{Column} instances to L{Alias} instances,        specifying how columns should be compiled as aliases in very        specific situations.  This is typically used to work around        strange deficiencies in various databases.    @ivar auto_tables: The list of all implicitly-used tables.  e.g.,        in store.find(Foo, Foo.attr==Bar.id), the tables of Bar and        Foo are implicitly used because columns in them are        referenced. This is used when building tables.    @ivar join_tables: If not None, when Join expressions are        compiled, tables seen will be added to this set. This acts as        a blacklist against auto_tables when compiling Joins, because        the generated statements should not refer to the table twice.    @ivar context: an instance of L{Context}, specifying the context        of the expression currently being compiled.    @ivar precedence: Current precedence, automatically set and restored        by the compiler. If an inner precedence is lower than an outer        precedence, parenthesis around the inner expression are        automatically emitted.    """    def __init__(self):        self._stack = []        self.precedence = 0        self.parameters = []        self.auto_tables = []        self.join_tables = None        self.context = None        self.aliases = None    def push(self, attr, new_value=Undef):        """Set an attribute in a way that can later be reverted with L{pop}.        """        old_value = getattr(self, attr, None)        self._stack.append((attr, old_value))        if new_value is Undef:            new_value = copy(old_value)        setattr(self, attr, new_value)        return old_value    def pop(self):        """Revert the topmost L{push}.        """        setattr(self, *self._stack.pop(-1))compile = Compile()compile_python = CompilePython()# --------------------------------------------------------------------# Expression contextsclass Context(object):    """    An object used to specify the nature of expected SQL expressions    being compiled in a given context.    """    def __init__(self, name):        self._name = name    def __repr__(self):        return "%s(%r)" % (self.__class__.__name__, self._name)TABLE = Context("TABLE")EXPR = Context("EXPR")COLUMN = Context("COLUMN")COLUMN_PREFIX = Context("COLUMN_PREFIX")COLUMN_NAME = Context("COLUMN_NAME")SELECT = Context("SELECT")# --------------------------------------------------------------------# Builtin type support@compile.when(str)def compile_str(compile, state, expr):    state.parameters.append(CharsVariable(expr))    return "?"@compile.when(unicode)def compile_unicode(compile, state, expr):    state.parameters.append(UnicodeVariable(expr))    return "?"@compile.when(int, long)def compile_int(compile, state, expr):    state.parameters.append(IntVariable(expr))    return "?"@compile.when(float)def compile_float(compile, state, expr):    state.parameters.append(FloatVariable(expr))    return "?"@compile.when(bool)def compile_bool(compile, state, expr):    state.parameters.append(BoolVariable(expr))    return "?"@compile.when(datetime)def compile_datetime(compile, state, expr):    state.parameters.append(DateTimeVariable(expr))    return "?"@compile.when(date)def compile_date(compile, state, expr):    state.parameters.append(DateVariable(expr))    return "?"@compile.when(time)def compile_time(compile, state, expr):    state.parameters.append(TimeVariable(expr))    return "?"@compile.when(timedelta)def compile_timedelta(compile, state, expr):    state.parameters.append(TimeDeltaVariable(expr))    return "?"@compile.when(type(None))def compile_none(compile, state, expr):    return "NULL"@compile_python.when(str, unicode, bool, int, long, float,                     datetime, date, time, timedelta, type(None))def compile_python_builtin(compile, state, expr):    return repr(expr)@compile.when(Variable)def compile_variable(compile, state, variable):    state.parameters.append(variable)    return "?"@compile_python.when(Variable)def compile_python_variable(compile, state, variable):    return repr(variable.get())class SQLToken(str):    """Marker for strings the should be considered as a single SQL token.    In the future, these strings will be quoted, when needed.    """@compile.when(SQLToken)def compile_str(compile, state, expr):    return expr# --------------------------------------------------------------------# Base classes for expressionsMAX_PRECEDENCE = 1000class Expr(LazyValue):    pass@compile_python.when(Expr)def compile_python_unsupported(compile, state, expr):    raise CompileError("Can't compile python expressions with %r" % type(expr))class Comparable(object):    def __eq__(self, other):        if other is not None and not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Eq(self, other)    def __ne__(self, other):        if other is not None and not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Ne(self, other)    def __gt__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Gt(self, other)    def __ge__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Ge(self, other)    def __lt__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Lt(self, other)    def __le__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Le(self, other)    def __rshift__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return RShift(self, other)    def __lshift__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return LShift(self, other)    def __and__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return And(self, other)    def __or__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Or(self, other)    def __add__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Add(self, other)    def __sub__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Sub(self, other)    def __mul__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Mul(self, other)    def __div__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Div(self, other)        def __mod__(self, other):        if not isinstance(other, (Expr, Variable)):            other = getattr(self, "variable_factory", Variable)(value=other)        return Mod(self, other)    def is_in(self, others):        if not isinstance(others, Expr):            if not others:                return None            others = list(others)            variable_factory = getattr(self, "variable_factory", Variable)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -