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

"""
redi.models
~~~~~~~~~~~

This module contains most of the functionality of redi.

"""

import uuid

from operator import itemgetter
from UserDict import DictMixin
from . import config

from .utils import ListMixin, is_collection, compress_key, expand_key

class RedisKey(object):
    """Contains methods that can be applied to any Redis key."""

    def __init__(self, key, redis=None, o=False):
        super(RedisKey, self).__init__()

        self.key = key
        self._o = o

        if redis is None:
            self.redis = config.redis

        self.redis = redis
        self.uuid = uuid.uuid4().hex

    def __repr__(self):
        return '<redis-key {0}>'.format(self.key)

    @property
    def _(self):
        return 'hi'

    def delete(self):
        """Removes this key from Redis."""
        return self.redis.delete(self.key)

    def __getattribute__(self, key):

        if key not in ('_o', 'children', 'key', 'redis'):
            if self._o:
                if key in self.children:

                    key = compress_key(expand_key(self.key) + [key])

                    return auto_type(key, redis=self.redis, o=True)

        return object.__getattribute__(self, key)

    def expire(self, s):
        """Expires this key from Redis in given seconds."""
        # TODO: Accept datetime for expire_at

        return self.redis.expire(self.key, s)

    def rename(self, new_name, safe=True):
        """Renames this key."""

        new_name = compress_key(new_name)

        if safe:
            if self.redis.renamenx(self.key, new_name):
                self.key = new_name
                return True
            return False
        else:
            self.redis.rename(self.key, new_name)
            self.key = new_name
            return True

    @property
    def children(self):
        """Lists all children of current key."""

        namespace = compress_key(expand_key(self.key) + ['*'])

        keys = []

        for key in self.redis.keys(namespace):
            keys.append(expand_key(key)[-1])

        return keys

    @property
    def siblings(self):
        """Lists all siblings of current key."""

        namespace = compress_key(expand_key(self.key)[:-1]+ ['*'])

        keys = self.redis.keys(namespace)

        # clean up results
        keys.remove(self.key)

        for key in self.children:
            try:
                keys.remove(key)
            except ValueError:
                pass

        return keys

    @staticmethod
    def to_redis(o):
        """Converts Python datatypes to Redis values."""

        # don't serialize internal datatype classesf
        if isinstance(o, SubList) or isinstance(o, SubDict):
            o = o.data

        return config.encoder(o)

    def to_python(self, o):
        """Converts Redis values to Python datatypes."""
        try:
            v = config.decoder(o)

            if isinstance(v, dict):
                return SubDict(v, self.save)

            elif is_collection(v):
                return SubList(v, self.save)

            try:
                if not isinstance(v, float):
                    return int(v)
            except ValueError:
                pass

            try:
                if not isinstance(v, int):
                    return float(v)
            except ValueError:
                pass

            return v

        except (ValueError, TypeError):
            try:
                return unicode(o, config.str_codec)
            except (UnicodeDecodeError, TypeError):
                return o

    def save(self, *args):
        pass

class RedisString(RedisKey):
    """Redis String interface."""

    def __init__(self, key, redis=None, o=False):
        super(RedisString, self).__init__(key, redis=redis, o=o)

        self.key = key

    def __repr__(self):
        return '<redis-string {0}>'.format(self.key)

    @property
    def _raw(self):
        """Returns raw Redis data."""
        return self.redis.get(self.key)

    def save(self, value):
        """Saves current value to Database."""
        v = self.to_redis(value)
        return self.redis.set(self.key, v)

    @property
    def data(self):
        """Writes value to database."""
        v = self.redis.get(self.key)
        return self.to_python(v)

    @data.setter
    def data(self, value):
        """Writes value to database."""
        self.save(value)

    @property
    def type(self):
        return self.data.__class__

    def write(self):
        return self.data.write()

    def __getitem__(self, item):
        return self.data.__getitem__(item)

    def __setitem__(self, k, v):
        return self.data.__setitem__(k, v)

    def __delitem__(self, k):
        return self.data.__delitem__(k)

class RedisListString(RedisString, ListMixin):
    """Redis value of awesomeness."""

    def __init__(self, key, redis, o=False):
        super(RedisListString, self).__init__(key, redis=redis, o=o)
        self.key = key

    def __repr__(self):
        return '<redis-list-string {0}>'.format(self.key)

    def __getitem__(self, item):
        return self.data.__getitem__(item)

    def __setitem__(self, k, v):
        return self.data.__setitem__(k, v)

    def __delitem__(self, k):
        return self.data.__delitem__(k)

    def _get_element(self, i):
        return self.data._get_element(i)

    def _set_element(self, i, value):
        return self.data._set_element(i, value)

    def __len__(self):
        return self.data.__len__()

    def _resize_region(self, start, end, new_size):
        return self.data._resize_region(start, end, new_size)

    def _constructor(self, iter):
        return self.data._constructor(iter)

class RedisDictString(RedisString, DictMixin):
    """Redis value of awesomeness."""

    def __init__(self, key, redis, o=False):
        super(RedisDictString, self).__init__(key, redis=redis, o=o)
        self.key = key

    def __repr__(self):
        return '<redis-dict-string {0}>'.format(self.key)

    def get(self, item):
        return self.data.get(item)

    def keys(self):
        return self.data.keys()

class RedisList(RedisKey):
    """Redis list of awesomeness."""

    def __init__(self, key, redis, o=False):
        super(RedisList, self).__init__(key, redis=redis, o=o)
        self.key = key

    def __repr__(self):
        return '<redis-list {0}>'.format(self.key)

    @property
    def _raw(self):
        for v in self.redis.lrange(self.key, 0, -1):
            yield v

    def save(self, value, i=None):
        """Save list."""

        self[i] = value

    def __getitem__(self, i):
        is_single = not isinstance(i, slice)

        if is_single:
            value = self.redis.lindex(self.key, i)
            values = self.to_python(value)
            try:
                values.i = i
            except AttributeError:
                pass

        else:
            start = 0 if i.start is None else i.start
            stop = -1 if i.stop is None else i.stop

            values = self.redis.lrange(self.key, start, stop)
            values = map(self.to_python, values)

            for i in range(start, start+len(values)):
                try:
                    values[i].i = i
                except AttributeError:
                    pass

        return values

    def __setitem__(self, i, value):
        v = self.to_redis(value)
        return self.redis.lset(self.key, i, v)

    def __delitem__(self, i):

        for value in self[i]:
            self.redis.lrem(self.key, value)

    def __iter__(self):
        for v in self[:]:
            yield v

    def __len__(self):
        return self.redis.llen(self.key)

    def __contains__(self, value):
        i = self.index(value)
        return (i is not None)

    def insert(self, index, value, before=True):

        refvalue = self[index]
        where = 'BEFORE' if before else 'AFTER'

        return self.redis.linsert(self.key, where, refvalue, value)

    def index(self, value):
        """Returns first found index of given value."""

        for i, v in enumerate(self):
            try:
                if value.__dict__ == v.__dict__:
                    return i
            except AttributeError:
                if value == v:
                    return i

    def append(self, value, right=True):
        v = self.to_redis(value)

        if right:
            return self.redis.rpush(self.key, v)
        else:
            return self.redis.lpush(self.key, v)

    def extend(self, values):
        for value in values:
             v = self.to_redis(value)
             self.append(v)

    def rpush(self, value):
        """Redis RPUSH."""
        return self.append(value, right=True)

    def lpush(self, value):
        """Redis LPUSH."""
        return self.append(value, right=False)

    def lpop(self):
        """Redis LPOP."""
        return self.pop(right=False)

    def rpop(self):
        """Redis RPOP."""
        return self.pop(right=True)

    def pop(self, right=True):
        """Redis (R|L)POP."""

        if right:
            v = self.redis.lpop(self.key)
        else:
            v = self.redis.rpop(self.key)

        return self.to_python(v)

    def brpop(self, timeout=config.block_timeout):
        """Redis BRPOP."""
        return self.bpop(timeout, right=True)

    def blpop(self, timeout=config.block_timeout):
        """Redis BLPOP."""
        return self.bpop(timeout, right=False)

    def bpop(self, timeout=config.block_timeout, right=True):
        """Redis B(R|L)POP."""

        if right:
            v = self.redis.brpop(self.key, timeout)
        else:
            v = self.redis.blpop(self.key, timeout)

        try:
            return self.to_python(v[1])
        except TypeError:
            return None

    def find(self, *search):
        """FINDS ALL TEH THINGS."""

        for item in self._raw:
            for s in search:
                if callable(s):
                    if s(item):
                        yield item
                else:
                    if s in item:
                        yield self.to_python(item)

    def sorted_by(self, key, reverse=False ):

        return sorted(self, key=itemgetter(key), reverse=reverse)

class SubList(ListMixin):
    """Lists within Redis values."""

    def __init__(self, l, writer):
        self.data = l
        self.writer = writer
        self.i = None

    def write(self):
        """Writes List to Redis."""
        if self.i is not None:
            self.writer(self.data, self.i)
        else:
            self.writer(self.data)

    def _get_element(self, i):
        return self.data[i]

    def _set_element(self, i, value):
        self.data[i] = value
        self.write()

    def __len__(self):
        return len(self.data)

    def _resize_region(self, start, end, new_size):

        self.data[start:end] = [None] * new_size
        self.write()

    def _constructor(self, iter):
        return SubList(iter, self.writer)

    def __iter__(self):
        for item in self.data:
            yield item

class SubDict(DictMixin):
    """Dicts within Redis values."""

    def __init__(self, d, writer):
        self.data = d
        self.writer = writer
        self.i = None

    def write(self):
        """Writes Dict to Redis."""
        if self.i is not None:
            self.writer(self.data, self.i)
        else:
            self.writer(self.data)

    def __getitem__(self, item):
        return self.data.get(item)

    def __setitem__(self, k, v):
        self.data[k] = v
        self.write()

    def __delitem__(self, k):
        del self.data[k]
        self.write()

    def __repr__(self):
        return repr(self.data)

    def keys(self):
        return self.data.keys()

def auto_type(key, redis=None, default=None, o=True):
    """Returns datatype instance"""

    if redis is None:
        redis = config.redis

    key = compress_key(key)

    if redis.exists(key):

        datatype = redis.type(key)

        if datatype == 'string':
            test_string = RedisString(key, redis=redis).data

            if isinstance(test_string, dict):
                datatype = 'dict-string'
            elif isinstance(test_string, list):
                datatype = 'list-string'
            elif isinstance(test_string, basestring):
                datatype = 'string'
            elif isinstance(test_string, int):
                datatype = 'string'
            elif isinstance(test_string, float):
                datatype = 'string'

        return TYPE_MAP.get(datatype)(key, redis=redis, o=o)

    else:
        if default:
            try:
                return TYPE_MAP.get(default)(key, redis=redis, o=o)
            except KeyError:
                raise ValueError('Provide a valid default redis type.')

        return None

TYPE_MAP = {
    'string': RedisString,
    'value': RedisString,

    'liststring': RedisListString,
    'list-string': RedisListString,
    'stringlist': RedisListString,
    'string-list': RedisListString,

    'dictstring': RedisDictString,
    'dict-string': RedisDictString,
    'stringdict': RedisDictString,
    'string-dict': RedisDictString,

    'list': RedisList
}

<commit_msg>redi.s._('key')<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
redi.models
~~~~~~~~~~~

This module contains most of the functionality of redi.

"""

import uuid

from operator import itemgetter
from UserDict import DictMixin
from . import config

from .utils import ListMixin, is_collection, compress_key, expand_key

class RedisKey(object):
    """Contains methods that can be applied to any Redis key."""

    def __init__(self, key, redis=None, o=False):
        super(RedisKey, self).__init__()

        self.key = key
        self._o = o

        if redis is None:
            self.redis = config.redis

        self.redis = redis
        self.uuid = uuid.uuid4().hex

    def __repr__(self):
        return '<redis-key {0}>'.format(self.key)

    def _(self, key, default='string'):

        d = getattr(self, key, None)

        if d is None:
            key = compress_key(expand_key(self.key) + [key])
            return auto_type(key, redis=self.redis, default=default, o=True)

    def delete(self):
        """Removes this key from Redis."""
        return self.redis.delete(self.key)

    def __getattribute__(self, key):

        if key not in ('_o', 'children', 'key', 'redis'):
            if self._o:
                if key in self.children:

                    key = compress_key(expand_key(self.key) + [key])

                    return auto_type(key, redis=self.redis, o=True)

        return object.__getattribute__(self, key)

    def expire(self, s):
        """Expires this key from Redis in given seconds."""
        # TODO: Accept datetime for expire_at

        return self.redis.expire(self.key, s)

    def rename(self, new_name, safe=True):
        """Renames this key."""

        new_name = compress_key(new_name)

        if safe:
            if self.redis.renamenx(self.key, new_name):
                self.key = new_name
                return True
            return False
        else:
            self.redis.rename(self.key, new_name)
            self.key = new_name
            return True

    @property
    def children(self):
        """Lists all children of current key."""

        current_key = expand_key(self.key)

        namespace = compress_key(current_key + ['*'])

        keys = []

        for key in self.redis.keys(namespace):
            _key = expand_key(key)[len(current_key):]
            keys.append(compress_key(_key))

        return keys

    @property
    def siblings(self):
        """Lists all siblings of current key."""

        namespace = compress_key(expand_key(self.key)[:-1]+ ['*'])

        keys = self.redis.keys(namespace)

        # clean up results
        keys.remove(self.key)

        for key in self.children:
            try:
                keys.remove(key)
            except ValueError:
                pass

        return keys

    @staticmethod
    def to_redis(o):
        """Converts Python datatypes to Redis values."""

        # don't serialize internal datatype classesf
        if isinstance(o, SubList) or isinstance(o, SubDict):
            o = o.data

        return config.encoder(o)

    def to_python(self, o):
        """Converts Redis values to Python datatypes."""
        try:
            v = config.decoder(o)

            if isinstance(v, dict):
                return SubDict(v, self.save)

            elif is_collection(v):
                return SubList(v, self.save)

            try:
                if not isinstance(v, float):
                    return int(v)
            except ValueError:
                pass

            try:
                if not isinstance(v, int):
                    return float(v)
            except ValueError:
                pass

            return v

        except (ValueError, TypeError):
            try:
                return unicode(o, config.str_codec)
            except (UnicodeDecodeError, TypeError):
                return o

    def save(self, *args):
        pass

class RedisString(RedisKey):
    """Redis String interface."""

    def __init__(self, key, redis=None, o=False):
        super(RedisString, self).__init__(key, redis=redis, o=o)

        self.key = key

    def __repr__(self):
        return '<redis-string {0}>'.format(self.key)

    @property
    def _raw(self):
        """Returns raw Redis data."""
        return self.redis.get(self.key)

    def save(self, value):
        """Saves current value to Database."""
        v = self.to_redis(value)
        return self.redis.set(self.key, v)

    @property
    def data(self):
        """Writes value to database."""
        v = self.redis.get(self.key)
        return self.to_python(v)

    @data.setter
    def data(self, value):
        """Writes value to database."""
        self.save(value)

    @property
    def type(self):
        return self.data.__class__

    def write(self):
        return self.data.write()

    def __getitem__(self, item):
        return self.data.__getitem__(item)

    def __setitem__(self, k, v):
        return self.data.__setitem__(k, v)

    def __delitem__(self, k):
        return self.data.__delitem__(k)

class RedisListString(RedisString, ListMixin):
    """Redis value of awesomeness."""

    def __init__(self, key, redis, o=False):
        super(RedisListString, self).__init__(key, redis=redis, o=o)
        self.key = key

    def __repr__(self):
        return '<redis-list-string {0}>'.format(self.key)

    def __getitem__(self, item):
        return self.data.__getitem__(item)

    def __setitem__(self, k, v):
        return self.data.__setitem__(k, v)

    def __delitem__(self, k):
        return self.data.__delitem__(k)

    def _get_element(self, i):
        return self.data._get_element(i)

    def _set_element(self, i, value):
        return self.data._set_element(i, value)

    def __len__(self):
        return self.data.__len__()

    def _resize_region(self, start, end, new_size):
        return self.data._resize_region(start, end, new_size)

    def _constructor(self, iter):
        return self.data._constructor(iter)

class RedisDictString(RedisString, DictMixin):
    """Redis value of awesomeness."""

    def __init__(self, key, redis, o=False):
        super(RedisDictString, self).__init__(key, redis=redis, o=o)
        self.key = key

    def __repr__(self):
        return '<redis-dict-string {0}>'.format(self.key)

    def get(self, item):
        return self.data.get(item)

    def keys(self):
        return self.data.keys()

class RedisList(RedisKey):
    """Redis list of awesomeness."""

    def __init__(self, key, redis, o=False):
        super(RedisList, self).__init__(key, redis=redis, o=o)
        self.key = key

    def __repr__(self):
        return '<redis-list {0}>'.format(self.key)

    @property
    def _raw(self):
        for v in self.redis.lrange(self.key, 0, -1):
            yield v

    def save(self, value, i=None):
        """Save list."""

        self[i] = value

    def __getitem__(self, i):
        is_single = not isinstance(i, slice)

        if is_single:
            value = self.redis.lindex(self.key, i)
            values = self.to_python(value)
            try:
                values.i = i
            except AttributeError:
                pass

        else:
            start = 0 if i.start is None else i.start
            stop = -1 if i.stop is None else i.stop

            values = self.redis.lrange(self.key, start, stop)
            values = map(self.to_python, values)

            for i in range(start, start+len(values)):
                try:
                    values[i].i = i
                except AttributeError:
                    pass

        return values

    def __setitem__(self, i, value):
        v = self.to_redis(value)
        return self.redis.lset(self.key, i, v)

    def __delitem__(self, i):

        for value in self[i]:
            self.redis.lrem(self.key, value)

    def __iter__(self):
        for v in self[:]:
            yield v

    def __len__(self):
        return self.redis.llen(self.key)

    def __contains__(self, value):
        i = self.index(value)
        return (i is not None)

    def insert(self, index, value, before=True):

        refvalue = self[index]
        where = 'BEFORE' if before else 'AFTER'

        return self.redis.linsert(self.key, where, refvalue, value)

    def index(self, value):
        """Returns first found index of given value."""

        for i, v in enumerate(self):
            try:
                if value.__dict__ == v.__dict__:
                    return i
            except AttributeError:
                if value == v:
                    return i

    def append(self, value, right=True):
        v = self.to_redis(value)

        if right:
            return self.redis.rpush(self.key, v)
        else:
            return self.redis.lpush(self.key, v)

    def extend(self, values):
        for value in values:
             v = self.to_redis(value)
             self.append(v)

    def rpush(self, value):
        """Redis RPUSH."""
        return self.append(value, right=True)

    def lpush(self, value):
        """Redis LPUSH."""
        return self.append(value, right=False)

    def lpop(self):
        """Redis LPOP."""
        return self.pop(right=False)

    def rpop(self):
        """Redis RPOP."""
        return self.pop(right=True)

    def pop(self, right=True):
        """Redis (R|L)POP."""

        if right:
            v = self.redis.lpop(self.key)
        else:
            v = self.redis.rpop(self.key)

        return self.to_python(v)

    def brpop(self, timeout=config.block_timeout):
        """Redis BRPOP."""
        return self.bpop(timeout, right=True)

    def blpop(self, timeout=config.block_timeout):
        """Redis BLPOP."""
        return self.bpop(timeout, right=False)

    def bpop(self, timeout=config.block_timeout, right=True):
        """Redis B(R|L)POP."""

        if right:
            v = self.redis.brpop(self.key, timeout)
        else:
            v = self.redis.blpop(self.key, timeout)

        try:
            return self.to_python(v[1])
        except TypeError:
            return None

    def find(self, *search):
        """FINDS ALL TEH THINGS."""

        for item in self._raw:
            for s in search:
                if callable(s):
                    if s(item):
                        yield item
                else:
                    if s in item:
                        yield self.to_python(item)

    def sorted_by(self, key, reverse=False ):

        return sorted(self, key=itemgetter(key), reverse=reverse)

class SubList(ListMixin):
    """Lists within Redis values."""

    def __init__(self, l, writer):
        self.data = l
        self.writer = writer
        self.i = None

    def write(self):
        """Writes List to Redis."""
        if self.i is not None:
            self.writer(self.data, self.i)
        else:
            self.writer(self.data)

    def _get_element(self, i):
        return self.data[i]

    def _set_element(self, i, value):
        self.data[i] = value
        self.write()

    def __len__(self):
        return len(self.data)

    def _resize_region(self, start, end, new_size):

        self.data[start:end] = [None] * new_size
        self.write()

    def _constructor(self, iter):
        return SubList(iter, self.writer)

    def __iter__(self):
        for item in self.data:
            yield item

class SubDict(DictMixin):
    """Dicts within Redis values."""

    def __init__(self, d, writer):
        self.data = d
        self.writer = writer
        self.i = None

    def write(self):
        """Writes Dict to Redis."""
        if self.i is not None:
            self.writer(self.data, self.i)
        else:
            self.writer(self.data)

    def __getitem__(self, item):
        return self.data.get(item)

    def __setitem__(self, k, v):
        self.data[k] = v
        self.write()

    def __delitem__(self, k):
        del self.data[k]
        self.write()

    def __repr__(self):
        return repr(self.data)

    def keys(self):
        return self.data.keys()

def auto_type(key, redis=None, default=None, o=True):
    """Returns datatype instance"""

    if redis is None:
        redis = config.redis

    key = compress_key(key)

    if redis.exists(key):

        datatype = redis.type(key)

        if datatype == 'string':
            test_string = RedisString(key, redis=redis).data

            if isinstance(test_string, dict):
                datatype = 'dict-string'
            elif isinstance(test_string, list):
                datatype = 'list-string'
            elif isinstance(test_string, basestring):
                datatype = 'string'
            elif isinstance(test_string, int):
                datatype = 'string'
            elif isinstance(test_string, float):
                datatype = 'string'

        return TYPE_MAP.get(datatype)(key, redis=redis, o=o)

    else:
        if default:
            try:
                return TYPE_MAP.get(default)(key, redis=redis, o=o)
            except KeyError:
                raise ValueError('Provide a valid default redis type.')

        return None

TYPE_MAP = {
    'string': RedisString,
    'value': RedisString,

    'liststring': RedisListString,
    'list-string': RedisListString,
    'stringlist': RedisListString,
    'string-list': RedisListString,

    'dictstring': RedisDictString,
    'dict-string': RedisDictString,
    'stringdict': RedisDictString,
    'string-dict': RedisDictString,

    'list': RedisList
}

<|endoftext|>


<commit_before>#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

import httplib
import os
import socket
import sys
import urllib
import urlparse
import warnings

from cStringIO import StringIO

from TTransport import *

class THttpClient(TTransportBase):
  """Http implementation of TTransport base."""

  def __init__(self, uri_or_host, port=None, path=None):
    """THttpClient supports two different types constructor parameters.

    THttpClient(host, port, path) - deprecated
    THttpClient(uri)

    Only the second supports https.
    """
    if port is not None:
      warnings.warn(
        "Please use the THttpClient('http://host:port/path') syntax",
        DeprecationWarning,
        stacklevel=2)
      self.host = uri_or_host
      self.port = port
      assert path
      self.path = path
      self.scheme = 'http'
    else:
      parsed = urlparse.urlparse(uri_or_host)
      self.scheme = parsed.scheme
      assert self.scheme in ('http', 'https')
      if self.scheme == 'http':
        self.port = parsed.port or httplib.HTTP_PORT
      elif self.scheme == 'https':
        self.port = parsed.port or httplib.HTTPS_PORT
      self.host = parsed.hostname
      self.path = parsed.path
      if parsed.query:
        self.path += '?%s' % parsed.query
    self.__wbuf = StringIO()
    self.__http = None
    self.__timeout = None
    self.__custom_headers = None

  def open(self):
    if self.scheme == 'http':
      self.__http = httplib.HTTP(self.host, self.port)
    else:
      self.__http = httplib.HTTPS(self.host, self.port)

  def close(self):
    self.__http.close()
    self.__http = None

  def isOpen(self):
    return self.__http is not None

  def setTimeout(self, ms):
    if not hasattr(socket, 'getdefaulttimeout'):
      raise NotImplementedError

    if ms is None:
      self.__timeout = None
    else:
      self.__timeout = ms / 1000.0

  def setCustomHeaders(self, headers):
    self.__custom_headers = headers

  def read(self, sz):
    return self.__http.file.read(sz)

  def write(self, buf):
    self.__wbuf.write(buf)

  def __withTimeout(f):
    def _f(*args, **kwargs):
      orig_timeout = socket.getdefaulttimeout()
      socket.setdefaulttimeout(args[0].__timeout)
      result = f(*args, **kwargs)
      socket.setdefaulttimeout(orig_timeout)
      return result
    return _f

  def flush(self):
    if self.isOpen():
      self.close()
    self.open()

    # Pull data out of buffer
    data = self.__wbuf.getvalue()
    self.__wbuf = StringIO()

    # HTTP request
    self.__http.putrequest('POST', self.path)

    # Write headers
    self.__http.putheader('Host', self.host)
    self.__http.putheader('Content-Type', 'application/x-thrift')
    self.__http.putheader('Content-Length', str(len(data)))

    if not self.__custom_headers or 'User-Agent' not in self.__custom_headers:
      user_agent = 'Python/THttpClient'
      script = os.path.basename(sys.argv[0])
      if script:
        user_agent = '%s (%s)' % (user_agent, urllib.quote(script))
      self.__http.putheader('User-Agent', user_agent)

    if self.__custom_headers:
        for key, val in self.__custom_headers.iteritems():
            self.__http.putheader(key, val)

    self.__http.endheaders()

    # Write payload
    self.__http.send(data)

    # Get reply to flush the request
    self.code, self.message, self.headers = self.__http.getreply()

  # Decorate if we know how to timeout
  if hasattr(socket, 'getdefaulttimeout'):
    flush = __withTimeout(flush)
<commit_msg>THRIFT-2900 Python THttpClient does not reset socket timeout on exception Client: Python Patch: Aiden Scandella <aiden@uber.com><commit_after>#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

import httplib
import os
import socket
import sys
import urllib
import urlparse
import warnings

from cStringIO import StringIO

from TTransport import *

class THttpClient(TTransportBase):
  """Http implementation of TTransport base."""

  def __init__(self, uri_or_host, port=None, path=None):
    """THttpClient supports two different types constructor parameters.

    THttpClient(host, port, path) - deprecated
    THttpClient(uri)

    Only the second supports https.
    """
    if port is not None:
      warnings.warn(
        "Please use the THttpClient('http://host:port/path') syntax",
        DeprecationWarning,
        stacklevel=2)
      self.host = uri_or_host
      self.port = port
      assert path
      self.path = path
      self.scheme = 'http'
    else:
      parsed = urlparse.urlparse(uri_or_host)
      self.scheme = parsed.scheme
      assert self.scheme in ('http', 'https')
      if self.scheme == 'http':
        self.port = parsed.port or httplib.HTTP_PORT
      elif self.scheme == 'https':
        self.port = parsed.port or httplib.HTTPS_PORT
      self.host = parsed.hostname
      self.path = parsed.path
      if parsed.query:
        self.path += '?%s' % parsed.query
    self.__wbuf = StringIO()
    self.__http = None
    self.__timeout = None
    self.__custom_headers = None

  def open(self):
    if self.scheme == 'http':
      self.__http = httplib.HTTP(self.host, self.port)
    else:
      self.__http = httplib.HTTPS(self.host, self.port)

  def close(self):
    self.__http.close()
    self.__http = None

  def isOpen(self):
    return self.__http is not None

  def setTimeout(self, ms):
    if not hasattr(socket, 'getdefaulttimeout'):
      raise NotImplementedError

    if ms is None:
      self.__timeout = None
    else:
      self.__timeout = ms / 1000.0

  def setCustomHeaders(self, headers):
    self.__custom_headers = headers

  def read(self, sz):
    return self.__http.file.read(sz)

  def write(self, buf):
    self.__wbuf.write(buf)

  def __withTimeout(f):
    def _f(*args, **kwargs):
      orig_timeout = socket.getdefaulttimeout()
      socket.setdefaulttimeout(args[0].__timeout)
      try:
        result = f(*args, **kwargs)
      finally:
        socket.setdefaulttimeout(orig_timeout)
      return result
    return _f

  def flush(self):
    if self.isOpen():
      self.close()
    self.open()

    # Pull data out of buffer
    data = self.__wbuf.getvalue()
    self.__wbuf = StringIO()

    # HTTP request
    self.__http.putrequest('POST', self.path)

    # Write headers
    self.__http.putheader('Host', self.host)
    self.__http.putheader('Content-Type', 'application/x-thrift')
    self.__http.putheader('Content-Length', str(len(data)))

    if not self.__custom_headers or 'User-Agent' not in self.__custom_headers:
      user_agent = 'Python/THttpClient'
      script = os.path.basename(sys.argv[0])
      if script:
        user_agent = '%s (%s)' % (user_agent, urllib.quote(script))
      self.__http.putheader('User-Agent', user_agent)

    if self.__custom_headers:
        for key, val in self.__custom_headers.iteritems():
            self.__http.putheader(key, val)

    self.__http.endheaders()

    # Write payload
    self.__http.send(data)

    # Get reply to flush the request
    self.code, self.message, self.headers = self.__http.getreply()

  # Decorate if we know how to timeout
  if hasattr(socket, 'getdefaulttimeout'):
    flush = __withTimeout(flush)
<|endoftext|>


<commit_before>__version__ = '0.6.11'
<commit_msg>Version 0.6.12<commit_after>__version__ = '0.6.12'
<|endoftext|>


<commit_before>from . import database
from . import configmanager
import sqlalchemy
import sqlalchemy.orm

def getMainConnection():
	return database.ConnectionManager.getConnection("main")

#Groups posts and tags in posts dict.
#Will be a dict formatted as such:
#{postId: {post: $POST_OBJECT_FROM_DATABASE, tags: [$TAGS_FROM_DATABASE]}
def _getDictFromJoin(results):
	posts = {}
	for result in results:
		post, tag = result
		if post.id in posts.keys():
			posts[post.id]["tags"].append(tag)
		else:
			posts[post.id] = {"post": post, "tags": []}
			if tag != None:
				posts[post.id]["tags"].append(tag)

	return sorted(
			list(posts.values()),
			key = lambda x: x["post"].time_posted,
			reverse = True)

def _getPostQuery(limit = None, offset = 0, tags = True, connection = None):
	if connection == None:
		connection = getMainConnection()
	if tags:
		#Gets all the posts using a join.
		#We won't use getPostById in a loop to prevent many queries.

		#Subquery to get all posts within our limit
		postQuery = (connection.session
			.query(database.tables.Post)
			.order_by(sqlalchemy.desc(database.tables.Post.time_posted))
			.limit(limit)
			.offset(offset)
			.subquery())

		postAlias = sqlalchemy.orm.aliased(database.tables.Post, postQuery)

		#Outerjoin these together
		query = (connection.session
			.query(postAlias, database.tables.Tag)
			.outerjoin(database.tables.Tag)
			.order_by(database.tables.Tag.id))

		return query
	else:
		query = (connection.session
			.query(database.tables.Post)
			.limit(limit)
			.offset(offset))

		return query

def getPosts(limit = None, offset = 0, tags = True, connection = None):
	query = _getPostQuery(limit, offset, tags, connection)
	posts = query.all()

	if tags:
		return _getDictFromJoin(posts)
	else:
		return sorted(posts, key = lambda x: x.time_posted, reverse = True)

def getPostCount(limit = None, offset = 0, connection = None):
	query = _getPostQuery(limit, offset, False, connection)
	return query.count()

#Gets a post form the database
#Returns None if there is no post with such an id
def getPostById(postId, tags = True, connection = None):
	if connection == None:
		connection = getMainConnection()
	if tags:
		postsAndTags = (connection.session
			.query(database.tables.Post, database.tables.Tag)
			.outerjoin(database.tables.Tag)
			.filter(database.tables.Post.id == postId).order_by(database.tables.Tag.id)
			.all())

		if len(postsAndTags) == 0:
			return None

		return {
				"post": postsAndTags[0][0],
				"tags": [item[1] for item in postsAndTags if item[1] != None]
			}
	else:
		return (connection.session.query(database.tables.Post)
			.filter(database.tables.Post.id == postId)
			.first())

def _getPostWithTagQuery(tag, limit = None, offset = 0, tags = True, connection = None):
	if connection == None:
		connection = getMainConnection()

	if tags:
		postQuery = (connection.session
			.query(sqlalchemy.distinct(database.tables.Tag.post_id))
			.select_from(database.tables.Post)
			.join(database.tables.Tag, database.tables.Tag.post_id == database.tables.Post.id)
			.filter(database.tables.Tag.name == tag.lower())
			.limit(limit)
			.offset(offset)
			.subquery())

		query = (connection.session
			.query(database.tables.Post, database.tables.Tag)
			.join(database.tables.Tag)
			.filter(database.tables.Post.id.in_(postQuery))
		)
		return query
	else:
		query = (connection.session
			.query(database.tables.Post)
			.join(database.tables.Tag)
			.filter(sqlalchemy.func.lower(database.tables.Tag.name) == tag.lower())
			.limit(limit)
			.offset(offset))

		return query

def getPostsWithTag(tag, limit = None, offset = 0, tags = True, connection = None):
	query = _getPostWithTagQuery(tag, limit, offset, tags, connection)
	posts = query.all()

	if tags:
		return _getDictFromJoin(posts)
	else:
		return sorted(posts, key = lambda x: x.time_posted, reverse = True)

def getPostWithTagCount(limit = None, offset = 0, connection = None):
	query = _getPostWithTagQuery(limit, offset, False, connection)
	return query.count()

def addPost(title, body, time_posted, author, tags, connection = None):
	#Functions are not re-run if they are default arguments.
	if connection == None:
		connection = getMainConnection()

	if type(tags) == str:
		tags = tags.split(" ")
	#Create the post object
	post = database.tables.Post(
		title = title,
		body = body,
		time_posted = time_posted,
		author = author)

	connection.session.add(post)
	connection.session.flush()
	#Parse the tags and add them to the table
	for tag in tags:
		if len(tag) > 0:
			tag = database.tables.Tag(post_id = post.id, name = tag)
			connection.session.add(tag)
	connection.session.commit()

def editPost(postId, title, body, tags, connection = None):
	if connection == None:
		connection = getMainConnection()

	if type(tags) == str:
		tags = tags.split(" ")

	post = getPostById(postId)["post"]
	post.title = title
	post.body = body

	currentTags = (connection.session
		.query(database.tables.Tag)
		.filter(database.tables.Tag.post_id == postId))

	for tag in currentTags:
		if tag.name not in currentTags:
			connection.session.delete(tag)

	connection.session.flush()
	currentTagNames = (connection.session
		.query(database.tables.Tag.name)
		.filter(database.tables.Tag.post_id == postId))

	for tag in tags:
		if len(tag) > 0 and tag not in currentTagNames:
			tag = database.tables.Tag(post_id = post.id, name = tag)
			connection.session.add(tag)

	connection.session.commit()

def deletePost(post, connection = None):
	if connection == None:
		connection = getMainConnection()

	if type(post) == int:
		post = getPostById(post, tags = False)

	if type(post) != database.tables.Post:
		raise ValueError("post must be of type int or Post, not %s" % type(post))

	connection.session.delete(post)
	connection.session.commit()
<commit_msg>Fix arguments in getPostCountWithTag<commit_after>from . import database
from . import configmanager
import sqlalchemy
import sqlalchemy.orm

def getMainConnection():
	return database.ConnectionManager.getConnection("main")

#Groups posts and tags in posts dict.
#Will be a dict formatted as such:
#{postId: {post: $POST_OBJECT_FROM_DATABASE, tags: [$TAGS_FROM_DATABASE]}
def _getDictFromJoin(results):
	posts = {}
	for result in results:
		post, tag = result
		if post.id in posts.keys():
			posts[post.id]["tags"].append(tag)
		else:
			posts[post.id] = {"post": post, "tags": []}
			if tag != None:
				posts[post.id]["tags"].append(tag)

	return sorted(
			list(posts.values()),
			key = lambda x: x["post"].time_posted,
			reverse = True)

def _getPostQuery(limit = None, offset = 0, tags = True, connection = None):
	if connection == None:
		connection = getMainConnection()
	if tags:
		#Gets all the posts using a join.
		#We won't use getPostById in a loop to prevent many queries.

		#Subquery to get all posts within our limit
		postQuery = (connection.session
			.query(database.tables.Post)
			.order_by(sqlalchemy.desc(database.tables.Post.time_posted))
			.limit(limit)
			.offset(offset)
			.subquery())

		postAlias = sqlalchemy.orm.aliased(database.tables.Post, postQuery)

		#Outerjoin these together
		query = (connection.session
			.query(postAlias, database.tables.Tag)
			.outerjoin(database.tables.Tag)
			.order_by(database.tables.Tag.id))

		return query
	else:
		query = (connection.session
			.query(database.tables.Post)
			.limit(limit)
			.offset(offset))

		return query

def getPosts(limit = None, offset = 0, tags = True, connection = None):
	query = _getPostQuery(limit, offset, tags, connection)
	posts = query.all()

	if tags:
		return _getDictFromJoin(posts)
	else:
		return sorted(posts, key = lambda x: x.time_posted, reverse = True)

def getPostCount(limit = None, offset = 0, connection = None):
	query = _getPostQuery(limit, offset, False, connection)
	return query.count()

#Gets a post form the database
#Returns None if there is no post with such an id
def getPostById(postId, tags = True, connection = None):
	if connection == None:
		connection = getMainConnection()
	if tags:
		postsAndTags = (connection.session
			.query(database.tables.Post, database.tables.Tag)
			.outerjoin(database.tables.Tag)
			.filter(database.tables.Post.id == postId).order_by(database.tables.Tag.id)
			.all())

		if len(postsAndTags) == 0:
			return None

		return {
				"post": postsAndTags[0][0],
				"tags": [item[1] for item in postsAndTags if item[1] != None]
			}
	else:
		return (connection.session.query(database.tables.Post)
			.filter(database.tables.Post.id == postId)
			.first())

def _getPostWithTagQuery(tag, limit = None, offset = 0, tags = True, connection = None):
	if connection == None:
		connection = getMainConnection()

	if tags:
		postQuery = (connection.session
			.query(sqlalchemy.distinct(database.tables.Tag.post_id))
			.select_from(database.tables.Post)
			.join(database.tables.Tag, database.tables.Tag.post_id == database.tables.Post.id)
			.filter(database.tables.Tag.name == tag.lower())
			.limit(limit)
			.offset(offset)
			.subquery())

		query = (connection.session
			.query(database.tables.Post, database.tables.Tag)
			.join(database.tables.Tag)
			.filter(database.tables.Post.id.in_(postQuery))
		)
		return query
	else:
		query = (connection.session
			.query(database.tables.Post)
			.join(database.tables.Tag)
			.filter(sqlalchemy.func.lower(database.tables.Tag.name) == tag.lower())
			.limit(limit)
			.offset(offset))

		return query

def getPostsWithTag(tag, limit = None, offset = 0, tags = True, connection = None):
	query = _getPostWithTagQuery(tag, limit, offset, tags, connection)
	posts = query.all()

	if tags:
		return _getDictFromJoin(posts)
	else:
		return sorted(posts, key = lambda x: x.time_posted, reverse = True)

def getPostWithTagCount(tag, limit = None, offset = 0, connection = None):
	query = _getPostWithTagQuery(tag, limit, offset, False, connection)
	return query.count()

def addPost(title, body, time_posted, author, tags, connection = None):
	#Functions are not re-run if they are default arguments.
	if connection == None:
		connection = getMainConnection()

	if type(tags) == str:
		tags = tags.split(" ")
	#Create the post object
	post = database.tables.Post(
		title = title,
		body = body,
		time_posted = time_posted,
		author = author)

	connection.session.add(post)
	connection.session.flush()
	#Parse the tags and add them to the table
	for tag in tags:
		if len(tag) > 0:
			tag = database.tables.Tag(post_id = post.id, name = tag)
			connection.session.add(tag)
	connection.session.commit()

def editPost(postId, title, body, tags, connection = None):
	if connection == None:
		connection = getMainConnection()

	if type(tags) == str:
		tags = tags.split(" ")

	post = getPostById(postId)["post"]
	post.title = title
	post.body = body

	currentTags = (connection.session
		.query(database.tables.Tag)
		.filter(database.tables.Tag.post_id == postId))

	for tag in currentTags:
		if tag.name not in currentTags:
			connection.session.delete(tag)

	connection.session.flush()
	currentTagNames = (connection.session
		.query(database.tables.Tag.name)
		.filter(database.tables.Tag.post_id == postId))

	for tag in tags:
		if len(tag) > 0 and tag not in currentTagNames:
			tag = database.tables.Tag(post_id = post.id, name = tag)
			connection.session.add(tag)

	connection.session.commit()

def deletePost(post, connection = None):
	if connection == None:
		connection = getMainConnection()

	if type(post) == int:
		post = getPostById(post, tags = False)

	if type(post) != database.tables.Post:
		raise ValueError("post must be of type int or Post, not %s" % type(post))

	connection.session.delete(post)
	connection.session.commit()
<|endoftext|>


<commit_before>from models import *
from fields import XHTMLField, ReadonlyXHTMLWidget
from django import forms
from django.contrib import admin, messages
from django.contrib.auth.admin import UserAdmin
from django.contrib.contenttypes import generic
from django.core.exceptions import ObjectDoesNotExist
from django.db import IntegrityError
from django.db.models.fields import FieldDoesNotExist
from django.http import HttpResponseRedirect
from reversion import admin as reversion_admin
from urlparse import urlparse, parse_qsl, urlunparse
from urllib import urlencode

class FootnoteAdminForm(forms.ModelForm):
    stamp = forms.CharField(required=False, widget=forms.HiddenInput)
    class Meta:
        model = Footnote

class CitationInline(generic.GenericStackedInline):
    model = Citation
    extra = 0
    template = 'admin/main/edit_inline/stacked.html'

class TopicAssignmentInline(generic.GenericStackedInline):
    model = TopicAssignment
    extra = 1

class AliasInline(admin.StackedInline):
    model = Alias
    extra = 0

class FootnoteInline(admin.StackedInline):
    model = Footnote
    extra = 0
    template = 'admin/main/footnote/edit_inline/stacked.html'
    form = FootnoteAdminForm
    formfield_overrides = { XHTMLField: { 'widget': ReadonlyXHTMLWidget } }

class DocumentLinkInline(admin.StackedInline):
    model = DocumentLink
    extra = 0

class ScanInline(admin.StackedInline):
    model = Scan

class UserProfileInline(admin.StackedInline):
    model = UserProfile

################################################################################

class VersionAdmin(reversion_admin.VersionAdmin):
    list_display = ('as_text', 'last_updater', 'last_updated')
    def save_model(self, request, obj, form, change):
        if not change: # adding new object
            obj.creator = request.user
        obj.last_updater = request.user
        obj.save()
    def save_formset(self, request, form, formset, change):
        instances = formset.save(commit=False)
        for instance in instances:
            try:
                instance.creator
            except ObjectDoesNotExist:
                instance.creator = request.user
            if 'last_updated' in instance._meta.get_all_field_names():
                instance.last_updater = request.user
            instance.save()
        formset.save_m2m()
    def response_add(self, request, obj, post_url_continue='../%s/'):
        response = super(VersionAdmin, self).response_add(request, obj, post_url_continue)
        if (request.POST.has_key('_continue') or
            request.POST.has_key('_popup') or
            request.POST.has_key('_addanother')):
            return response
        else:
            return HttpResponseRedirect(obj.get_absolute_url())
    def response_change(self, request, obj):
        response = super(VersionAdmin, self).response_change(request, obj)
        if request.POST.has_key('_return_to') and not (
            request.POST.has_key('_continue') or
            request.POST.has_key('_saveasnew') or
            request.POST.has_key('_addanother')):
            return HttpResponseRedirect(request.POST['_return_to'])
        elif (request.POST.has_key('_return_to') and
              request.POST.has_key('_continue')):
            parts = list(urlparse(response['Location']))
            query = parse_qsl(parts[4])
            query.append(('return_to', request.POST['_return_to']))
            parts[4] = urlencode(query)
            response['Location'] = urlunparse(parts)
            return response
        else:
            return response
    def message_user(self, request, message):
        if 'success' in message.lower():
            messages.success(request, message)
        else:
            messages.info(request, message)

class TopicAdmin(VersionAdmin):
    inlines = (AliasInline, CitationInline)
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class NoteAdmin(VersionAdmin):
    inlines = (CitationInline, TopicAssignmentInline)
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class DocumentAdmin(VersionAdmin):
    inlines = (TopicAssignmentInline, DocumentLinkInline, ScanInline)
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class TranscriptAdmin(VersionAdmin):
    inlines = (FootnoteInline,)
    def save_formset(self, request, form, formset, change):
        transcript = form.instance
        # Update the transcript HTML to remove any links to deleted footnotes.
        for footnote_form in formset.forms:
            if formset._should_delete_form(footnote_form):
                footnote_form.instance.remove_self_from(transcript)
        # Save the transcript formset.
        super(TranscriptAdmin, self).save_formset(request, form, formset, change)
        # Update the transcript HTML with correct links to any new footnotes.
        for footnote_form in formset.forms:
            if (hasattr(footnote_form, 'cleaned_data') and
                'stamp' in footnote_form.cleaned_data):
                stamp = footnote_form.cleaned_data['stamp']
                if stamp:
                    a = transcript.content.cssselect('a.footnote[href="' + stamp + '"]')[0]
                    a.attrib['href'] = footnote_form.instance.get_absolute_url()
        # Save the transcript HTML.
        transcript.save()
    class Media:
        css = { 'all': ('style/custom-theme/jquery-ui-1.8.5.custom.css',
                        'style/admin-transcript.css') }
        js = ('function/jquery-1.4.2.min.js',
              'function/jquery-ui-1.8.5.custom.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/jquery.ellipsis.js',
              'function/admin-transcript.js')

class FootnoteAdmin(VersionAdmin):
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class UserProfileAdmin(UserAdmin):
    inlines = (UserProfileInline,)

admin.site.unregister(User)

admin.site.register(Topic, TopicAdmin)
admin.site.register(Note, NoteAdmin)
admin.site.register(Document, DocumentAdmin)
admin.site.register(Transcript, TranscriptAdmin)
admin.site.register(Footnote, FootnoteAdmin)
admin.site.register(Project)
admin.site.register(User, UserProfileAdmin)
<commit_msg>Show user affiliations in admin.<commit_after>from models import *
from fields import XHTMLField, ReadonlyXHTMLWidget
from django import forms
from django.contrib import admin, messages
from django.contrib.auth.admin import UserAdmin
from django.contrib.contenttypes import generic
from django.core.exceptions import ObjectDoesNotExist
from django.db import IntegrityError
from django.db.models.fields import FieldDoesNotExist
from django.http import HttpResponseRedirect
from reversion import admin as reversion_admin
from urlparse import urlparse, parse_qsl, urlunparse
from urllib import urlencode

class FootnoteAdminForm(forms.ModelForm):
    stamp = forms.CharField(required=False, widget=forms.HiddenInput)
    class Meta:
        model = Footnote

class CitationInline(generic.GenericStackedInline):
    model = Citation
    extra = 0
    template = 'admin/main/edit_inline/stacked.html'

class TopicAssignmentInline(generic.GenericStackedInline):
    model = TopicAssignment
    extra = 1

class AliasInline(admin.StackedInline):
    model = Alias
    extra = 0

class FootnoteInline(admin.StackedInline):
    model = Footnote
    extra = 0
    template = 'admin/main/footnote/edit_inline/stacked.html'
    form = FootnoteAdminForm
    formfield_overrides = { XHTMLField: { 'widget': ReadonlyXHTMLWidget } }

class DocumentLinkInline(admin.StackedInline):
    model = DocumentLink
    extra = 0

class ScanInline(admin.StackedInline):
    model = Scan

class UserProfileInline(admin.StackedInline):
    model = UserProfile

################################################################################

class VersionAdmin(reversion_admin.VersionAdmin):
    list_display = ('as_text', 'last_updater', 'last_updated')
    def save_model(self, request, obj, form, change):
        if not change: # adding new object
            obj.creator = request.user
        obj.last_updater = request.user
        obj.save()
    def save_formset(self, request, form, formset, change):
        instances = formset.save(commit=False)
        for instance in instances:
            try:
                instance.creator
            except ObjectDoesNotExist:
                instance.creator = request.user
            if 'last_updated' in instance._meta.get_all_field_names():
                instance.last_updater = request.user
            instance.save()
        formset.save_m2m()
    def response_add(self, request, obj, post_url_continue='../%s/'):
        response = super(VersionAdmin, self).response_add(request, obj, post_url_continue)
        if (request.POST.has_key('_continue') or
            request.POST.has_key('_popup') or
            request.POST.has_key('_addanother')):
            return response
        else:
            return HttpResponseRedirect(obj.get_absolute_url())
    def response_change(self, request, obj):
        response = super(VersionAdmin, self).response_change(request, obj)
        if request.POST.has_key('_return_to') and not (
            request.POST.has_key('_continue') or
            request.POST.has_key('_saveasnew') or
            request.POST.has_key('_addanother')):
            return HttpResponseRedirect(request.POST['_return_to'])
        elif (request.POST.has_key('_return_to') and
              request.POST.has_key('_continue')):
            parts = list(urlparse(response['Location']))
            query = parse_qsl(parts[4])
            query.append(('return_to', request.POST['_return_to']))
            parts[4] = urlencode(query)
            response['Location'] = urlunparse(parts)
            return response
        else:
            return response
    def message_user(self, request, message):
        if 'success' in message.lower():
            messages.success(request, message)
        else:
            messages.info(request, message)

class TopicAdmin(VersionAdmin):
    inlines = (AliasInline, CitationInline)
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class NoteAdmin(VersionAdmin):
    inlines = (CitationInline, TopicAssignmentInline)
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class DocumentAdmin(VersionAdmin):
    inlines = (TopicAssignmentInline, DocumentLinkInline, ScanInline)
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class TranscriptAdmin(VersionAdmin):
    inlines = (FootnoteInline,)
    def save_formset(self, request, form, formset, change):
        transcript = form.instance
        # Update the transcript HTML to remove any links to deleted footnotes.
        for footnote_form in formset.forms:
            if formset._should_delete_form(footnote_form):
                footnote_form.instance.remove_self_from(transcript)
        # Save the transcript formset.
        super(TranscriptAdmin, self).save_formset(request, form, formset, change)
        # Update the transcript HTML with correct links to any new footnotes.
        for footnote_form in formset.forms:
            if (hasattr(footnote_form, 'cleaned_data') and
                'stamp' in footnote_form.cleaned_data):
                stamp = footnote_form.cleaned_data['stamp']
                if stamp:
                    a = transcript.content.cssselect('a.footnote[href="' + stamp + '"]')[0]
                    a.attrib['href'] = footnote_form.instance.get_absolute_url()
        # Save the transcript HTML.
        transcript.save()
    class Media:
        css = { 'all': ('style/custom-theme/jquery-ui-1.8.5.custom.css',
                        'style/admin-transcript.css') }
        js = ('function/jquery-1.4.2.min.js',
              'function/jquery-ui-1.8.5.custom.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/jquery.ellipsis.js',
              'function/admin-transcript.js')

class FootnoteAdmin(VersionAdmin):
    class Media:
        js = ('function/jquery-1.4.2.min.js',
              'function/wymeditor/jquery.wymeditor.pack.js',
              'function/jquery.timeago.js',
              'function/admin.js')

class UserProfileAdmin(UserAdmin):
    inlines = (UserProfileInline,)
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'affiliation')
    def affiliation(self, user):
        return user.get_profile().affiliation

admin.site.unregister(User)

admin.site.register(Topic, TopicAdmin)
admin.site.register(Note, NoteAdmin)
admin.site.register(Document, DocumentAdmin)
admin.site.register(Transcript, TranscriptAdmin)
admin.site.register(Footnote, FootnoteAdmin)
admin.site.register(Project)
admin.site.register(User, UserProfileAdmin)
<|endoftext|>


<commit_before># Copyright 2014 Novo Nordisk Foundation Center for Biosustainability, DTU.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
WebModels API
-------------

A high level API for retrieving models from the
http://darwin.di.uminho.pt/models and http://bigg.ucsd.edu databases
"""

from __future__ import absolute_import, print_function

import io
import tempfile
import logging

import requests

import lazy_object_proxy
import optlang

from functools import partial

from pandas import DataFrame

from cobra.io import load_json_model, read_sbml_model

from cameo.util import str_to_valid_variable_name
from cameo.core.solver_based_model import to_solver_based_model

__all__ = ['index_models_minho', 'index_models_bigg', 'bigg', 'minho']

logger = logging.getLogger(__name__)

class NotFoundException(Exception):
    def __init__(self, type, index, *args, **kwargs):
        message = "Could not retrieve %s for entry with index %i" % (type, index)
        Exception.__init__(self, message, *args, **kwargs)

def load_webmodel(query, solver_interface):
    logger.debug('Querying webmodels ... trying http://bigg.ucsd.edu first')
    try:
        model = get_model_from_bigg(query, solver_interface=solver_interface)
    except Exception:
        logger.debug('Querying webmodels ... trying minho next')
        try:
            df = index_models_minho()
        except requests.ConnectionError as e:
            logger.error("You need to be connected to the internet to load an online model.")
            raise e
        except Exception as e:
            logger.error("Something went wrong while looking up available webmodels.")
            raise e
        try:
            index = df.query('name == "%s"' % query).id.values[0]
            model = get_model_from_uminho(index)
            # handle = get_sbml_file(index)
            # path = handle.name
        except IndexError:
            raise ValueError("%s is neither a file nor a model ID." % query)
    return model

def index_models_minho(host="http://darwin.di.uminho.pt/models"):
    """
    Retrieves a summary of all models in the database.

    Parameters
    ----------
    host: the service host (optional, default: http://darwin.di.uminho.pt/models)

    Returns
    -------
    pandas.DataFrame
        summary of the models in the database
    """
    uri = host + "/models.json"
    try:
        response = requests.get(uri, timeout=3)
    except requests.ConnectionError as e:
        logger.error("Cannot reach %s. Are you sure that you are connected to the internet?" % host)
        raise e
    if response.ok:
        try:
            json = response.json()
        except Exception as e:
            logger.error('No json could be decoded from server response coming from {}.'.format(host))
            raise e
        else:
            index = DataFrame(json, columns=["id", "name", "doi", "author",
                                             "year", "formats", "organism",
                                             "taxonomy", "optflux_validated"])
            index.columns = ["id", "name", "doi", "author", "year", "formats", "organism", "taxonomy", "validated"]
            return index
    else:
        raise Exception("Could not index available models. %s returned status code %d" % (host, response.status_code))

def get_model_from_uminho(index, host="http://darwin.di.uminho.pt/models"):
    sbml_file = get_sbml_file(index, host)
    sbml_file.close()
    return to_solver_based_model(read_sbml_model(sbml_file.name))

def get_sbml_file(index, host="http://darwin.di.uminho.pt/models"):
    temp = tempfile.NamedTemporaryFile(delete=False)
    uri = host + "/models/%i.sbml" % index
    try:
        response = requests.get(uri)
    except requests.ConnectionError as e:
        logger.error("Cannot reach {}. Are you sure that you are connected to the internet?".format(host))
        raise e
    if response.ok:

        temp.write(response.text.encode('utf-8'))
        temp.flush()
        return temp
    else:
        raise NotFoundException("sbml", index)

def index_models_bigg():
    try:
        response = requests.get('http://bigg.ucsd.edu/api/v2/models', timeout=3)
    except requests.ConnectionError as e:
        logger.error("Cannot reach http://bigg.ucsd.edu. Are you sure that you are connected to the internet?")
        raise e
    if response.ok:
        try:
            json = response.json()
        except Exception as e:
            logger.error('No json could be decoded from server response coming from http://bigg.ucsd.edu.')
            raise e
        else:
            return DataFrame.from_dict(json['results'])
    else:
        raise Exception(
            "Could not index available models. bigg.ucsd.edu returned status code {}".format(response.status_code))

def get_model_from_bigg(id, solver_interface=optlang):
    try:
        response = requests.get('http://bigg.ucsd.edu/api/v2/models/{}/download'.format(id))
    except requests.ConnectionError as e:
        logger.error("Cannot reach http://bigg.ucsd.edu. Are you sure that you are connected to the internet?")
        raise e
    if response.ok:
        with io.StringIO(response.text) as f:
            return to_solver_based_model(load_json_model(f), solver_interface=solver_interface)
    else:
        raise Exception(
            "Could not download model {}. bigg.ucsd.edu returned status code {}".format(id, response.status_code))

class ModelDB(object):
    def __init__(self, index_method, get_model_method):
        self._index_method = index_method
        self._get_model_method = get_model_method
        self._index = None

    def _index_models(self):
        try:
            index = self._index_method()
        except requests.ConnectionError():
            self._index = ["no_models_available"]
            self.no_models_available = "The server could not be reached. Make sure you are connected to the internet"
        self._index = list(index)

    def __dir__(self):
        if self._index is None:
            self._index_models()
        return list(self._index)

    def __getattr__(self, item):
        if self._index is None:
            self._index_models()
        if item in self._index:
            return self._get_model_method(item)
        else:
            super(ModelDB, self).__getattribute__(item)

bigg = ModelDB(lambda: index_models_bigg().bigg_id, get_model_from_bigg)

minho = ModelDB(lambda: index_models_minho().name, get_model_from_uminho)

def validated_minho_names():
    minho = index_models_minho()
    minho_validated = minho[minho.validated]
    return minho_validated.name

minho.validated = ModelDB(validated_minho_names, get_model_from_uminho)

# bigg = ModelDB()
# try:
#     model_ids = index_models_bigg().bigg_id
# except requests.ConnectionError:
#     bigg.no_models_available = "Cameo couldn't reach http://bigg.ucsd.edu at initialization time." \
#                                "Are you connected to the internet?"
# except Exception as e:
#     bigg.no_models_available = "Cameo could reach http://bigg.ucsd.edu at initialization time" \
#                                "but something went wrong while decoding the server response."
#     logger.debug(e)
# else:
#     for id in model_ids:
#         setattr(bigg, str_to_valid_variable_name(id), lazy_object_proxy.Proxy(partial(get_model_from_bigg, id)))
#
# minho = ModelDB()
# try:
#     minho_models = index_models_minho()
# except requests.ConnectionError as e:
#     minho.no_models_available = "Cameo couldn't reach http://darwin.di.uminho.pt/models at initialization time." \
#                                 "Are you connected to the internet?"
#     logger.debug(e)
# except Exception as e:
#     minho.no_models_available = "Cameo could reach http://darwin.di.uminho.pt/models at initialization time" \
#                                 "but something went wrong while decoding the server response."
#     logger.debug(e)
# else:
#     model_indices = minho_models.id
#     model_ids = minho_models.name
#     for index, id in zip(model_indices, model_ids):
#         setattr(minho, str_to_valid_variable_name(id), lazy_object_proxy.Proxy(partial(get_model_from_uminho, index)))
#
#     validated_models = minho_models[minho_models.validated]
#     minho.validated = ModelDB()
#     model_indices = validated_models.id
#     model_ids = validated_models.name
#     for index, id in zip(model_indices, model_ids):
#         setattr(minho.validated, str_to_valid_variable_name(id),
#                 lazy_object_proxy.Proxy(partial(get_model_from_uminho, index)))

if __name__ == "__main__":
    print(index_models_minho())
    from cameo import load_model

    model = load_model(get_sbml_file(2))
    print(model.objective)
<commit_msg>fix: small error catching bug<commit_after># Copyright 2014 Novo Nordisk Foundation Center for Biosustainability, DTU.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
WebModels API
-------------

A high level API for retrieving models from the
http://darwin.di.uminho.pt/models and http://bigg.ucsd.edu databases
"""

from __future__ import absolute_import, print_function

import io
import tempfile
import logging

import requests

import lazy_object_proxy
import optlang

from functools import partial

from pandas import DataFrame

from cobra.io import load_json_model, read_sbml_model

from cameo.util import str_to_valid_variable_name
from cameo.core.solver_based_model import to_solver_based_model

__all__ = ['index_models_minho', 'index_models_bigg', 'bigg', 'minho']

logger = logging.getLogger(__name__)

class NotFoundException(Exception):
    def __init__(self, type, index, *args, **kwargs):
        message = "Could not retrieve %s for entry with index %i" % (type, index)
        Exception.__init__(self, message, *args, **kwargs)

def load_webmodel(query, solver_interface):
    logger.debug('Querying webmodels ... trying http://bigg.ucsd.edu first')
    try:
        model = get_model_from_bigg(query, solver_interface=solver_interface)
    except Exception:
        logger.debug('Querying webmodels ... trying minho next')
        try:
            df = index_models_minho()
        except requests.ConnectionError as e:
            logger.error("You need to be connected to the internet to load an online model.")
            raise e
        except Exception as e:
            logger.error("Something went wrong while looking up available webmodels.")
            raise e
        try:
            index = df.query('name == "%s"' % query).id.values[0]
            model = get_model_from_uminho(index)
            # handle = get_sbml_file(index)
            # path = handle.name
        except IndexError:
            raise ValueError("%s is neither a file nor a model ID." % query)
    return model

def index_models_minho(host="http://darwin.di.uminho.pt/models"):
    """
    Retrieves a summary of all models in the database.

    Parameters
    ----------
    host: the service host (optional, default: http://darwin.di.uminho.pt/models)

    Returns
    -------
    pandas.DataFrame
        summary of the models in the database
    """
    uri = host + "/models.json"
    try:
        response = requests.get(uri, timeout=3)
    except requests.ConnectionError as e:
        logger.error("Cannot reach %s. Are you sure that you are connected to the internet?" % host)
        raise e
    if response.ok:
        try:
            json = response.json()
        except Exception as e:
            logger.error('No json could be decoded from server response coming from {}.'.format(host))
            raise e
        else:
            index = DataFrame(json, columns=["id", "name", "doi", "author",
                                             "year", "formats", "organism",
                                             "taxonomy", "optflux_validated"])
            index.columns = ["id", "name", "doi", "author", "year", "formats", "organism", "taxonomy", "validated"]
            return index
    else:
        raise Exception("Could not index available models. %s returned status code %d" % (host, response.status_code))

def get_model_from_uminho(index, host="http://darwin.di.uminho.pt/models"):
    sbml_file = get_sbml_file(index, host)
    sbml_file.close()
    return to_solver_based_model(read_sbml_model(sbml_file.name))

def get_sbml_file(index, host="http://darwin.di.uminho.pt/models"):
    temp = tempfile.NamedTemporaryFile(delete=False)
    uri = host + "/models/%i.sbml" % index
    try:
        response = requests.get(uri)
    except requests.ConnectionError as e:
        logger.error("Cannot reach {}. Are you sure that you are connected to the internet?".format(host))
        raise e
    if response.ok:

        temp.write(response.text.encode('utf-8'))
        temp.flush()
        return temp
    else:
        raise NotFoundException("sbml", index)

def index_models_bigg():
    try:
        response = requests.get('http://bigg.ucsd.edu/api/v2/models', timeout=3)
    except requests.ConnectionError as e:
        logger.error("Cannot reach http://bigg.ucsd.edu. Are you sure that you are connected to the internet?")
        raise e
    if response.ok:
        try:
            json = response.json()
        except Exception as e:
            logger.error('No json could be decoded from server response coming from http://bigg.ucsd.edu.')
            raise e
        else:
            return DataFrame.from_dict(json['results'])
    else:
        raise Exception(
            "Could not index available models. bigg.ucsd.edu returned status code {}".format(response.status_code))

def get_model_from_bigg(id, solver_interface=optlang):
    try:
        response = requests.get('http://bigg.ucsd.edu/api/v2/models/{}/download'.format(id))
    except requests.ConnectionError as e:
        logger.error("Cannot reach http://bigg.ucsd.edu. Are you sure that you are connected to the internet?")
        raise e
    if response.ok:
        with io.StringIO(response.text) as f:
            return to_solver_based_model(load_json_model(f), solver_interface=solver_interface)
    else:
        raise Exception(
            "Could not download model {}. bigg.ucsd.edu returned status code {}".format(id, response.status_code))

class ModelDB(object):
    def __init__(self, index_method, get_model_method):
        self._index_method = index_method
        self._get_model_method = get_model_method
        self._index = None

    def _index_models(self):
        try:
            index = self._index_method()
        except requests.ConnectionError:
            self._index = ["no_models_available"]
            self.no_models_available = "The server could not be reached. Make sure you are connected to the internet"
        else:
            self._index = list(index)

    def __dir__(self):
        if self._index is None:
            self._index_models()
        return list(self._index)

    def __getattr__(self, item):
        if self._index is None:
            self._index_models()
        if item in self._index:
            return self._get_model_method(item)
        else:
            super(ModelDB, self).__getattribute__(item)

bigg = ModelDB(lambda: index_models_bigg().bigg_id, get_model_from_bigg)

minho = ModelDB(lambda: index_models_minho().name, get_model_from_uminho)

def validated_minho_names():
    minho = index_models_minho()
    minho_validated = minho[minho.validated]
    return minho_validated.name

minho.validated = ModelDB(validated_minho_names, get_model_from_uminho)

# bigg = ModelDB()
# try:
#     model_ids = index_models_bigg().bigg_id
# except requests.ConnectionError:
#     bigg.no_models_available = "Cameo couldn't reach http://bigg.ucsd.edu at initialization time." \
#                                "Are you connected to the internet?"
# except Exception as e:
#     bigg.no_models_available = "Cameo could reach http://bigg.ucsd.edu at initialization time" \
#                                "but something went wrong while decoding the server response."
#     logger.debug(e)
# else:
#     for id in model_ids:
#         setattr(bigg, str_to_valid_variable_name(id), lazy_object_proxy.Proxy(partial(get_model_from_bigg, id)))
#
# minho = ModelDB()
# try:
#     minho_models = index_models_minho()
# except requests.ConnectionError as e:
#     minho.no_models_available = "Cameo couldn't reach http://darwin.di.uminho.pt/models at initialization time." \
#                                 "Are you connected to the internet?"
#     logger.debug(e)
# except Exception as e:
#     minho.no_models_available = "Cameo could reach http://darwin.di.uminho.pt/models at initialization time" \
#                                 "but something went wrong while decoding the server response."
#     logger.debug(e)
# else:
#     model_indices = minho_models.id
#     model_ids = minho_models.name
#     for index, id in zip(model_indices, model_ids):
#         setattr(minho, str_to_valid_variable_name(id), lazy_object_proxy.Proxy(partial(get_model_from_uminho, index)))
#
#     validated_models = minho_models[minho_models.validated]
#     minho.validated = ModelDB()
#     model_indices = validated_models.id
#     model_ids = validated_models.name
#     for index, id in zip(model_indices, model_ids):
#         setattr(minho.validated, str_to_valid_variable_name(id),
#                 lazy_object_proxy.Proxy(partial(get_model_from_uminho, index)))

if __name__ == "__main__":
    print(index_models_minho())
    from cameo import load_model

    model = load_model(get_sbml_file(2))
    print(model.objective)
<|endoftext|>


<commit_before>#-# Modified by D.C.-G. for translation purpose
from albow import Label
from albow.translate import _
from config import config
from glbackground import GLBackground
import pygame

class NudgeButton(GLBackground):
    """ A button that captures movement keys while pressed and sends them to a listener as nudge events.
    Poorly planned. """

    is_gl_container = True

    def __init__(self, editor):
        GLBackground.__init__(self)
        nudgeLabel = Label("Nudge", margin=8)

        self.editor = editor
        self.add(nudgeLabel)
        self.shrink_wrap()
        self.root = self.get_root()

        # tooltipBacking = Panel()
        # tooltipBacking.bg_color = (0, 0, 0, 0.6)
        keys = [_(config.keys[config.convert(k)].get()) for k in ("forward", "back", "left", "right", "up", "down")]

        nudgeLabel.tooltipText = _("Click and hold.  While holding, use the movement keys ({0}/{1}/{2}/{3}/{4}/{5}) to nudge. Left mouse to nudge a block, Right mouse to nudge a greater distance.").format(
            *keys)
        # tooltipBacking.shrink_wrap()

    def mouse_down(self, event):
        self.root.notMove = True
        self.root.nudge = self
        self.focus()
        if event.button == 3 and config.keys.fastNudge.get() == "None":
            self.editor.rightClickNudge = True

    def mouse_up(self, event):
        self.root.notMove = False
        self.root.nudge = None
        if event.button == 3 and config.keys.fastNudge.get() == "None":
            self.editor.rightClickNudge = False
            self.editor.turn_off_focus()
        if event.button == 1:
            self.editor.turn_off_focus()

    def key_down(self, evt):
        if not pygame.key.get_focused():
            return

        keyname = evt.dict.get('keyname', None) or self.root.getKey(evt)

        if keyname == config.keys.fastNudge.get():
            self.editor.rightClickNudge = True

    def key_up(self, evt):
        keyname = evt.dict.get('keyname', None) or self.root.getKey(evt)

        if keyname == config.keys.fastNudge.get():
            self.editor.rightClickNudge = False
<commit_msg>Changed tooltip text a bit for nudge buttons<commit_after>#-# Modified by D.C.-G. for translation purpose
from albow import Label
from albow.translate import _
from config import config
from glbackground import GLBackground
import pygame

class NudgeButton(GLBackground):
    """ A button that captures movement keys while pressed and sends them to a listener as nudge events.
    Poorly planned. """

    is_gl_container = True

    def __init__(self, editor):
        GLBackground.__init__(self)
        nudgeLabel = Label("Nudge", margin=8)

        self.editor = editor
        self.add(nudgeLabel)
        self.shrink_wrap()
        self.root = self.get_root()

        # tooltipBacking = Panel()
        # tooltipBacking.bg_color = (0, 0, 0, 0.6)
        keys = [_(config.keys[config.convert(k)].get()) for k in ("forward", "back", "left", "right", "up", "down", "fast nudge")]
        if keys[6] == "None":
            keys[6] = "Right mouse"

        nudgeLabel.tooltipText = _("Click and hold.  While holding, use the movement keys ({0}/{1}/{2}/{3}/{4}/{5}) to nudge. Left mouse to nudge a block.\n{6} to nudge a greater distance.").format(
            *keys)
        # tooltipBacking.shrink_wrap()

    def mouse_down(self, event):
        self.root.notMove = True
        self.root.nudge = self
        self.focus()
        if event.button == 3 and config.keys.fastNudge.get() == "None":
            self.editor.rightClickNudge = True

    def mouse_up(self, event):
        self.root.notMove = False
        self.root.nudge = None
        if event.button == 3 and config.keys.fastNudge.get() == "None":
            self.editor.rightClickNudge = False
            self.editor.turn_off_focus()
        if event.button == 1:
            self.editor.turn_off_focus()

    def key_down(self, evt):
        if not pygame.key.get_focused():
            return

        keyname = evt.dict.get('keyname', None) or self.root.getKey(evt)

        if keyname == config.keys.fastNudge.get():
            self.editor.rightClickNudge = True

    def key_up(self, evt):
        keyname = evt.dict.get('keyname', None) or self.root.getKey(evt)

        if keyname == config.keys.fastNudge.get():
            self.editor.rightClickNudge = False
<|endoftext|>