<commit_before>import copy
import types
import pdb
from collections import defaultdict

class Position:
    def __init__(self, i, e, isTransposition):
        self.isTransposition = isTransposition
        self.i = i
        self.e = e

    def __hash__(self) :
        try :
            return self._hash
        except AttributeError :
            h = self._hash = hash(tuple(eval(repr(self))))
            return h

    def __str__(self):
        if self.isTransposition :
            val = str((self.i, self.e, 't'))
        else :
            val = str((self.i, self.e))
        return val

    def __repr__(self):
        try :
            return self._repr
        except AttributeError :
            r = self._repr = str(self)
            return r

    def __eq__(lhs, rhs):
        #return lhs.i == rhs.i and \
        #       lhs.e == rhs.e and \
        #       lhs.isTransposition == rhs.isTransposition
        return repr(lhs) == repr(rhs)

    def __lt__(lhs, rhs):
        if lhs.i < rhs.i:
            return True

        if lhs.i >= rhs.i:
            return False

        # consider a standard position as lower than a transposition position
        if not lhs.isTransposition and rhs.isTransposition:
            return True

        if lhs.isTransposition != rhs.isTransposition:
            return False

        if lhs.e < rhs.e:
            return True

        if lhs.e > rhs.e:
            return False

        return False

def StandardPosition(i, e):
    return Position(i, e, False)

def TPosition(i, e):
    return Position(i, e, True)

def isSubsumming(subsumming, subsummee, n):
    i, e = subsumming.i, subsumming.e
    j, f = subsummee.i, subsummee.e

    # true if i and j are t-positions
    it = subsumming.isTransposition
    jt = subsummee.isTransposition

    # see 7.1.3
    if it:
        if jt:
            # 4. position it^e subsumes jt^f iff f > e and i = j
            if it and jt and f > e and i == j:
                return True
        else:
            # 3. position it^e subsumes j^f iff n = f > e and i = j
            if n == f and f > e and i == j:
                return True

    else:
        if jt:
            # 2. position i^e subsumes jt^f iff f > e and |j-(i-1)| <= f - e
            if f > e and (abs(j - (i - 1)) <= (f - e)):
                return True
        else:
            # 1. position i^e subsumes j^f iff e < f and |j-i| <= f - e
            if e < f and (abs(j - i) <= (f - e )):
                return True

    return False

def reduce(M, n):
    # Process entries by number of errors.
    # This is because a entry can only be subsumed
    # by entries with less errors.
    items = {}
    for entry in M:
        l = items.setdefault(entry.e, [])
        item = [entry, False]
        if item not in l:
            l.append(item)

    keys = items.keys()
    keys.sort()
    for eIndex in range(len(keys)):
        e = keys[eIndex]
        for item in items[e]:
            if item[1] is False:
                pos = item[0]
                for f in keys[eIndex + 1:]:
                    for jIndex in range(len(items[f])):
                        otherItem = items[f][jIndex]
                        if otherItem[1] is False:
                            otherPos = otherItem[0]
                            if isSubsumming(pos, otherPos, n):
                                otherItem[1] = True
        items[e] = filter(lambda j: not j[1], items[e])
    union = []
    for key in items:
        for item in items[key]:
            union.append(item[0])
    union.sort()

    return union

def subword(input, n, i, e):
    w = len(input)
    k = min(2*n - e + 1, w - i)
    return input[i:i + k]

def positiveK(cString):
    i = 0
    while i < len(cString) and  cString[i] != 1:
        i = i + 1
    if i == len(cString):
        return None
    else:
        return i + 1

def union(M, N, n):
    if type(M) is not types.ListType:
        M = [M]
    if type(N) is not types.ListType:
        N = [N]

    return reduce(M + N, n)

def profil( inputWord ):
    characters = {}
    cVector = []
    currentSymbol = 1
    for c in inputWord:
        if c not in characters:
            characters[c] = currentSymbol
            currentSymbol += 1
        cVector.append(characters[c])
    return cVector

def characterizedVector( character, inputWord ):
    cVector = []
    for c in inputWord:
        if c == character:
            cVector.append(1)
        else:
            cVector.append(0)
    return cVector

def genCharVectors(l):
    vectors = [[0] * l]
    for i in range(pow(2, l) - 1):
        vectors.append(addone(vectors[-1]))
    return vectors

def addone(vec):
    if len(vec) == 0:
        return []
    if vec[0] == 0:
        return [1] + vec[1:]

    if vec[0] == 1:
        return [0] + addone(vec[1:])

def isLikeStates(state, lowerStates):

    isLike = False
    i = 0
    while i < len(lowerStates) and isLike == False:
        lowerState = lowerStates[i]
        state = copy.copy(state)
        state.sort()

        difference = state[0][0] - lowerState[0][0]
        for index in range(len(state)):
            state[index] = state[index][0] - difference, state[index][1]

        if state == lowerState:
            isLike = True

        i += 1

    return isLike

def final(n, state, index, wordLen):
    isFinal = False

    j = 0
    while j < len(state) and isFinal == False:
        i = state[j].i + index
        e = state[j].e
        if wordLen - i + e <= n:
            isFinal = True
        j += 1
    return isFinal

class ErrorTolerantRecognizer:
    def __init__(self, n, transitionsStates = None):
        if transitionsStates is None:
            transitionsStates = handCraftedStates
        self.transitionsStates = transitionsStates
        self.n = n
        self.null_cvs = NullCV()

        new_states = []

        for states in self.transitionsStates[:] :
            new_dict = {}
            for k_1, v_1 in states.items() :
                new_dict_2 = {}
                for k_2, v_2 in v_1.items() :
                    try :
                        k_2_list = eval(k_2)
                    except NameError :
                        k_2_list = []
                        for each in k_2.strip('[]').split('), ') :
                            if 't' in each :
                                each = each.strip('t') + ",'t'"

                            if ')' not in each :
                                each += ")"
                            each_t = tuple(eval(each))
                            k_2_list.append(each_t)
                    new_dict_2[tuple(k_2_list)] = v_2
                k_list = eval(k_1)
                new_dict[tuple(k_list)] = new_dict_2
            new_states.append(new_dict)

        self.transitionsStates = new_states

    #@profile
    def recognize( self, word, fsa):
        words = []
        wordLen = len(word)

        lstr = str
        lint = int
        llen = len
        window = 2 * self.n + 1
        null_cvs = self.null_cvs
        transitionsStates = self.transitionsStates
        fsa_states = fsa.states
        fsa_finalStates = set(fsa.finalStates)

        states = [("", fsa.startState, ([(0,0)], 0))]
        states_append = states.append
        states_pop = states.pop

        while states :
            (V, q, M) = states_pop()

            stateType, index = M
            word_chunk = word[index:index+window]

            chunk_size = llen(word_chunk)
            word_states = transitionsStates[chunk_size]

            state_key = tuple(stateType)

            for (x, q1) in fsa_states[q].transitions.iteritems():
                if x in word_chunk :
                    cv = tuple([1 if char == x else 0 for char in word_chunk])
                else :
                    cv = null_cvs[chunk_size]

                state = word_states[cv][state_key]

                if state[0] :
                    mPrime = (state[0], state[1] + index)
                    V1 = V + x
                    states_append((V1, q1, mPrime))

            if q in fsa_finalStates and final(self.n, M[0], M[1], wordLen) :
                yield V

def delta( (stateType, index), character, input, w ):

    return state

class NullCV(defaultdict) :
    def __missing__(self, key) :
        value = self[key] = tuple([0]*key)
        return value

<commit_msg>Revert "try different hashing strategy"<commit_after>import copy
import types
import pdb

class Position:
    def __init__(self, i, e, isTransposition):
        self.isTransposition = isTransposition
        self.i = i
        self.e = e

    def __str__(self):
        val = str((self.i, self.e))
        if self.isTransposition:
            val = 't' + val
        return val

    def __repr__(self):
        return str(self)

    def __eq__(lhs, rhs):
        return lhs.i == rhs.i and \
               lhs.e == rhs.e and \
               lhs.isTransposition == rhs.isTransposition

    def __lt__(lhs, rhs):
        if lhs.i < rhs.i:
            return True

        if lhs.i >= rhs.i:
            return False

        # consider a standard position as lower than a transposition position
        if not lhs.isTransposition and rhs.isTransposition:
            return True

        if lhs.isTransposition != rhs.isTransposition:
            return False

        if lhs.e < rhs.e:
            return True

        if lhs.e > rhs.e:
            return False

        return False

def StandardPosition(i, e):
    return Position(i, e, False)

def TPosition(i, e):
    return Position(i, e, True)

def isSubsumming(subsumming, subsummee, n):
    i, e = subsumming.i, subsumming.e
    j, f = subsummee.i, subsummee.e

    # true if i and j are t-positions
    it = subsumming.isTransposition
    jt = subsummee.isTransposition

    # see 7.1.3
    if it:
        if jt:
            # 4. position it^e subsumes jt^f iff f > e and i = j
            if it and jt and f > e and i == j:
                return True
        else:
            # 3. position it^e subsumes j^f iff n = f > e and i = j
            if n == f and f > e and i == j:
                return True

    else:
        if jt:
            # 2. position i^e subsumes jt^f iff f > e and |j-(i-1)| <= f - e
            if f > e and (abs(j - (i - 1)) <= (f - e)):
                return True
        else:
            # 1. position i^e subsumes j^f iff e < f and |j-i| <= f - e
            if e < f and (abs(j - i) <= (f - e )):
                return True

    return False

def reduce(M, n):
    # Process entries by number of errors.
    # This is because a entry can only be subsumed
    # by entries with less errors.
    items = {}
    for entry in M:
        l = items.setdefault(entry.e, [])
        item = [entry, False]
        if item not in l:
            l.append(item)

    keys = items.keys()
    keys.sort()
    for eIndex in range(len(keys)):
        e = keys[eIndex]
        for item in items[e]:
            if item[1] is False:
                pos = item[0]
                for f in keys[eIndex + 1:]:
                    for jIndex in range(len(items[f])):
                        otherItem = items[f][jIndex]
                        if otherItem[1] is False:
                            otherPos = otherItem[0]
                            if isSubsumming(pos, otherPos, n):
                                otherItem[1] = True
        items[e] = filter(lambda j: not j[1], items[e])
    union = []
    for key in items:
        for item in items[key]:
            union.append(item[0])
    union.sort()

    return union

def subword(input, n, i, e):
    w = len(input)
    k = min(2*n - e + 1, w - i)
    return input[i:i + k]

def positiveK(cString):
    i = 0
    while i < len(cString) and  cString[i] != 1:
        i = i + 1
    if i == len(cString):
        return None
    else:
        return i + 1

def union(M, N, n):
    if type(M) is not types.ListType:
        M = [M]
    if type(N) is not types.ListType:
        N = [N]

    return reduce(M + N, n)

def profil( inputWord ):
    characters = {}
    cVector = []
    currentSymbol = 1
    for c in inputWord:
        if c not in characters:
            characters[c] = currentSymbol
            currentSymbol += 1
        cVector.append(characters[c])
    return cVector

def characterizedVector( character, inputWord ):
    cVector = []
    for c in inputWord:
        if c == character:
            cVector.append(1)
        else:
            cVector.append(0)
    return cVector

def genCharVectors(l):
    vectors = [[0] * l]
    for i in range(pow(2, l) - 1):
        vectors.append(addone(vectors[-1]))
    return vectors

def addone(vec):
    if len(vec) == 0:
        return []
    if vec[0] == 0:
        return [1] + vec[1:]

    if vec[0] == 1:
        return [0] + addone(vec[1:])

def isLikeStates(state, lowerStates):

    isLike = False
    i = 0
    while i < len(lowerStates) and isLike == False:
        lowerState = lowerStates[i]
        state = copy.copy(state)
        state.sort()

        difference = state[0][0] - lowerState[0][0]
        for index in range(len(state)):
            state[index] = state[index][0] - difference, state[index][1]

        if state == lowerState:
            isLike = True

        i += 1

    return isLike

def final(n, state, index, wordLen):
    isFinal = False

    j = 0
    while j < len(state) and isFinal == False:
        i = state[j].i + index
        e = state[j].e
        if wordLen - i + e <= n:
            isFinal = True
        j += 1
    return isFinal

class ErrorTolerantRecognizer:
    def __init__(self, n, transitionsStates = None):
        if transitionsStates is None:
            transitionsStates = handCraftedStates
        self.transitionsStates = transitionsStates
        self.n = n

    def recognize( self, word, fsa):
        words = []
        wordLen = len(word)
        lstr = str
        lint = int

        states = [("", fsa.startState, (str([(0,0)]), 0))]
        while len(states):
            (V, q, M) = states.pop()
            word_chunk = word[M[1]:][:(2 * self.n + 1)]
            word_states = self.transitionsStates[len(word_chunk)]
            stateType, index = M

            for (x, q1) in fsa.states[q].transitions.items():
                cv = [lint(char == x) for char in word_chunk]
                cv = lstr(cv)

                state = word_states[cv][lstr(stateType)]
                mPrime = (state[0], state[1] + index)

                if mPrime[0] != []:
                    V1 = V + x
                    states.append((V1, q1, mPrime))
            if q in fsa.finalStates and final(self.n, M[0], M[1], wordLen) :
                words.append(V)
        return words

def delta( (stateType, index), character, input, w ):

    return state
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''It contains the common SQL builders.

.. versionchanged:: 0.2
    It is renamed from ``common``.

.. versionchanged:: 0.1.6
    It is rewritten for using new :mod:`mosql.util`, but it is compatible with
    old version.

.. autosummary ::
    select
    insert
    update
    delete
    join
    or_

It is designed for building the standard SQL statement and tested in PostgreSQL.

.. note::
    If you use MySQL, here is a patch for MySQL --- :mod:`mosql.mysql`.
'''

__all__ = ['select', 'insert', 'delete', 'update', 'join', 'or_']

from .util import *

# defines formatting chains
single_value      = (value, )
single_identifier = (identifier, )
identifier_list   = (identifier, concat_by_comma)
column_list       = (identifier, concat_by_comma, paren)
where_list        = (build_where, )
set_list          = (build_set, )
statement_list    = (concat_by_space, )

# insert

insert  = Clause('insert into', single_identifier)
columns = Clause('columns'    , column_list, hidden=True)
values  = Clause('values'     , (value, concat_by_comma, paren))
returning = Clause('returning'  , identifier_list)

insert_into_stat = Statement([insert, columns, values, returning])

def insert(table, set=None, values=None, **clauses_args):
    '''It generates the SQL statement, ``insert into ...``.

    The following usages generate the same SQL statement:

    >>> print insert('person', {'person_id': 'mosky', 'name': 'Mosky Liu'})
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu')

    >>> print insert('person', (('person_id', 'mosky'), ('name', 'Mosky Liu')))
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu')

    >>> print insert('person', ('person_id', 'name'), ('mosky', 'Mosky Liu'))
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu')

    The columns is ignorable:

    >>> print insert('person', values=('mosky', 'Mosky Liu'))
    INSERT INTO "person" VALUES ('mosky', 'Mosky Liu')

    The :func:`insert`, :func:`update` and :func:`delete` support ``returning``.

    >>> print insert('person', {'person_id': 'mosky', 'name': 'Mosky Liu'}, returning=raw('*'))
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu') RETURNING *
    '''

    clauses_args['insert into'] = table

    if values is None:
        if hasattr(set, 'items'):
            pairs = set.items()
        else:
            pairs = set
        clauses_args['columns'], clauses_args['values'] = zip(*pairs)
    else:
        clauses_args['columns'] = set
        clauses_args['values']  = values

    return insert_into_stat.format(clauses_args)

# select

select   = Clause('select'  , identifier_list)
from_    = Clause('from'    , identifier_list)
joins    = Clause('joins'   , statement_list, hidden=True)
where    = Clause('where'   , where_list)
group_by = Clause('group by', identifier_list)
having   = Clause('having'  , where_list)
order_by = Clause('order by', identifier_list)
limit    = Clause('limit'   , single_value)
offset   = Clause('offset'  , single_value)

select_stat = Statement([select, from_, joins, where, group_by, having, order_by, limit, offset])

def select(table, where=None, select=raw('*'), **clauses_args):
    '''It generates the SQL statement, ``select ...`` .

    .. versionchanged:: 0.1.6
        The clause argument, ``join``, is renamed to ``joins``.

    The following usages generate the same SQL statement.

    >>> print select('person', {'person_id': 'mosky'})
    SELECT * FROM "person" WHERE "person_id" = 'mosky'

    >>> print select('person', (('person_id', 'mosky'), ))
    SELECT * FROM "person" WHERE "person_id" = 'mosky'

    It detects the dot in an identifier:

    >>> print select('person', select=('person.person_id', 'person.name'))
    SELECT "person"."person_id", "person"."name" FROM "person"

    Building prepare statement with :class:`mosql.util.param`:

    >>> print select('table', {'custom_param': param('my_param'), 'auto_param': param, 'using_alias': ___})
    SELECT * FROM "table" WHERE "auto_param" = %(auto_param)s AND "using_alias" = %(using_alias)s AND "custom_param" = %(my_param)s

    You can also specify the ``group_by``, ``having``, ``order_by``, ``limit``
    and ``offset`` in the keyword arguments. Here are some examples:

    >>> print select('person', {'name like': 'Mosky%'}, group_by=('age', ))
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' GROUP BY "age"

    >>> print select('person', {'name like': 'Mosky%'}, order_by=('age', ))
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' ORDER BY "age"

    >>> print select('person', {'name like': 'Mosky%'}, order_by=('age desc', ))
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' ORDER BY "age" DESC

    >>> print select('person', {'name like': 'Mosky%'}, order_by=('age ; DROP person; --', ))
    Traceback (most recent call last):
        ...
    OptionError: this option is not allowed: '; DROP PERSON; --'

    .. seealso ::
        The options allowed --- :attr:`mosql.util.allowed_options`.

    >>> print select('person', {'name like': 'Mosky%'}, limit=3, offset=1)
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' LIMIT 3 OFFSET 1

    The operators are also supported:

    >>> print select('person', {'person_id': ('andy', 'bob')})
    SELECT * FROM "person" WHERE "person_id" IN ('andy', 'bob')

    >>> print select('person', {'name': None})
    SELECT * FROM "person" WHERE "name" IS NULL

    >>> print select('person', {'name like': 'Mosky%', 'age >': 20})
    SELECT * FROM "person" WHERE "age" > 20 AND "name" LIKE 'Mosky%'

    >>> print select('person', {"person_id = '' OR true; --": 'mosky'})
    Traceback (most recent call last):
        ...
    OperatorError: this operator is not allowed: "= '' OR TRUE; --"

    .. seealso ::
        The operators allowed --- :attr:`mosql.util.allowed_operators`.

    If you want to use functions, wrap it with :class:`mosql.util.raw`:

    >>> print select('person', select=raw('count(*)'), group_by=('age', ))
    SELECT count(*) FROM "person" GROUP BY "age"

    .. warning ::
        You have responsibility to ensure the security if you use :class:`mosql.util.raw`.

    .. seealso ::
        How it builds the where clause --- :func:`mosql.util.build_where`
    '''

    clauses_args['from']   = table
    clauses_args['where']  = where
    clauses_args['select'] = select

    if 'order_by' in clauses_args:
        clauses_args['order by'] = clauses_args['order_by']
        del clauses_args['order_by']

    if 'group_by' in clauses_args:
        clauses_args['group by'] = clauses_args['group_by']
        del clauses_args['group_by']

    return select_stat.format(clauses_args)

# update

update = Clause('update', single_identifier)
set    = Clause('set'   , set_list)

update_stat = Statement([update, set, where, returning])

def update(table, where=None, set=None, **clauses_args):
    '''It generates the SQL statement, ``update ...`` .

    The following usages generate the same SQL statement.

    >>> print update('person', {'person_id': 'mosky'}, {'name': 'Mosky Liu'})
    UPDATE "person" SET "name"='Mosky Liu' WHERE "person_id" = 'mosky'

    >>> print update('person', (('person_id', 'mosky'), ), (('name', 'Mosky Liu'),) )
    UPDATE "person" SET "name"='Mosky Liu' WHERE "person_id" = 'mosky'

    .. seealso ::
        How it builds the where clause --- :func:`mosql.util.build_set`
    '''

    clauses_args['update'] = table
    clauses_args['where']  = where
    clauses_args['set']    = set

    return update_stat.format(clauses_args)

# delete from

delete = Clause('delete from', single_identifier)

delete_stat = Statement([delete, where, returning])

def delete(table, where=None, **clauses_args):
    '''It generates the SQL statement, ``delete from ...`` .

    The following usages generate the same SQL statement.

    >>> print delete('person', {'person_id': 'mosky'})
    DELETE FROM "person" WHERE "person_id" = 'mosky'

    >>> print delete('person', (('person_id', 'mosky'), ))
    DELETE FROM "person" WHERE "person_id" = 'mosky'
    '''

    clauses_args['delete from'] = table
    clauses_args['where'] = where

    return delete_stat.format(clauses_args)

# join

join  = Clause('join' , single_identifier)
type  = Clause('type' , tuple(), hidden=True)
on    = Clause('on'   , (build_on, ))
using = Clause('using', column_list)

join_stat = Statement([type, join, on, using])

def join(table, using=None, on=None, type=None, **clauses_args):
    '''It generates the SQL statement, ``... join ...`` .

    .. versionadded :: 0.1.6

    >>> print select('person', joins=join('detail'))
    SELECT * FROM "person" NATURAL JOIN "detail"

    >>> print select('person', joins=join('detail', using=('person_id', )))
    SELECT * FROM "person" INNER JOIN "detail" USING ("person_id")

    >>> print select('person', joins=join('detail', on={'person.person_id': 'detail.person_id'}))
    SELECT * FROM "person" INNER JOIN "detail" ON "person"."person_id" = "detail"."person_id"

    >>> print select('person', joins=join('detail', type='cross'))
    SELECT * FROM "person" CROSS JOIN "detail"

    .. seealso ::
        How it builds the where clause --- :func:`mosql.util.build_on`
    '''

    clauses_args['join'] = table
    clauses_args['using'] = using
    clauses_args['on'] = on

    if not type:
        if using or on:
            clauses_args['type'] = 'INNER'
        else:
            clauses_args['type'] = 'NATURAL'
    else:
        clauses_args['type'] = type.upper()

    return join_stat.format(clauses_args)

# or

def or_(*conditions):
    '''It concats the conditions by ``OR``.

    .. versionadded :: 0.1.6

    >>> print or_({'person_id': 'andy'}, {'person_id': 'bob'})
    "person_id" = 'andy' OR "person_id" = 'bob'
    '''

    return concat_by_or(build_where(c) for c in conditions)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

    # benchmark

    #from timeit import timeit
    #from functools import partial
    #timeit = partial(timeit, number=100000)

    #import mosql.util

    #print timeit(lambda: select('person', {'name': 'Mosky Liu'}, ('person_id', 'name'), limit=10, order_by='person_id'))
    ## -> 4.97957897186

    #print timeit(lambda: select('person', {'name': 'Mosky Liu'}, ('person.person_id', 'person.name'), limit=10, order_by='person_id'))
    ## -> 5.33279800415

    #mosql.util.delimit_identifier = None
    #print timeit(lambda: select('person', {'name': 'Mosky Liu'}, ('person_id', 'name'), limit=10, order_by='person_id'))
    ## -> 3.94950485229

    ##from mosql.common import select as old_select

    ##print timeit(lambda: old_select('person', {'name': 'Mosky Liu'}, ('person_id', 'name'), limit=10, order_by='person_id'))
    ### -> 6.79131507874
<commit_msg>support 'on duplicate key update' now<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''It contains the common SQL builders.

.. versionchanged:: 0.2
    It is renamed from ``common``.

.. versionchanged:: 0.1.6
    It is rewritten for using new :mod:`mosql.util`, but it is compatible with
    old version.

.. autosummary ::
    select
    insert
    update
    delete
    join
    or_

It is designed for building the standard SQL statement and tested in PostgreSQL.

.. note::
    If you use MySQL, here is a patch for MySQL --- :mod:`mosql.mysql`.
'''

__all__ = ['select', 'insert', 'delete', 'update', 'join', 'or_']

from .util import *

# defines formatting chains
single_value      = (value, )
single_identifier = (identifier, )
identifier_list   = (identifier, concat_by_comma)
column_list       = (identifier, concat_by_comma, paren)
where_list        = (build_where, )
set_list          = (build_set, )
statement_list    = (concat_by_space, )

# insert

insert  = Clause('insert into', single_identifier)
columns = Clause('columns'    , column_list, hidden=True)
values  = Clause('values'     , (value, concat_by_comma, paren))
returning = Clause('returning'  , identifier_list)
on_duplicate_key_update = Clause('on duplicate key update', set_list)

insert_into_stat = Statement([insert, columns, values, returning, on_duplicate_key_update])

def insert(table, set=None, values=None, **clauses_args):
    '''It generates the SQL statement, ``insert into ...``.

    The following usages generate the same SQL statement:

    >>> print insert('person', {'person_id': 'mosky', 'name': 'Mosky Liu'})
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu')

    >>> print insert('person', (('person_id', 'mosky'), ('name', 'Mosky Liu')))
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu')

    >>> print insert('person', ('person_id', 'name'), ('mosky', 'Mosky Liu'))
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu')

    The columns is ignorable:

    >>> print insert('person', values=('mosky', 'Mosky Liu'))
    INSERT INTO "person" VALUES ('mosky', 'Mosky Liu')

    The :func:`insert`, :func:`update` and :func:`delete` support ``returning``.

    >>> print insert('person', {'person_id': 'mosky', 'name': 'Mosky Liu'}, returning=raw('*'))
    INSERT INTO "person" ("person_id", "name") VALUES ('mosky', 'Mosky Liu') RETURNING *

    The MySQL-specific "on duplicate key update" is also supported:

    >>> print insert('person', values=('mosky', 'Mosky Liu'), on_duplicate_key_update={'name': 'Mosky Liu'})
    INSERT INTO "person" VALUES ('mosky', 'Mosky Liu') ON DUPLICATE KEY UPDATE "name"='Mosky Liu'
    '''

    clauses_args['insert into'] = table

    if values is None:
        if hasattr(set, 'items'):
            pairs = set.items()
        else:
            pairs = set
        clauses_args['columns'], clauses_args['values'] = zip(*pairs)
    else:
        clauses_args['columns'] = set
        clauses_args['values']  = values

    if 'on_duplicate_key_update' in clauses_args:
        clauses_args['on duplicate key update'] = clauses_args['on_duplicate_key_update']
        del clauses_args['on_duplicate_key_update']

    return insert_into_stat.format(clauses_args)

# select

select   = Clause('select'  , identifier_list)
from_    = Clause('from'    , identifier_list)
joins    = Clause('joins'   , statement_list, hidden=True)
where    = Clause('where'   , where_list)
group_by = Clause('group by', identifier_list)
having   = Clause('having'  , where_list)
order_by = Clause('order by', identifier_list)
limit    = Clause('limit'   , single_value)
offset   = Clause('offset'  , single_value)

select_stat = Statement([select, from_, joins, where, group_by, having, order_by, limit, offset])

def select(table, where=None, select=raw('*'), **clauses_args):
    '''It generates the SQL statement, ``select ...`` .

    .. versionchanged:: 0.1.6
        The clause argument, ``join``, is renamed to ``joins``.

    The following usages generate the same SQL statement.

    >>> print select('person', {'person_id': 'mosky'})
    SELECT * FROM "person" WHERE "person_id" = 'mosky'

    >>> print select('person', (('person_id', 'mosky'), ))
    SELECT * FROM "person" WHERE "person_id" = 'mosky'

    It detects the dot in an identifier:

    >>> print select('person', select=('person.person_id', 'person.name'))
    SELECT "person"."person_id", "person"."name" FROM "person"

    Building prepare statement with :class:`mosql.util.param`:

    >>> print select('table', {'custom_param': param('my_param'), 'auto_param': param, 'using_alias': ___})
    SELECT * FROM "table" WHERE "auto_param" = %(auto_param)s AND "using_alias" = %(using_alias)s AND "custom_param" = %(my_param)s

    You can also specify the ``group_by``, ``having``, ``order_by``, ``limit``
    and ``offset`` in the keyword arguments. Here are some examples:

    >>> print select('person', {'name like': 'Mosky%'}, group_by=('age', ))
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' GROUP BY "age"

    >>> print select('person', {'name like': 'Mosky%'}, order_by=('age', ))
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' ORDER BY "age"

    >>> print select('person', {'name like': 'Mosky%'}, order_by=('age desc', ))
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' ORDER BY "age" DESC

    >>> print select('person', {'name like': 'Mosky%'}, order_by=('age ; DROP person; --', ))
    Traceback (most recent call last):
        ...
    OptionError: this option is not allowed: '; DROP PERSON; --'

    .. seealso ::
        The options allowed --- :attr:`mosql.util.allowed_options`.

    >>> print select('person', {'name like': 'Mosky%'}, limit=3, offset=1)
    SELECT * FROM "person" WHERE "name" LIKE 'Mosky%' LIMIT 3 OFFSET 1

    The operators are also supported:

    >>> print select('person', {'person_id': ('andy', 'bob')})
    SELECT * FROM "person" WHERE "person_id" IN ('andy', 'bob')

    >>> print select('person', {'name': None})
    SELECT * FROM "person" WHERE "name" IS NULL

    >>> print select('person', {'name like': 'Mosky%', 'age >': 20})
    SELECT * FROM "person" WHERE "age" > 20 AND "name" LIKE 'Mosky%'

    >>> print select('person', {"person_id = '' OR true; --": 'mosky'})
    Traceback (most recent call last):
        ...
    OperatorError: this operator is not allowed: "= '' OR TRUE; --"

    .. seealso ::
        The operators allowed --- :attr:`mosql.util.allowed_operators`.

    If you want to use functions, wrap it with :class:`mosql.util.raw`:

    >>> print select('person', select=raw('count(*)'), group_by=('age', ))
    SELECT count(*) FROM "person" GROUP BY "age"

    .. warning ::
        You have responsibility to ensure the security if you use :class:`mosql.util.raw`.

    .. seealso ::
        How it builds the where clause --- :func:`mosql.util.build_where`
    '''

    clauses_args['from']   = table
    clauses_args['where']  = where
    clauses_args['select'] = select

    if 'order_by' in clauses_args:
        clauses_args['order by'] = clauses_args['order_by']
        del clauses_args['order_by']

    if 'group_by' in clauses_args:
        clauses_args['group by'] = clauses_args['group_by']
        del clauses_args['group_by']

    return select_stat.format(clauses_args)

# update

update = Clause('update', single_identifier)
set    = Clause('set'   , set_list)

update_stat = Statement([update, set, where, returning])

def update(table, where=None, set=None, **clauses_args):
    '''It generates the SQL statement, ``update ...`` .

    The following usages generate the same SQL statement.

    >>> print update('person', {'person_id': 'mosky'}, {'name': 'Mosky Liu'})
    UPDATE "person" SET "name"='Mosky Liu' WHERE "person_id" = 'mosky'

    >>> print update('person', (('person_id', 'mosky'), ), (('name', 'Mosky Liu'),) )
    UPDATE "person" SET "name"='Mosky Liu' WHERE "person_id" = 'mosky'

    .. seealso ::
        How it builds the where clause --- :func:`mosql.util.build_set`
    '''

    clauses_args['update'] = table
    clauses_args['where']  = where
    clauses_args['set']    = set

    return update_stat.format(clauses_args)

# delete from

delete = Clause('delete from', single_identifier)

delete_stat = Statement([delete, where, returning])

def delete(table, where=None, **clauses_args):
    '''It generates the SQL statement, ``delete from ...`` .

    The following usages generate the same SQL statement.

    >>> print delete('person', {'person_id': 'mosky'})
    DELETE FROM "person" WHERE "person_id" = 'mosky'

    >>> print delete('person', (('person_id', 'mosky'), ))
    DELETE FROM "person" WHERE "person_id" = 'mosky'
    '''

    clauses_args['delete from'] = table
    clauses_args['where'] = where

    return delete_stat.format(clauses_args)

# join

join  = Clause('join' , single_identifier)
type  = Clause('type' , tuple(), hidden=True)
on    = Clause('on'   , (build_on, ))
using = Clause('using', column_list)

join_stat = Statement([type, join, on, using])

def join(table, using=None, on=None, type=None, **clauses_args):
    '''It generates the SQL statement, ``... join ...`` .

    .. versionadded :: 0.1.6

    >>> print select('person', joins=join('detail'))
    SELECT * FROM "person" NATURAL JOIN "detail"

    >>> print select('person', joins=join('detail', using=('person_id', )))
    SELECT * FROM "person" INNER JOIN "detail" USING ("person_id")

    >>> print select('person', joins=join('detail', on={'person.person_id': 'detail.person_id'}))
    SELECT * FROM "person" INNER JOIN "detail" ON "person"."person_id" = "detail"."person_id"

    >>> print select('person', joins=join('detail', type='cross'))
    SELECT * FROM "person" CROSS JOIN "detail"

    .. seealso ::
        How it builds the where clause --- :func:`mosql.util.build_on`
    '''

    clauses_args['join'] = table
    clauses_args['using'] = using
    clauses_args['on'] = on

    if not type:
        if using or on:
            clauses_args['type'] = 'INNER'
        else:
            clauses_args['type'] = 'NATURAL'
    else:
        clauses_args['type'] = type.upper()

    return join_stat.format(clauses_args)

# or

def or_(*conditions):
    '''It concats the conditions by ``OR``.

    .. versionadded :: 0.1.6

    >>> print or_({'person_id': 'andy'}, {'person_id': 'bob'})
    "person_id" = 'andy' OR "person_id" = 'bob'
    '''

    return concat_by_or(build_where(c) for c in conditions)

if __name__ == '__main__':
    import doctest
    doctest.testmod()

    # benchmark

    #from timeit import timeit
    #from functools import partial
    #timeit = partial(timeit, number=100000)

    #import mosql.util

    #print timeit(lambda: select('person', {'name': 'Mosky Liu'}, ('person_id', 'name'), limit=10, order_by='person_id'))
    ## -> 4.97957897186

    #print timeit(lambda: select('person', {'name': 'Mosky Liu'}, ('person.person_id', 'person.name'), limit=10, order_by='person_id'))
    ## -> 5.33279800415

    #mosql.util.delimit_identifier = None
    #print timeit(lambda: select('person', {'name': 'Mosky Liu'}, ('person_id', 'name'), limit=10, order_by='person_id'))
    ## -> 3.94950485229

    ##from mosql.common import select as old_select

    ##print timeit(lambda: old_select('person', {'name': 'Mosky Liu'}, ('person_id', 'name'), limit=10, order_by='person_id'))
    ### -> 6.79131507874
<|endoftext|>


<commit_before>#!/usr/bin/env python

import numpy as np
# import matplotlib
# matplotlib.rcParams['figure.figsize'] = (20.0, 10.0)
# from mpl_toolkits.mplot3d import Axes3D
# import matplotlib.pyplot as plt

class Lij:
    """the Velocity Gradient Tensor Class"""

    def __init__(self, step, L11, L12, L13, L21, L22, L23, L31, L32, L33, tincr):
        self.step = int(step)
        self.Lij = np.array([[L11, L12, L13],[L21, L22, L23],[L31, L32, L33]],dtype='float_')
        self.tincr = float(tincr)

    def strain_rate(self):
        return (self.Lij + np.transpose(self.Lij))/2

    def rotation_rate(self):
        return (self.Lij - np.transpose(self.Lij))/2

class Trajectory:
    """Forward motion of particle: position and velocity"""
    def __init__(self, r, lat, lon, x, y, z, vx, vy, vz):
        self.r = float(r)
        self.lat = float(lat)
        self.lon = float(lon)
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.vx = float(vx)
        self.vy = float(vy)
        self.vz = float(vz)

class Path:
    """list of Lij types and Trajectory along a path"""

    def __init__(self,Lfilename,Pfilename):
        self.Lfilename = Lfilename
        self.Pfilename = Pfilename
        try:
            self._read_L_file()
        except IOError:
            print 'cannot open ' + Lfilename
        try:
            self._read_P_file()
        except IOError:
            print 'cannot open ' + Pfilename

    def _read_L_file(self):
        with open(self.Lfilename, 'r') as f:
            # get info from top line
            fl = f.readline().split()
            self.nsteps = int(fl[0])
            self.ictrl  = int(fl[1])
            self.eqincr = float(fl[2])
            self.temp   = float(fl[3])
            # skip the nextline
            _ = f.readline()
            # populate a list of Lij
            self.listLij = []
            for line in f.readlines():
                self.listLij.append( Lij( *tuple( line.split())))
            # if time step is negative, flip
            if self.listLij[0].tincr < 0:
                self.listLij.reverse()
                for l in self.listLij:
                    l.tincr = -l.tincr

    def _read_P_file(self):
        with open(self.Pfilename, 'r') as f:
            # skip the first 2 lines
            _ = f.readline()
            _ = f.readline()
            # populate a list of Trajectory objects
            self.listTrajectory = []
            for line in f.readlines():
                self.listTrajectory.append( Trajectory( *tuple( line.split())))

    def accumulate_strain(self):
        """get the total finite deformation along path"""
        # instantiate a finite deformation tensor
        F = Fij()
        # work along the path
        for L in self.listLij:
            F = update_strain(F,L)
        return F

    # def Flinn(self):
    #     """Get Flinn info along path"""

class Fij:
    """The Deformation Gradient Tensor Class
      with some methods to calculate attributes"""

    def __init__(self):
        self.Fij = np.identity(3)

    def rightCauchyGreen(self):
        return np.dot(np.transpose(self.Fij),self.Fij)

    def Finger(self):
        return np.linalg.inv(self.rightCauchyGreen())

    def leftCauchyGreen(self):
        return np.dot(self.Fij,np.transpose(self.Fij))

    def Cauchy(self):
        return np.linalg.inv(self.leftCauchyGreen())

    def Jacobian(self):
        return np.linalg.det(self.Fij)

    def rightStretch(self):
        U, s, Vh = np.linalg.svd(self.Fij)
        return np.dot( Vh.conj().T, np.dot( np.diag(s), Vh))

    def leftStretch(self):
        U, s, Vh = np.linalg.svd(self.Fij)
        return np.dot( U, np.dot( np.diag(s), U.conj().T))

    def Rotation(self):
        U, s, Vh = np.linalg.svd(self.Fij)
        return np.dot(U,Vh)

    def Principal(self):
        """get principal axis lengths and axes directions of finite strain ellipsoid"""
        w, v = np.linalg.eig(self.rightStretch())
        return w, np.dot(self.Rotation(), v)

    # def plot3d(self,axlim=3):
    #     """plot finite strain ellipsoid"""
    #     from mpl_toolkits.mplot3d import Axes3D
    #     import matplotlib.pyplot as plt
    #     from matplotlib.patches import FancyArrowPatch
    #     from mpl_toolkits.mplot3d import proj3d
    #     class Arrow3D(FancyArrowPatch):
    #
    #         def __init__(self, xs, ys, zs, *args, **kwargs):
    #             FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
    #             self._verts3d = xs, ys, zs
    #
    #         def draw(self, renderer):
    #             xs3d, ys3d, zs3d = self._verts3d
    #             xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
    #             self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
    #             FancyArrowPatch.draw(self, renderer)
    #     fig = plt.figure()
    #     ax = fig.gca(projection='3d')
    #     lim = [-axlim,axlim]
    #     ax.set_xlim(lim)
    #     ax.set_ylim(lim)
    #     ax.set_zlim(lim)
    #     ax.set_aspect("equal")
    #
    #     # draw sphere
    #     u, v = np.mgrid[0:2*np.pi:40j, 0:np.pi:20j]
    #     x = np.cos(u)*np.sin(v)
    #     y = np.sin(u)*np.sin(v)
    #     z = np.cos(v)
    #
    #     # put into array
    #     XYZ = np.vstack([x.flatten(),y.flatten(),z.flatten()])
    #     # deform according to F
    #     XYZ = np.dot(self.Fij,XYZ)
    #
    #     # put back into meshgrid
    #     a, b, c = np.vsplit(XYZ,3)
    #     x = np.reshape(a,x.shape)
    #     y = np.reshape(b,y.shape)
    #     z = np.reshape(c,z.shape)
    #
    #     # ax.plot_wireframe(x, y, z, color="r")
    #     ax.plot_surface(x,y,z,rstride=1,cstride=1,shade=True)
    #
    #     # plot principal vectors
    #     w, v = self.Principal()
    #     for jj in np.arange(3):
    #         a = Arrow3D([ 0, 1.2 * w[jj] * v[0, jj] ], [0, 1.2 * w[jj] * v[1, jj] ], [0, 1.2 * w[jj] * v[2, jj] ], mutation_scale=20,
    #                 lw=1, arrowstyle="-|>", color="k")
    #         ax.add_artist(a)
    #
    #     plt.show()

def update_strain(F,L):
    """update strain on finite deformation tensor F according to velocity gradients tensor L"""
    half_dtL = ( L.tincr / 2) * L.Lij
    A = np.identity(3) - half_dtL
    B = np.identity(3) + half_dtL
    F.Fij = np.dot(np.linalg.inv(A), np.dot( B, F.Fij))
    return F

def sph2cart(lat,lon,r):
    lat = np.deg2rad(lat)
    lon = np.deg2rad(lon)
    z = r * np.sin(lat)
    y = r * np.cos(lat) * np.sin(lon)
    x = r * np.cos(lat) * np.cos(lon)
    return x,y,z<commit_msg>comment out reverse time step when reading _L_ files (don't think this is appropriate)<commit_after>#!/usr/bin/env python

import numpy as np
# import matplotlib
# matplotlib.rcParams['figure.figsize'] = (20.0, 10.0)
# from mpl_toolkits.mplot3d import Axes3D
# import matplotlib.pyplot as plt

class Lij:
    """the Velocity Gradient Tensor Class"""

    def __init__(self, step, L11, L12, L13, L21, L22, L23, L31, L32, L33, tincr):
        self.step = int(step)
        self.Lij = np.array([[L11, L12, L13],[L21, L22, L23],[L31, L32, L33]],dtype='float_')
        self.tincr = float(tincr)

    def strain_rate(self):
        return (self.Lij + np.transpose(self.Lij))/2

    def rotation_rate(self):
        return (self.Lij - np.transpose(self.Lij))/2

class Trajectory:
    """Forward motion of particle: position and velocity"""
    def __init__(self, r, lat, lon, x, y, z, vx, vy, vz):
        self.r = float(r)
        self.lat = float(lat)
        self.lon = float(lon)
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.vx = float(vx)
        self.vy = float(vy)
        self.vz = float(vz)

class Path:
    """list of Lij types and Trajectory along a path"""

    def __init__(self,Lfilename,Pfilename):
        self.Lfilename = Lfilename
        self.Pfilename = Pfilename
        try:
            self._read_L_file()
        except IOError:
            print 'cannot open ' + Lfilename
        try:
            self._read_P_file()
        except IOError:
            print 'cannot open ' + Pfilename

    def _read_L_file(self):
        with open(self.Lfilename, 'r') as f:
            # get info from top line
            fl = f.readline().split()
            self.nsteps = int(fl[0])
            self.ictrl  = int(fl[1])
            self.eqincr = float(fl[2])
            self.temp   = float(fl[3])
            # skip the nextline
            _ = f.readline()
            # populate a list of Lij
            self.listLij = []
            for line in f.readlines():
                self.listLij.append( Lij( *tuple( line.split())))
            # if time step is negative, flip
            # if self.listLij[0].tincr < 0:
            #     self.listLij.reverse()
            #     for l in self.listLij:
            #         l.tincr = -l.tincr

    def _read_P_file(self):
        with open(self.Pfilename, 'r') as f:
            # skip the first 2 lines
            _ = f.readline()
            _ = f.readline()
            # populate a list of Trajectory objects
            self.listTrajectory = []
            for line in f.readlines():
                self.listTrajectory.append( Trajectory( *tuple( line.split())))

    def accumulate_strain(self):
        """get the total finite deformation along path"""
        # instantiate a finite deformation tensor
        F = Fij()
        # work along the path
        for L in self.listLij:
            F = update_strain(F,L)
        return F

    # def Flinn(self):
    #     """Get Flinn info along path"""

class Fij:
    """The Deformation Gradient Tensor Class
      with some methods to calculate attributes"""

    def __init__(self):
        self.Fij = np.identity(3)

    def rightCauchyGreen(self):
        return np.dot(np.transpose(self.Fij),self.Fij)

    def Finger(self):
        return np.linalg.inv(self.rightCauchyGreen())

    def leftCauchyGreen(self):
        return np.dot(self.Fij,np.transpose(self.Fij))

    def Cauchy(self):
        return np.linalg.inv(self.leftCauchyGreen())

    def Jacobian(self):
        return np.linalg.det(self.Fij)

    def rightStretch(self):
        U, s, Vh = np.linalg.svd(self.Fij)
        return np.dot( Vh.conj().T, np.dot( np.diag(s), Vh))

    def leftStretch(self):
        U, s, Vh = np.linalg.svd(self.Fij)
        return np.dot( U, np.dot( np.diag(s), U.conj().T))

    def Rotation(self):
        U, s, Vh = np.linalg.svd(self.Fij)
        return np.dot(U,Vh)

    def Principal(self):
        """get principal axis lengths and axes directions of finite strain ellipsoid"""
        w, v = np.linalg.eig(self.rightStretch())
        return w, np.dot(self.Rotation(),v)

    # def plot3d(self,axlim=3):
    #     """plot finite strain ellipsoid"""
    #     from mpl_toolkits.mplot3d import Axes3D
    #     import matplotlib.pyplot as plt
    #     from matplotlib.patches import FancyArrowPatch
    #     from mpl_toolkits.mplot3d import proj3d
    #     class Arrow3D(FancyArrowPatch):
    #
    #         def __init__(self, xs, ys, zs, *args, **kwargs):
    #             FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
    #             self._verts3d = xs, ys, zs
    #
    #         def draw(self, renderer):
    #             xs3d, ys3d, zs3d = self._verts3d
    #             xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
    #             self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
    #             FancyArrowPatch.draw(self, renderer)
    #     fig = plt.figure()
    #     ax = fig.gca(projection='3d')
    #     lim = [-axlim,axlim]
    #     ax.set_xlim(lim)
    #     ax.set_ylim(lim)
    #     ax.set_zlim(lim)
    #     ax.set_aspect("equal")
    #
    #     # draw sphere
    #     u, v = np.mgrid[0:2*np.pi:40j, 0:np.pi:20j]
    #     x = np.cos(u)*np.sin(v)
    #     y = np.sin(u)*np.sin(v)
    #     z = np.cos(v)
    #
    #     # put into array
    #     XYZ = np.vstack([x.flatten(),y.flatten(),z.flatten()])
    #     # deform according to F
    #     XYZ = np.dot(self.Fij,XYZ)
    #
    #     # put back into meshgrid
    #     a, b, c = np.vsplit(XYZ,3)
    #     x = np.reshape(a,x.shape)
    #     y = np.reshape(b,y.shape)
    #     z = np.reshape(c,z.shape)
    #
    #     # ax.plot_wireframe(x, y, z, color="r")
    #     ax.plot_surface(x,y,z,rstride=1,cstride=1,shade=True)
    #
    #     # plot principal vectors
    #     w, v = self.Principal()
    #     for jj in np.arange(3):
    #         a = Arrow3D([ 0, 1.2 * w[jj] * v[0, jj] ], [0, 1.2 * w[jj] * v[1, jj] ], [0, 1.2 * w[jj] * v[2, jj] ], mutation_scale=20,
    #                 lw=1, arrowstyle="-|>", color="k")
    #         ax.add_artist(a)
    #
    #     plt.show()

def update_strain(F,L):
    """update strain on finite deformation tensor F according to velocity gradients tensor L"""
    half_dtL = ( L.tincr / 2) * L.Lij
    A = np.identity(3) - half_dtL
    B = np.identity(3) + half_dtL
    F.Fij = np.dot(np.linalg.inv(A), np.dot( B, F.Fij))
    return F

def sph2cart(lat,lon,r):
    lat = np.deg2rad(lat)
    lon = np.deg2rad(lon)
    z = r * np.sin(lat)
    y = r * np.cos(lat) * np.sin(lon)
    x = r * np.cos(lat) * np.cos(lon)
    return x,y,z<|endoftext|>


<commit_before>import sys
sys.path.append("core")

from threading import Thread

import os
import os.path

global context
global moveConfig
global shadowList
global threads
global moduleToMove
global t
global onModuleMoved

def moveModuleInView(activeContext, onModuleMovedCallBack):
	global onModuleMoved
	onModuleMoved = onModuleMovedCallBack
	global context
	context = activeContext

	global moduleToMove

#	get module to move
	print "move", context.window.active_view().file_name()
	moduleToMove = context.getModuleByFullPath(context.window.active_view().file_name())
	if moduleToMove is None:
		return

	global moveConfig
	global shadowList

	moveConfig = {
		"type": moduleToMove.type,
		"fullPath": moduleToMove.getFullPath(),
		"name": moduleToMove.name[0:moduleToMove.name.find(".")],
		"importString":moduleToMove.getImportString()
	}

	if moveConfig["type"] == "script":
		packages = context.getScriptPackages()
	elif moveConfig["type"] == "text":
		packages = context.getTextPackages()

	context.window.show_quick_panel(packages, onPackageSelected, 0)
	shadowList = packages

def onPackageSelected(selectionIndex):
	global moveConfig
	global shadowList
	moduleSuggestiong = shadowList[selectionIndex]
	if selectionIndex == -1:
		return
	if selectionIndex == 0:
		moduleSuggestiong = ""

	if moveConfig["type"] == "script":
		packagePath = context.getBaseDir()+ context.settings["script_folder"] + "/" + moduleSuggestiong
		if os.path.exists(packagePath) == True:
			moveConfig["packageBase"] = context.settings["script_folder"]
	elif moveConfig["type"] == "text":

		packagePath = context.getBaseDir()+ context.settings["text_folder"] + "/" + moduleSuggestiong
		if os.path.exists(packagePath) == True:
			moveConfig["packageBase"] = context.settings["text_folder"]

	context.window.show_input_panel("Change module path/name to: ", moduleSuggestiong+moveConfig["name"], onNameDone, onNameChange, onNamceCancle)

def onNameDone(inputString):

	global moveConfig
	global onModuleMoved

	moveConfig["newImportString"] = inputString
	moveModule()
	onModuleMoved()

	updateModules()

	pass

def moveModule():
	global moduleToMove
	global context
	context.window.run_command("close_file")
	newFullPath  = moduleToMove.getFullPath().replace(moveConfig["importString"], moveConfig["newImportString"])

	dir = os.path.dirname(newFullPath)

	if not os.path.exists(dir):
		os.makedirs(dir)

	os.rename(moduleToMove.getFullPath(), newFullPath)
	context.window.open_file(newFullPath)

	pass

def onNameChange(input):
	pass

def onNamceCancle(input):
	pass

def updateModules():
	global moveConfig
	global context
	global moduleToMove
	global t

	# update module refs
	modulesList = context.getScriptModules()
	modulesList.remove(moduleToMove)
	count = 0
	t = Thread(target=update, args=(modulesList, moveConfig, updateDone))
	t.start()

def updateDone():
	print "update done"

	pass

def update(modules, moveConfig, callback):
	global moduleToMove
	for module in modules:
		f = open(module.getFullPath(), "r")
		data = f.read()
		f.close();

		if data.find("define([") is not -1 and data.find(moveConfig["importString"]) is not -1:
			updateModule(module, data, moveConfig)

	callback();
	pass

def updateModule(module, data, moveConfig):
	print "update module", module.name
	print "change package at : ", moveConfig["importString"]
	print "change package at : ", moveConfig["newImportString"]

	#update import string
	data = data.replace(moveConfig["importString"], moveConfig["newImportString"], 1)

	f = open(module.getFullPath(), "w+")
	f.write(data)
	f.close()
	pass

<commit_msg>done implementing move/rename > enter test phase<commit_after>import sys
sys.path.append("core")

from threading import Thread

import os
import os.path
import re

global context
global moveConfig
global shadowList
global threads
global moduleToMove
global t
global onModuleMoved

def moveModuleInView(activeContext, onModuleMovedCallBack):
	global onModuleMoved
	onModuleMoved = onModuleMovedCallBack
	global context
	context = activeContext

	global moduleToMove

#	get module to move
	moduleToMove = context.getModuleByFullPath(context.window.active_view().file_name())
	if moduleToMove is None:
		return

	global moveConfig
	global shadowList

	moveConfig = {
		"type": moduleToMove.type,
		"fullPath": moduleToMove.getFullPath(),
		"name": moduleToMove.name[0:moduleToMove.name.find(".")],
		"importString":moduleToMove.package + moduleToMove.name.split(moduleToMove.ext)[0]
	}

	if moveConfig["type"] == "script":
		packages = context.getScriptPackages()
	elif moveConfig["type"] == "text":
		packages = context.getTextPackages()

	context.window.show_quick_panel(packages, onPackageSelected, 0)
	shadowList = packages

def onPackageSelected(selectionIndex):
	global moveConfig
	global shadowList
	moduleSuggestiong = shadowList[selectionIndex]
	if selectionIndex == -1:
		return
	if selectionIndex == 0:
		moduleSuggestiong = ""

	if moveConfig["type"] == "script":
		packagePath = context.getBaseDir()+ context.settings["script_folder"] + "/" + moduleSuggestiong
		if os.path.exists(packagePath) == True:
			moveConfig["packageBase"] = context.settings["script_folder"]
	elif moveConfig["type"] == "text":

		packagePath = context.getBaseDir()+ context.settings["text_folder"] + "/" + moduleSuggestiong
		if os.path.exists(packagePath) == True:
			moveConfig["packageBase"] = context.settings["text_folder"]

	context.window.show_input_panel("Change module path/name to: ", moduleSuggestiong+moveConfig["name"], onNameDone, onNameChange, onNamceCancle)

def onNameDone(inputString):

	global moveConfig
	global onModuleMoved
	global context

	moveConfig["newImportString"] = inputString
	moveConfig["newName"] = inputString[inputString.rfind("/")+1:]

	moveModule()
	onModuleMoved()

	updateModules()

	pass

def moveModule():
	global moduleToMove
	global context
	global moveConfig
	context.window.run_command("close_file")

	if moduleToMove.type is "text":
		current = context.settings["text_folder"] + "/" +moveConfig["importString"]
		new = context.settings["text_folder"] + "/" +moveConfig["newImportString"]
	else:
		current = context.settings["script_folder"] + "/" +moveConfig["importString"]
		new = context.settings["script_folder"] + "/" +moveConfig["newImportString"]

	newFullPath  = moduleToMove.getFullPath().replace(current, new)

	dir = os.path.dirname(newFullPath)

	if not os.path.exists(dir):
		os.makedirs(dir)

	os.rename(moduleToMove.getFullPath(), newFullPath)
	context.window.open_file(newFullPath)

	pass

def onNameChange(input):
	pass

def onNamceCancle(input):
	pass

def updateModules():
	global moveConfig
	global context
	global moduleToMove
	global t

	if moduleToMove.type is "text":
		#moveConfig["importString"] = "text!" + context.settings["texts_name"] + "/" + moveConfig["importString"] + ".html"
		#moveConfig["newImportString"] = "text!" + context.settings["texts_name"] + "/" + moveConfig["newImportString"] + ".html"
		pass

	# update module refs
	modulesList = context.getScriptModules()
	if moduleToMove in modulesList:
		modulesList.remove(moduleToMove)
	count = 0
	t = Thread(target=update, args=(modulesList, moveConfig, updateDone))
	t.start()

def updateDone():
	pass

def update(modules, moveConfig, callback):
	global moduleToMove
	for module in modules:
		f = open(module.getFullPath(), "r")
		data = f.read()
		f.close();

		if data.find("define([") is not -1 and data.find(moveConfig["importString"]) is not -1:
			updateModule(module, data, moveConfig)

	callback();
	pass

def updateModule(module, data, moveConfig):

	#update import string
	data = data.replace("'"+moveConfig["importString"]+"'", "'"+moveConfig["newImportString"]+"'", 1)
	#data = re.sub('\\b'+moveConfig["importString"]+'\\b', moveConfig["importString"], data)

	#update variable name
	if moveConfig["name"] is not moveConfig["newName"]:
		data = re.sub('\\b'+moveConfig["name"]+'\\b', moveConfig["newName"], data)

	f = open(module.getFullPath(), "w+")
	f.write(data)
	f.close()
	pass

<|endoftext|>


<commit_before>import datetime

from django.conf import settings
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.sites.models import Site
from django.core import mail
from django.core.exceptions import ImproperlyConfigured
from django.core.handlers.wsgi import WSGIRequest
from django.test import Client
from django.test import TestCase

from registration import forms
from registration import signals
from registration.admin import RegistrationAdmin
from registration.backends import get_backend
from registration.backends.default import DefaultBackend
from registration.backends.simple import SimpleBackend
from registration.models import RegistrationProfile

class _MockRequestClient(Client):
    """
    A ``django.test.Client`` subclass which can return mock
    ``HttpRequest`` objects.

    """
    def request(self, **request):
        """
        Rather than issuing a request and returning the response, this
        simply constructs an ``HttpRequest`` object and returns it.

        """
        environ = {
            'HTTP_COOKIE':      self.cookies,
            'PATH_INFO':         '/',
            'QUERY_STRING':      '',
            'REMOTE_ADDR':       '127.0.0.1',
            'REQUEST_METHOD':    'GET',
            'SCRIPT_NAME':       '',
            'SERVER_NAME':       'testserver',
            'SERVER_PORT':       '80',
            'SERVER_PROTOCOL':   'HTTP/1.1',
            'wsgi.version':      (1,0),
            'wsgi.url_scheme':   'http',
            'wsgi.errors':       self.errors,
            'wsgi.multiprocess': True,
            'wsgi.multithread':  False,
            'wsgi.run_once':     False,
            }
        environ.update(self.defaults)
        environ.update(request)
        request = WSGIRequest(environ)

        # We have to manually add a session since we'll be bypassing
        # the middleware chain.
        session_middleware = SessionMiddleware()
        session_middleware.process_request(request)
        return request

def _mock_request():
    """
    Construct and return a mock ``HttpRequest`` object; this is used
    in testing backend methods which expect an ``HttpRequest`` but
    which are not being called from views.

    """
    return _MockRequestClient().request()

class BackendRetrievalTests(TestCase):
    """
    Test that utilities for retrieving the active backend work
    properly.

    """
    def test_get_backend(self):
        """
        Verify that ``get_backend()`` returns the correct value when
        passed a valid backend.

        """
        self.failUnless(isinstance(get_backend('registration.backends.default.DefaultBackend'),
                                   DefaultBackend))

    def test_backend_error_invalid(self):
        """
        Test that a nonexistent/unimportable backend raises the
        correct exception.

        """
        self.assertRaises(ImproperlyConfigured, get_backend,
                          'registration.backends.doesnotexist.NonExistentBackend')

    def test_backend_attribute_error(self):
        """
        Test that a backend module which exists but does not have a
        class of the specified name raises the correct exception.

        """
        self.assertRaises(ImproperlyConfigured, get_backend,
                          'registration.backends.default.NonexistentBackend')

class DefaultRegistrationBackendTests(TestCase):
    """
    Test the default registration backend.

    Running these tests successfull will require two templates to be
    created for the sending of activation emails; details on these
    templates and their contexts may be found in the documentation for
    the default backend.

    """
    backend = DefaultBackend()

    def setUp(self):
        """
        Create an instance of the default backend for use in testing,
        and set ``ACCOUNT_ACTIVATION_DAYS`` if it's not set already.

        """
        self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None)
        if self.old_activation is None:
            settings.ACCOUNT_ACTIVATION_DAYS = 7

    def tearDown(self):
        """
        Yank out ``ACCOUNT_ACTIVATION_DAYS`` back out if it wasn't
        originally set.

        """
        if self.old_activation is None:
            settings.ACCOUNT_ACTIVATION_DAYS = self.old_activation

    def test_registration(self):
        """
        Test the registration process: registration creates a new
        inactive account and a new profile with activation key,
        populates the correct account data and sends an activation
        email.

        """
        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        # Details of the returned user must match what went in.
        self.assertEqual(new_user.username, 'bob')
        self.failUnless(new_user.check_password('secret'))
        self.assertEqual(new_user.email, 'bob@example.com')

        # New user must not be active.
        self.failIf(new_user.is_active)

        # A registration profile was created, and an activation email
        # was sent.
        self.assertEqual(RegistrationProfile.objects.count(), 1)
        self.assertEqual(len(mail.outbox), 1)

    def test_registration_no_sites(self):
        """
        Test that registration still functions properly when
        ``django.contrib.sites`` is not installed; the fallback will
        be a ``RequestSite`` instance.

        """
        Site._meta.installed = False

        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        self.assertEqual(new_user.username, 'bob')
        self.failUnless(new_user.check_password('secret'))
        self.assertEqual(new_user.email, 'bob@example.com')

        self.failIf(new_user.is_active)

        self.assertEqual(RegistrationProfile.objects.count(), 1)
        self.assertEqual(len(mail.outbox), 1)

        Site._meta.installed = True

    def test_valid_activation(self):
        """
        Test the activation process: activating within the permitted
        window sets the account's ``is_active`` field to ``True`` and
        resets the activation key.

        """
        valid_user = self.backend.register(_mock_request(),
                                           username='alice',
                                           email='alice@example.com',
                                           password1='swordfish')

        valid_profile = RegistrationProfile.objects.get(user=valid_user)
        activated = self.backend.activate(_mock_request(),
                                          valid_profile.activation_key)
        self.assertEqual(activated.username, valid_user.username)
        self.failUnless(activated.is_active)

        # Fetch the profile again to verify its activation key has
        # been reset.
        valid_profile = RegistrationProfile.objects.get(user=valid_user)
        self.assertEqual(valid_profile.activation_key,
                         RegistrationProfile.ACTIVATED)

    def test_invalid_activation(self):
        """
        Test the activation process: trying to activate outside the
        permitted window fails, and leaves the account inactive.

        """
        expired_user = self.backend.register(_mock_request(),
                                             username='bob',
                                             email='bob@example.com',
                                             password1='secret')

        expired_user.date_joined = expired_user.date_joined - datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
        expired_user.save()
        expired_profile = RegistrationProfile.objects.get(user=expired_user)
        self.failIf(self.backend.activate(_mock_request(),
                                          expired_profile.activation_key))
        self.failUnless(expired_profile.activation_key_expired())

    def test_allow(self):
        """
        Test that the setting ``REGISTRATION_OPEN`` appropriately
        controls whether registration is permitted.

        """
        old_allowed = getattr(settings, 'REGISTRATION_OPEN', True)
        settings.REGISTRATION_OPEN = True
        self.failUnless(self.backend.registration_allowed(_mock_request()))

        settings.REGISTRATION_OPEN = False
        self.failIf(self.backend.registration_allowed(_mock_request()))
        settings.REGISTRATION_OPEN = old_allowed

    def test_form_class(self):
        """
        Test that the default form class returned is
        ``registration.forms.RegistrationForm``.

        """
        self.failUnless(self.backend.get_form_class(_mock_request()) is forms.RegistrationForm)

    def test_post_registration_redirect(self):
        """
        Test that the default post-registration redirect is the named
        pattern ``registration_complete``.

        """
        self.assertEqual(self.backend.post_registration_redirect(_mock_request(), User()),
                         ('registration_complete', (), {}))

    def test_registration_signal(self):
        """
        Test that registering a user sends the ``user_registered``
        signal.

        """
        def receiver(sender, **kwargs):
            self.failUnless('user' in kwargs)
            self.assertEqual(kwargs['user'].username, 'bob')
            self.failUnless('request' in kwargs)
            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
            received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_registered.connect(receiver, sender=self.backend.__class__)

        self.backend.register(_mock_request(),
                              username='bob',
                              email='bob@example.com',
                              password1='secret')

        self.assertEqual(len(received_signals), 1)
        self.assertEqual(received_signals, [signals.user_registered])

    def test_activation_signal_success(self):
        """
        Test that successfully activating a user sends the
        ``user_activated`` signal.

        """
        def receiver(sender, **kwargs):
            self.failUnless('user' in kwargs)
            self.assertEqual(kwargs['user'].username, 'bob')
            self.failUnless('request' in kwargs)
            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
            received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_activated.connect(receiver, sender=self.backend.__class__)

        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')
        profile = RegistrationProfile.objects.get(user=new_user)
        self.backend.activate(_mock_request(), profile.activation_key)

        self.assertEqual(len(received_signals), 1)
        self.assertEqual(received_signals, [signals.user_activated])

    def test_activation_signal_failure(self):
        """
        Test that an unsuccessful activation attempt does not send the
        ``user_activated`` signal.

        """
        receiver = lambda sender, **kwargs: received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_activated.connect(receiver, sender=self.backend.__class__)

        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')
        new_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1)
        new_user.save()
        profile = RegistrationProfile.objects.get(user=new_user)
        self.backend.activate(_mock_request(), profile.activation_key)

        self.assertEqual(len(received_signals), 0)

    def test_email_send_action(self):
        """
        Test re-sending of activation emails via admin action.

        """
        admin_class = RegistrationAdmin(RegistrationProfile, admin.site)

        alice = self.backend.register(_mock_request(),
                                      username='alice',
                                      email='alice@example.com',
                                      password1='swordfish')

        admin_class.resend_activation_email(_mock_request(),
                                            RegistrationProfile.objects.all())
        self.assertEqual(len(mail.outbox), 2) # One on registering, one more on the resend.

        RegistrationProfile.objects.filter(user=alice).update(activation_key=RegistrationProfile.ACTIVATED)
        admin_class.resend_activation_email(_mock_request(),
                                            RegistrationProfile.objects.all())
        self.assertEqual(len(mail.outbox), 2) # No additional email because the account has activated.

    def test_activation_action(self):
        """
        Test manual activation of users view admin action.

        """
        admin_class = RegistrationAdmin(RegistrationProfile, admin.site)

        alice = self.backend.register(_mock_request(),
                                      username='alice',
                                      email='alice@example.com',
                                      password1='swordfish')

        admin_class.activate_users(_mock_request(),
                                   RegistrationProfile.objects.all())
        self.failUnless(User.objects.get(username='alice').is_active)

class SimpleRegistrationBackendTests(TestCase):
    """
    Test the simple registration backend, which does signup and
    immediate activation.

    """
    backend = SimpleBackend()

    def test_registration(self):
        """
        Test the registration process: registration creates a new
        inactive account and a new profile with activation key,
        populates the correct account data and sends an activation
        email.

        """
        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        # Details of the returned user must match what went in.
        self.assertEqual(new_user.username, 'bob')
        self.failUnless(new_user.check_password('secret'))
        self.assertEqual(new_user.email, 'bob@example.com')

        # New user must not be active.
        self.failUnless(new_user.is_active)

    def test_allow(self):
        """
        Test that the setting ``REGISTRATION_OPEN`` appropriately
        controls whether registration is permitted.

        """
        old_allowed = getattr(settings, 'REGISTRATION_OPEN', True)
        settings.REGISTRATION_OPEN = True
        self.failUnless(self.backend.registration_allowed(_mock_request()))

        settings.REGISTRATION_OPEN = False
        self.failIf(self.backend.registration_allowed(_mock_request()))
        settings.REGISTRATION_OPEN = old_allowed

    def test_form_class(self):
        """
        Test that the default form class returned is
        ``registration.forms.RegistrationForm``.

        """
        self.failUnless(self.backend.get_form_class(_mock_request()) is forms.RegistrationForm)

    def test_post_registration_redirect(self):
        """
        Test that the default post-registration redirect is the public
        URL of the new user account.

        """
        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        self.assertEqual(self.backend.post_registration_redirect(_mock_request(), new_user),
                         (new_user.get_absolute_url(), (), {}))

    def test_registration_signal(self):
        """
        Test that registering a user sends the ``user_registered``
        signal.

        """
        def receiver(sender, **kwargs):
            self.failUnless('user' in kwargs)
            self.assertEqual(kwargs['user'].username, 'bob')
            self.failUnless('request' in kwargs)
            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
            received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_registered.connect(receiver, sender=self.backend.__class__)

        self.backend.register(_mock_request(),
                              username='bob',
                              email='bob@example.com',
                              password1='secret')

        self.assertEqual(len(received_signals), 1)
        self.assertEqual(received_signals, [signals.user_registered])

    def test_activation(self):
        """
        Test that activating against this backend is an error.

        """
        self.assertRaises(NotImplementedError, self.backend.activate,
                          request=_mock_request())

    def test_post_activation_redirect(self):
        """
        Test that asking for a post-activation redirect from this
        backend is an error.

        """
        self.assertRaises(NotImplementedError, self.backend.post_activation_redirect,
                          request=_mock_request(), user=User())
<commit_msg>Fix #117: Add wsgi.input to mock request factory so tests run cleanly under newer Django versions.<commit_after>import datetime

from django.conf import settings
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.sites.models import Site
from django.core import mail
from django.core.exceptions import ImproperlyConfigured
from django.core.handlers.wsgi import WSGIRequest
from django.test import Client
from django.test import TestCase

from registration import forms
from registration import signals
from registration.admin import RegistrationAdmin
from registration.backends import get_backend
from registration.backends.default import DefaultBackend
from registration.backends.simple import SimpleBackend
from registration.models import RegistrationProfile

class _MockRequestClient(Client):
    """
    A ``django.test.Client`` subclass which can return mock
    ``HttpRequest`` objects.

    """
    def request(self, **request):
        """
        Rather than issuing a request and returning the response, this
        simply constructs an ``HttpRequest`` object and returns it.

        """
        environ = {
            'HTTP_COOKIE': self.cookies,
            'PATH_INFO': '/',
            'QUERY_STRING': '',
            'REMOTE_ADDR': '127.0.0.1',
            'REQUEST_METHOD': 'GET',
            'SCRIPT_NAME': '',
            'SERVER_NAME': 'testserver',
            'SERVER_PORT': '80',
            'SERVER_PROTOCOL': 'HTTP/1.1',
            'wsgi.version': (1,0),
            'wsgi.url_scheme': 'http',
            'wsgi.errors': self.errors,
            'wsgi.multiprocess':True,
            'wsgi.multithread': False,
            'wsgi.run_once': False,
            'wsgi.input': None,
            }
        environ.update(self.defaults)
        environ.update(request)
        request = WSGIRequest(environ)

        # We have to manually add a session since we'll be bypassing
        # the middleware chain.
        session_middleware = SessionMiddleware()
        session_middleware.process_request(request)
        return request

def _mock_request():
    """
    Construct and return a mock ``HttpRequest`` object; this is used
    in testing backend methods which expect an ``HttpRequest`` but
    which are not being called from views.

    """
    return _MockRequestClient().request()

class BackendRetrievalTests(TestCase):
    """
    Test that utilities for retrieving the active backend work
    properly.

    """
    def test_get_backend(self):
        """
        Verify that ``get_backend()`` returns the correct value when
        passed a valid backend.

        """
        self.failUnless(isinstance(get_backend('registration.backends.default.DefaultBackend'),
                                   DefaultBackend))

    def test_backend_error_invalid(self):
        """
        Test that a nonexistent/unimportable backend raises the
        correct exception.

        """
        self.assertRaises(ImproperlyConfigured, get_backend,
                          'registration.backends.doesnotexist.NonExistentBackend')

    def test_backend_attribute_error(self):
        """
        Test that a backend module which exists but does not have a
        class of the specified name raises the correct exception.

        """
        self.assertRaises(ImproperlyConfigured, get_backend,
                          'registration.backends.default.NonexistentBackend')

class DefaultRegistrationBackendTests(TestCase):
    """
    Test the default registration backend.

    Running these tests successfull will require two templates to be
    created for the sending of activation emails; details on these
    templates and their contexts may be found in the documentation for
    the default backend.

    """
    backend = DefaultBackend()

    def setUp(self):
        """
        Create an instance of the default backend for use in testing,
        and set ``ACCOUNT_ACTIVATION_DAYS`` if it's not set already.

        """
        self.old_activation = getattr(settings, 'ACCOUNT_ACTIVATION_DAYS', None)
        if self.old_activation is None:
            settings.ACCOUNT_ACTIVATION_DAYS = 7

    def tearDown(self):
        """
        Yank out ``ACCOUNT_ACTIVATION_DAYS`` back out if it wasn't
        originally set.

        """
        if self.old_activation is None:
            settings.ACCOUNT_ACTIVATION_DAYS = self.old_activation

    def test_registration(self):
        """
        Test the registration process: registration creates a new
        inactive account and a new profile with activation key,
        populates the correct account data and sends an activation
        email.

        """
        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        # Details of the returned user must match what went in.
        self.assertEqual(new_user.username, 'bob')
        self.failUnless(new_user.check_password('secret'))
        self.assertEqual(new_user.email, 'bob@example.com')

        # New user must not be active.
        self.failIf(new_user.is_active)

        # A registration profile was created, and an activation email
        # was sent.
        self.assertEqual(RegistrationProfile.objects.count(), 1)
        self.assertEqual(len(mail.outbox), 1)

    def test_registration_no_sites(self):
        """
        Test that registration still functions properly when
        ``django.contrib.sites`` is not installed; the fallback will
        be a ``RequestSite`` instance.

        """
        Site._meta.installed = False

        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        self.assertEqual(new_user.username, 'bob')
        self.failUnless(new_user.check_password('secret'))
        self.assertEqual(new_user.email, 'bob@example.com')

        self.failIf(new_user.is_active)

        self.assertEqual(RegistrationProfile.objects.count(), 1)
        self.assertEqual(len(mail.outbox), 1)

        Site._meta.installed = True

    def test_valid_activation(self):
        """
        Test the activation process: activating within the permitted
        window sets the account's ``is_active`` field to ``True`` and
        resets the activation key.

        """
        valid_user = self.backend.register(_mock_request(),
                                           username='alice',
                                           email='alice@example.com',
                                           password1='swordfish')

        valid_profile = RegistrationProfile.objects.get(user=valid_user)
        activated = self.backend.activate(_mock_request(),
                                          valid_profile.activation_key)
        self.assertEqual(activated.username, valid_user.username)
        self.failUnless(activated.is_active)

        # Fetch the profile again to verify its activation key has
        # been reset.
        valid_profile = RegistrationProfile.objects.get(user=valid_user)
        self.assertEqual(valid_profile.activation_key,
                         RegistrationProfile.ACTIVATED)

    def test_invalid_activation(self):
        """
        Test the activation process: trying to activate outside the
        permitted window fails, and leaves the account inactive.

        """
        expired_user = self.backend.register(_mock_request(),
                                             username='bob',
                                             email='bob@example.com',
                                             password1='secret')

        expired_user.date_joined = expired_user.date_joined - datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS)
        expired_user.save()
        expired_profile = RegistrationProfile.objects.get(user=expired_user)
        self.failIf(self.backend.activate(_mock_request(),
                                          expired_profile.activation_key))
        self.failUnless(expired_profile.activation_key_expired())

    def test_allow(self):
        """
        Test that the setting ``REGISTRATION_OPEN`` appropriately
        controls whether registration is permitted.

        """
        old_allowed = getattr(settings, 'REGISTRATION_OPEN', True)
        settings.REGISTRATION_OPEN = True
        self.failUnless(self.backend.registration_allowed(_mock_request()))

        settings.REGISTRATION_OPEN = False
        self.failIf(self.backend.registration_allowed(_mock_request()))
        settings.REGISTRATION_OPEN = old_allowed

    def test_form_class(self):
        """
        Test that the default form class returned is
        ``registration.forms.RegistrationForm``.

        """
        self.failUnless(self.backend.get_form_class(_mock_request()) is forms.RegistrationForm)

    def test_post_registration_redirect(self):
        """
        Test that the default post-registration redirect is the named
        pattern ``registration_complete``.

        """
        self.assertEqual(self.backend.post_registration_redirect(_mock_request(), User()),
                         ('registration_complete', (), {}))

    def test_registration_signal(self):
        """
        Test that registering a user sends the ``user_registered``
        signal.

        """
        def receiver(sender, **kwargs):
            self.failUnless('user' in kwargs)
            self.assertEqual(kwargs['user'].username, 'bob')
            self.failUnless('request' in kwargs)
            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
            received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_registered.connect(receiver, sender=self.backend.__class__)

        self.backend.register(_mock_request(),
                              username='bob',
                              email='bob@example.com',
                              password1='secret')

        self.assertEqual(len(received_signals), 1)
        self.assertEqual(received_signals, [signals.user_registered])

    def test_activation_signal_success(self):
        """
        Test that successfully activating a user sends the
        ``user_activated`` signal.

        """
        def receiver(sender, **kwargs):
            self.failUnless('user' in kwargs)
            self.assertEqual(kwargs['user'].username, 'bob')
            self.failUnless('request' in kwargs)
            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
            received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_activated.connect(receiver, sender=self.backend.__class__)

        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')
        profile = RegistrationProfile.objects.get(user=new_user)
        self.backend.activate(_mock_request(), profile.activation_key)

        self.assertEqual(len(received_signals), 1)
        self.assertEqual(received_signals, [signals.user_activated])

    def test_activation_signal_failure(self):
        """
        Test that an unsuccessful activation attempt does not send the
        ``user_activated`` signal.

        """
        receiver = lambda sender, **kwargs: received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_activated.connect(receiver, sender=self.backend.__class__)

        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')
        new_user.date_joined -= datetime.timedelta(days=settings.ACCOUNT_ACTIVATION_DAYS + 1)
        new_user.save()
        profile = RegistrationProfile.objects.get(user=new_user)
        self.backend.activate(_mock_request(), profile.activation_key)

        self.assertEqual(len(received_signals), 0)

    def test_email_send_action(self):
        """
        Test re-sending of activation emails via admin action.

        """
        admin_class = RegistrationAdmin(RegistrationProfile, admin.site)

        alice = self.backend.register(_mock_request(),
                                      username='alice',
                                      email='alice@example.com',
                                      password1='swordfish')

        admin_class.resend_activation_email(_mock_request(),
                                            RegistrationProfile.objects.all())
        self.assertEqual(len(mail.outbox), 2) # One on registering, one more on the resend.

        RegistrationProfile.objects.filter(user=alice).update(activation_key=RegistrationProfile.ACTIVATED)
        admin_class.resend_activation_email(_mock_request(),
                                            RegistrationProfile.objects.all())
        self.assertEqual(len(mail.outbox), 2) # No additional email because the account has activated.

    def test_activation_action(self):
        """
        Test manual activation of users view admin action.

        """
        admin_class = RegistrationAdmin(RegistrationProfile, admin.site)

        alice = self.backend.register(_mock_request(),
                                      username='alice',
                                      email='alice@example.com',
                                      password1='swordfish')

        admin_class.activate_users(_mock_request(),
                                   RegistrationProfile.objects.all())
        self.failUnless(User.objects.get(username='alice').is_active)

class SimpleRegistrationBackendTests(TestCase):
    """
    Test the simple registration backend, which does signup and
    immediate activation.

    """
    backend = SimpleBackend()

    def test_registration(self):
        """
        Test the registration process: registration creates a new
        inactive account and a new profile with activation key,
        populates the correct account data and sends an activation
        email.

        """
        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        # Details of the returned user must match what went in.
        self.assertEqual(new_user.username, 'bob')
        self.failUnless(new_user.check_password('secret'))
        self.assertEqual(new_user.email, 'bob@example.com')

        # New user must not be active.
        self.failUnless(new_user.is_active)

    def test_allow(self):
        """
        Test that the setting ``REGISTRATION_OPEN`` appropriately
        controls whether registration is permitted.

        """
        old_allowed = getattr(settings, 'REGISTRATION_OPEN', True)
        settings.REGISTRATION_OPEN = True
        self.failUnless(self.backend.registration_allowed(_mock_request()))

        settings.REGISTRATION_OPEN = False
        self.failIf(self.backend.registration_allowed(_mock_request()))
        settings.REGISTRATION_OPEN = old_allowed

    def test_form_class(self):
        """
        Test that the default form class returned is
        ``registration.forms.RegistrationForm``.

        """
        self.failUnless(self.backend.get_form_class(_mock_request()) is forms.RegistrationForm)

    def test_post_registration_redirect(self):
        """
        Test that the default post-registration redirect is the public
        URL of the new user account.

        """
        new_user = self.backend.register(_mock_request(),
                                         username='bob',
                                         email='bob@example.com',
                                         password1='secret')

        self.assertEqual(self.backend.post_registration_redirect(_mock_request(), new_user),
                         (new_user.get_absolute_url(), (), {}))

    def test_registration_signal(self):
        """
        Test that registering a user sends the ``user_registered``
        signal.

        """
        def receiver(sender, **kwargs):
            self.failUnless('user' in kwargs)
            self.assertEqual(kwargs['user'].username, 'bob')
            self.failUnless('request' in kwargs)
            self.failUnless(isinstance(kwargs['request'], WSGIRequest))
            received_signals.append(kwargs.get('signal'))

        received_signals = []
        signals.user_registered.connect(receiver, sender=self.backend.__class__)

        self.backend.register(_mock_request(),
                              username='bob',
                              email='bob@example.com',
                              password1='secret')

        self.assertEqual(len(received_signals), 1)
        self.assertEqual(received_signals, [signals.user_registered])

    def test_activation(self):
        """
        Test that activating against this backend is an error.

        """
        self.assertRaises(NotImplementedError, self.backend.activate,
                          request=_mock_request())

    def test_post_activation_redirect(self):
        """
        Test that asking for a post-activation redirect from this
        backend is an error.

        """
        self.assertRaises(NotImplementedError, self.backend.post_activation_redirect,
                          request=_mock_request(), user=User())
<|endoftext|>