<commit_before>from selenium.common.exceptions import StaleElementReferenceException, NoSuchElementException, InvalidSelectorException, WebDriverException

from .locator import locator_to_by_value
from .identifier import Identifier
from .waiter import Waiter
from . import exceptions

class Context:
    def __init__(self):
        self.__wait_interval = None
        self.__wait_timeout = None

    def get_web_driver(self):
        pass

    def get_web_driver_type(self):
        pass

    def _selenium_context(self):
        pass

    def _refresh(self):
        pass

    def persist(self):
        pass

    def get_screenshot_as_file(self, filename):
        pass

    def get_screenshot_as_png(self):
        pass

    def get_screenshot_as_base64(self):
        pass

    def get_wait_interval(self):
        """
            Get the wait interval of this context.
            If the wait interval for element is not set, return the driver's wait interval.

        :return: the wait interval
        """
        if self.__wait_interval is not None:
            return self.__wait_interval
        return self.get_web_driver().get_wait_interval()

    def set_wait_interval(self, interval):
        """
            Set the wait interval of this context.

        :param interval: the new wait interval (in milliseconds)
        """
        self.__wait_interval = interval

    def get_wait_timeout(self):
        """
            Get the wait timeout of this context.
            If the wait timeout for element is not set, return the driver's wait timeout.

        :return: the wait timeout
        """
        if self.__wait_timeout is not None:
            return self.__wait_timeout
        return self.get_web_driver().get_wait_timeout()

    def set_wait_timeout(self, timeout):
        """
            Set the wait timeout of this context.

        :param timeout: the new wait timeout (in milliseconds)
        """
        self.__wait_timeout = timeout

    def wait_for(self, interval=None, timeout=None):
        pass

    def waiter(self, interval=None, timeout=None):
        """
            Get a Waiter instance.

        :param interval: the wait interval (in milliseconds). If None, use context's wait interval.
        :param timeout: the wait timeout (in milliseconds). If None, use context's wait interval.
        """
        _interval = self.get_wait_interval() if interval is None else interval
        _timeout = self.get_wait_timeout() if timeout is None else timeout
        return Waiter(_interval, _timeout)

    def _find_selenium_element(self, locator):
        by, value = locator_to_by_value(locator)
        try:
            try:
                return self._selenium_context().find_element(by, value)
            except StaleElementReferenceException:
                self._refresh()
                return self._selenium_context().find_element(by, value)
        except InvalidSelectorException:
            raise exceptions.InvalidLocatorException("The value <%s> of locator <%s> is not a valid expression." % (value, locator), self)
        except NoSuchElementException:
            raise exceptions.NoSuchElementException("Cannot find element by <%s> under:" % locator, self)
        except WebDriverException as wde:
            raise exceptions.EasyiumException(wde.msg, self)

    def has_child(self, locator):
        """
            Return whether this context has a child element.

        :param locator: the locator (relative to this context) of the child element
        :return: whether this context has a child element.
        """
        try:
            self.find_element(locator)
            return True
        except exceptions.NoSuchElementException:
            return False

    def find_element(self, locator, identifier=Identifier.id):
        """
            Find a DynamicElement under this context immediately.

        :param locator:
            the locator (relative to this context) of the element to be found.
            The format of locator is: "by=value", the possible values of "by" are::

                "id": By.ID
                "xpath": By.XPATH
                "link": By.LINK_TEXT
                "partial_link": By.PARTIAL_LINK_TEXT
                "name": By.NAME
                "tag": By.TAG_NAME
                "class": By.CLASS_NAME
                "css": By.CSS_SELECTOR
                "ios_uiautomation": MobileBy.IOS_UIAUTOMATION
                "android_uiautomation": MobileBy.ANDROID_UIAUTOMATOR
                "accessibility_id": MobileBy.ACCESSIBILITY_ID
        :param identifier:
            the identifier is a function to generate the locator of the found element, you can get the standard ones in class Identifier.
            Otherwise, you can create one like this::

                context.find_element("class=food", lambda e: "xpath=.//*[@attr='%s']" % e.get_attribute("attr"))
        :return: the DynamicElement found by locator
        """
        # import the DynamicElement here to avoid cyclic dependency
        from .dynamicelement import DynamicElement

        by, value = locator_to_by_value(locator)
        try:
            try:
                return DynamicElement(self, self._selenium_context().find_element(by, value), locator, identifier)
            except (exceptions.NoSuchElementException, StaleElementReferenceException):
                # Only Element can reach here
                self.wait_for().exists()
                return DynamicElement(self, self._selenium_context().find_element(by, value), locator, identifier)
        except InvalidSelectorException:
            raise exceptions.InvalidLocatorException("The value <%s> of locator <%s> is not a valid expression." % (value, locator), self)
        except NoSuchElementException:
            raise exceptions.NoSuchElementException("Cannot find element by <%s> under:" % locator, self)
        except WebDriverException as wde:
            raise exceptions.EasyiumException(wde.msg, self)

    def find_elements(self, locator, identifier=Identifier.id, at_least=0):
        """
            Find DynamicElement list under this context immediately.

        :param locator:
            the locator (relative to this context) of the elements to be found.
            The format of locator is: "by=value", the possible values of "by" are::

                "id": By.ID
                "xpath": By.XPATH
                "link": By.LINK_TEXT
                "partial_link": By.PARTIAL_LINK_TEXT
                "name": By.NAME
                "tag": By.TAG_NAME
                "class": By.CLASS_NAME
                "css": By.CSS_SELECTOR
                "ios_uiautomation": MobileBy.IOS_UIAUTOMATION
                "android_uiautomation": MobileBy.ANDROID_UIAUTOMATOR
                "accessibility_id": MobileBy.ACCESSIBILITY_ID
        :param identifier:
            the identifier is a function to generate the locator of the found elements, you can get the standard ones in class Identifier.
            Otherwise, you can create one like this::

                context.find_elements("class=food", lambda e: "xpath=.//*[@attr='%s']" % e.get_attribute("attr"))
        :param at_least: end finding elements when the number of found elements is at least the given number.
        :return: the DynamicElement list found by locator
        """
        # import the DynamicElement here to avoid cyclic dependency
        from .dynamicelement import DynamicElement

        by, value = locator_to_by_value(locator)
        selenium_elements = {"inner": []}

        def find_selenium_elements():
            try:
                try:
                    selenium_elements["inner"] = self._selenium_context().find_elements(by, value)
                    return selenium_elements["inner"]
                except (exceptions.NoSuchElementException, StaleElementReferenceException):
                    # Only Element can reach here
                    self.wait_for().exists()
                    selenium_elements["inner"] = self._selenium_context().find_elements(by, value)
                    return selenium_elements["inner"]
            except InvalidSelectorException:
                raise exceptions.InvalidLocatorException("The value <%s> of locator <%s> is not a valid expression." % (value, locator), self)
            except WebDriverException as wde:
                raise exceptions.EasyiumException(wde.msg, self)

        try:
            self.waiter().wait_for(lambda : len(find_selenium_elements()) >= at_least)
        except exceptions.TimeoutException as e:
            if e.__class__ == exceptions.ElementTimeoutException:
                # raised by self.wait_for().exists() in find_selenium_elements()
                raise
            raise exceptions.TimeoutException("Timed out waiting for the number of found elements by <%s> under:\n%s\nto be at least <%s>." % (locator, self, at_least))

        return [DynamicElement(self, selenium_element, locator, identifier) for selenium_element in selenium_elements["inner"]]
<commit_msg>Add docstring of locator for has_child.<commit_after>from selenium.common.exceptions import StaleElementReferenceException, NoSuchElementException, InvalidSelectorException, WebDriverException

from .locator import locator_to_by_value
from .identifier import Identifier
from .waiter import Waiter
from . import exceptions

class Context:
    def __init__(self):
        self.__wait_interval = None
        self.__wait_timeout = None

    def get_web_driver(self):
        pass

    def get_web_driver_type(self):
        pass

    def _selenium_context(self):
        pass

    def _refresh(self):
        pass

    def persist(self):
        pass

    def get_screenshot_as_file(self, filename):
        pass

    def get_screenshot_as_png(self):
        pass

    def get_screenshot_as_base64(self):
        pass

    def get_wait_interval(self):
        """
            Get the wait interval of this context.
            If the wait interval for element is not set, return the driver's wait interval.

        :return: the wait interval
        """
        if self.__wait_interval is not None:
            return self.__wait_interval
        return self.get_web_driver().get_wait_interval()

    def set_wait_interval(self, interval):
        """
            Set the wait interval of this context.

        :param interval: the new wait interval (in milliseconds)
        """
        self.__wait_interval = interval

    def get_wait_timeout(self):
        """
            Get the wait timeout of this context.
            If the wait timeout for element is not set, return the driver's wait timeout.

        :return: the wait timeout
        """
        if self.__wait_timeout is not None:
            return self.__wait_timeout
        return self.get_web_driver().get_wait_timeout()

    def set_wait_timeout(self, timeout):
        """
            Set the wait timeout of this context.

        :param timeout: the new wait timeout (in milliseconds)
        """
        self.__wait_timeout = timeout

    def wait_for(self, interval=None, timeout=None):
        pass

    def waiter(self, interval=None, timeout=None):
        """
            Get a Waiter instance.

        :param interval: the wait interval (in milliseconds). If None, use context's wait interval.
        :param timeout: the wait timeout (in milliseconds). If None, use context's wait interval.
        """
        _interval = self.get_wait_interval() if interval is None else interval
        _timeout = self.get_wait_timeout() if timeout is None else timeout
        return Waiter(_interval, _timeout)

    def _find_selenium_element(self, locator):
        by, value = locator_to_by_value(locator)
        try:
            try:
                return self._selenium_context().find_element(by, value)
            except StaleElementReferenceException:
                self._refresh()
                return self._selenium_context().find_element(by, value)
        except InvalidSelectorException:
            raise exceptions.InvalidLocatorException("The value <%s> of locator <%s> is not a valid expression." % (value, locator), self)
        except NoSuchElementException:
            raise exceptions.NoSuchElementException("Cannot find element by <%s> under:" % locator, self)
        except WebDriverException as wde:
            raise exceptions.EasyiumException(wde.msg, self)

    def has_child(self, locator):
        """
            Return whether this context has a child element.

        :param locator:
            the locator (relative to this context) of the child element.
            The format of locator is: "by=value", the possible values of "by" are::

                "id": By.ID
                "xpath": By.XPATH
                "link": By.LINK_TEXT
                "partial_link": By.PARTIAL_LINK_TEXT
                "name": By.NAME
                "tag": By.TAG_NAME
                "class": By.CLASS_NAME
                "css": By.CSS_SELECTOR
                "ios_uiautomation": MobileBy.IOS_UIAUTOMATION
                "android_uiautomation": MobileBy.ANDROID_UIAUTOMATOR
                "accessibility_id": MobileBy.ACCESSIBILITY_ID
        :return: whether this context has a child element.
        """
        try:
            self.find_element(locator)
            return True
        except exceptions.NoSuchElementException:
            return False

    def find_element(self, locator, identifier=Identifier.id):
        """
            Find a DynamicElement under this context immediately.

        :param locator:
            the locator (relative to this context) of the element to be found.
            The format of locator is: "by=value", the possible values of "by" are::

                "id": By.ID
                "xpath": By.XPATH
                "link": By.LINK_TEXT
                "partial_link": By.PARTIAL_LINK_TEXT
                "name": By.NAME
                "tag": By.TAG_NAME
                "class": By.CLASS_NAME
                "css": By.CSS_SELECTOR
                "ios_uiautomation": MobileBy.IOS_UIAUTOMATION
                "android_uiautomation": MobileBy.ANDROID_UIAUTOMATOR
                "accessibility_id": MobileBy.ACCESSIBILITY_ID
        :param identifier:
            the identifier is a function to generate the locator of the found element, you can get the standard ones in class Identifier.
            Otherwise, you can create one like this::

                context.find_element("class=food", lambda e: "xpath=.//*[@attr='%s']" % e.get_attribute("attr"))
        :return: the DynamicElement found by locator
        """
        # import the DynamicElement here to avoid cyclic dependency
        from .dynamicelement import DynamicElement

        by, value = locator_to_by_value(locator)
        try:
            try:
                return DynamicElement(self, self._selenium_context().find_element(by, value), locator, identifier)
            except (exceptions.NoSuchElementException, StaleElementReferenceException):
                # Only Element can reach here
                self.wait_for().exists()
                return DynamicElement(self, self._selenium_context().find_element(by, value), locator, identifier)
        except InvalidSelectorException:
            raise exceptions.InvalidLocatorException("The value <%s> of locator <%s> is not a valid expression." % (value, locator), self)
        except NoSuchElementException:
            raise exceptions.NoSuchElementException("Cannot find element by <%s> under:" % locator, self)
        except WebDriverException as wde:
            raise exceptions.EasyiumException(wde.msg, self)

    def find_elements(self, locator, identifier=Identifier.id, at_least=0):
        """
            Find DynamicElement list under this context immediately.

        :param locator:
            the locator (relative to this context) of the elements to be found.
            The format of locator is: "by=value", the possible values of "by" are::

                "id": By.ID
                "xpath": By.XPATH
                "link": By.LINK_TEXT
                "partial_link": By.PARTIAL_LINK_TEXT
                "name": By.NAME
                "tag": By.TAG_NAME
                "class": By.CLASS_NAME
                "css": By.CSS_SELECTOR
                "ios_uiautomation": MobileBy.IOS_UIAUTOMATION
                "android_uiautomation": MobileBy.ANDROID_UIAUTOMATOR
                "accessibility_id": MobileBy.ACCESSIBILITY_ID
        :param identifier:
            the identifier is a function to generate the locator of the found elements, you can get the standard ones in class Identifier.
            Otherwise, you can create one like this::

                context.find_elements("class=food", lambda e: "xpath=.//*[@attr='%s']" % e.get_attribute("attr"))
        :param at_least: end finding elements when the number of found elements is at least the given number.
        :return: the DynamicElement list found by locator
        """
        # import the DynamicElement here to avoid cyclic dependency
        from .dynamicelement import DynamicElement

        by, value = locator_to_by_value(locator)
        selenium_elements = {"inner": []}

        def find_selenium_elements():
            try:
                try:
                    selenium_elements["inner"] = self._selenium_context().find_elements(by, value)
                    return selenium_elements["inner"]
                except (exceptions.NoSuchElementException, StaleElementReferenceException):
                    # Only Element can reach here
                    self.wait_for().exists()
                    selenium_elements["inner"] = self._selenium_context().find_elements(by, value)
                    return selenium_elements["inner"]
            except InvalidSelectorException:
                raise exceptions.InvalidLocatorException("The value <%s> of locator <%s> is not a valid expression." % (value, locator), self)
            except WebDriverException as wde:
                raise exceptions.EasyiumException(wde.msg, self)

        try:
            self.waiter().wait_for(lambda : len(find_selenium_elements()) >= at_least)
        except exceptions.TimeoutException as e:
            if e.__class__ == exceptions.ElementTimeoutException:
                # raised by self.wait_for().exists() in find_selenium_elements()
                raise
            raise exceptions.TimeoutException("Timed out waiting for the number of found elements by <%s> under:\n%s\nto be at least <%s>." % (locator, self, at_least))

        return [DynamicElement(self, selenium_element, locator, identifier) for selenium_element in selenium_elements["inner"]]
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''MUDA core tests'''
import tempfile
import os
import six

import numpy as np

import jams
import librosa

import muda

import pytest

def test_jam_pack():

    jam = jams.JAMS()

    sr = 22050
    y = np.zeros(sr)

    muda.jam_pack(jam, y=y, sr=sr)

    # Make sure the jam now has a mudabox
    assert hasattr(jam.sandbox, 'muda')
    assert hasattr(jam.sandbox.muda, 'history')
    assert hasattr(jam.sandbox.muda, 'state')

    assert jam.sandbox.muda['y'] is y
    assert jam.sandbox.muda['sr'] == sr

@pytest.fixture()
def audio_file():
    return 'tests/data/fixture.wav'

@pytest.fixture()
def jam_in():
    return 'tests/data/fixture.jams'

@pytest.fixture(params=[0, 1, 2, 3],
                ids=['JAMS()',
                     'fixture.jams',
                     "JAMS('fixture.jams')",
                     'fdesc'])
def jam_loader(request):
    if request.param == 0:
        yield jams.JAMS()

    elif request.param == 1:
        yield 'tests/data/fixture.jams'

    elif request.param == 2:
        yield jams.load('tests/data/fixture.jams')

    else:
        with open('tests/data/fixture.jams', 'r') as fdesc:
            yield fdesc

@pytest.mark.parametrize('validate', [False, True])
@pytest.mark.parametrize('strict', [False, True])
@pytest.mark.parametrize('fmt', ['auto', 'jams',
                                 pytest.mark.xfail('jamz', raises=OSError)])
def test_load_jam_audio(jam_loader, audio_file, validate, strict, fmt):

    jam = muda.load_jam_audio(jam_loader, audio_file,
                              validate=validate, strict=strict, fmt=fmt)

    assert hasattr(jam.sandbox, 'muda')

    duration = librosa.get_duration(**jam.sandbox.muda._audio)
    assert jam.file_metadata.duration == duration

@pytest.mark.parametrize('strict', [False, True])
@pytest.mark.parametrize('fmt', ['auto', 'jams', 'jamz'])
def test_save(jam_in, audio_file, strict, fmt):

    jam = muda.load_jam_audio(jam_in, audio_file)

    _, jamfile = tempfile.mkstemp(suffix='.jams')
    _, audfile = tempfile.mkstemp(suffix='.wav')

    muda.save(audfile, jamfile, jam, strict=strict, fmt=fmt)

    jam2 = muda.load_jam_audio(jamfile, audfile, fmt=fmt)
    jam2_raw = jams.load(jamfile, fmt=fmt)

    os.unlink(audfile)
    os.unlink(jamfile)

    assert hasattr(jam2.sandbox, 'muda')
    assert '_audio' in jam2.sandbox.muda
    assert '_audio' not in jam2_raw.sandbox.muda

    duration = librosa.get_duration(**jam2.sandbox.muda['_audio'])

    assert jam2.file_metadata.duration == duration

def test_serialize_pipeline():

    D1 = muda.deformers.LogspaceTimeStretch()
    D2 = muda.deformers.LogspaceTimeStretch()
    P_orig = muda.Pipeline([('stretch_1', D1),
                            ('stretch_2', D2)])
    P_ser = muda.serialize(P_orig)

    P_new = muda.deserialize(P_ser)

    assert P_orig is not P_new
    assert P_orig.get_params() == P_new.get_params()

def test_serialize_union():

    D1 = muda.deformers.LogspaceTimeStretch()
    D2 = muda.deformers.LogspaceTimeStretch()
    U_orig = muda.Union([('stretch_1', D1),
                         ('stretch_2', D2)])
    U_ser = muda.serialize(U_orig)

    U_new = muda.deserialize(U_ser)

    assert U_orig is not U_new
    assert U_orig.get_params() == U_new.get_params()

def test_reload_jampack(jam_in, audio_file):

    # This test is to address #42, where mudaboxes reload as dict
    # instead of Sandbox
    jam = muda.load_jam_audio(jam_in, audio_file)

    jam2 = muda.load_jam_audio(six.StringIO(jam.dumps()), audio_file)
    assert isinstance(jam.sandbox.muda, jams.Sandbox)
    assert isinstance(jam2.sandbox.muda, jams.Sandbox)
<commit_msg>fixed tests for py2<commit_after>#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''MUDA core tests'''
import tempfile
import os
import six

import numpy as np

import jams
import librosa

import muda

import pytest

def test_jam_pack():

    jam = jams.JAMS()

    sr = 22050
    y = np.zeros(sr)

    muda.jam_pack(jam, y=y, sr=sr)

    # Make sure the jam now has a mudabox
    assert hasattr(jam.sandbox, 'muda')
    assert hasattr(jam.sandbox.muda, 'history')
    assert hasattr(jam.sandbox.muda, 'state')

    assert jam.sandbox.muda['y'] is y
    assert jam.sandbox.muda['sr'] == sr

@pytest.fixture()
def audio_file():
    return 'tests/data/fixture.wav'

@pytest.fixture()
def jam_in():
    return 'tests/data/fixture.jams'

@pytest.fixture(params=[0, 1, 2, 3],
                ids=['JAMS()',
                     'fixture.jams',
                     "JAMS('fixture.jams')",
                     'fdesc'])
def jam_loader(request):
    if request.param == 0:
        yield jams.JAMS()

    elif request.param == 1:
        yield 'tests/data/fixture.jams'

    elif request.param == 2:
        yield jams.load('tests/data/fixture.jams')

    else:
        with open('tests/data/fixture.jams', 'r') as fdesc:
            yield fdesc

@pytest.mark.parametrize('validate', [False, True])
@pytest.mark.parametrize('strict', [False, True])
# gzip will throw an IOError on py2, and OSError on py3.
@pytest.mark.parametrize('fmt', ['auto', 'jams',
                                 pytest.mark.xfail('jamz',
                                                   raises=(OSError, IOError))])
def test_load_jam_audio(jam_loader, audio_file, validate, strict, fmt):

    jam = muda.load_jam_audio(jam_loader, audio_file,
                              validate=validate, strict=strict, fmt=fmt)

    assert hasattr(jam.sandbox, 'muda')

    duration = librosa.get_duration(**jam.sandbox.muda._audio)
    assert jam.file_metadata.duration == duration

@pytest.mark.parametrize('strict', [False, True])
@pytest.mark.parametrize('fmt', ['auto', 'jams', 'jamz'])
def test_save(jam_in, audio_file, strict, fmt):

    jam = muda.load_jam_audio(jam_in, audio_file)

    _, jamfile = tempfile.mkstemp(suffix='.jams')
    _, audfile = tempfile.mkstemp(suffix='.wav')

    muda.save(audfile, jamfile, jam, strict=strict, fmt=fmt)

    jam2 = muda.load_jam_audio(jamfile, audfile, fmt=fmt)
    jam2_raw = jams.load(jamfile, fmt=fmt)

    os.unlink(audfile)
    os.unlink(jamfile)

    assert hasattr(jam2.sandbox, 'muda')
    assert '_audio' in jam2.sandbox.muda
    assert '_audio' not in jam2_raw.sandbox.muda

    duration = librosa.get_duration(**jam2.sandbox.muda['_audio'])

    assert jam2.file_metadata.duration == duration

def test_serialize_pipeline():

    D1 = muda.deformers.LogspaceTimeStretch()
    D2 = muda.deformers.LogspaceTimeStretch()
    P_orig = muda.Pipeline([('stretch_1', D1),
                            ('stretch_2', D2)])
    P_ser = muda.serialize(P_orig)

    P_new = muda.deserialize(P_ser)

    assert P_orig is not P_new
    assert P_orig.get_params() == P_new.get_params()

def test_serialize_union():

    D1 = muda.deformers.LogspaceTimeStretch()
    D2 = muda.deformers.LogspaceTimeStretch()
    U_orig = muda.Union([('stretch_1', D1),
                         ('stretch_2', D2)])
    U_ser = muda.serialize(U_orig)

    U_new = muda.deserialize(U_ser)

    assert U_orig is not U_new
    assert U_orig.get_params() == U_new.get_params()

def test_reload_jampack(jam_in, audio_file):

    # This test is to address #42, where mudaboxes reload as dict
    # instead of Sandbox
    jam = muda.load_jam_audio(jam_in, audio_file)

    jam2 = muda.load_jam_audio(six.StringIO(jam.dumps()), audio_file)
    assert isinstance(jam.sandbox.muda, jams.Sandbox)
    assert isinstance(jam2.sandbox.muda, jams.Sandbox)
<|endoftext|>


<commit_before>from django.db import models
from django.contrib.auth.models import User, Group
from datetime import datetime
import thumbnailer.shadowbox
from django.conf import settings
from taggit.managers import TaggableManager
from filemanager.models import fileobject
from djangoratings.fields import RatingField

##Does this actuall work? I don't think it does.... It seems to always return(SET_NULL)
##I've disabled it. Now whenever a fileobject gets deleted, it starts a task checking for null fields.
def select_thumbnail(instance):
   #project=Project.objects.filter(title=title)
    files=fileobject.objects.filter(pk=instance)###  This gets a list of files from the project
    for fl in files:
        if fl.filetype != 'norender' and fl.filetype != "text" and fl.filename != project.thumbnail:### Look for thumbnailable pic.
            project.thumbnail = fl
            return (fl)
    if noThumb:
        #project.thumbnail = fileobject.objects.all()[0] ## !!!!! THIS SETS THE THUMBNAIL. It sets it to whatever the first uploaded image is. This should be something better asap.
        return(SET_NULL)

class Project(models.Model):

    title = models.CharField(max_length=60,blank=True, null=True, unique=True)
    thumbnail = models.ForeignKey('filemanager.fileobject', blank=True, null=True, on_delete=models.SET_NULL , related_name='thumbnail')
    body = models.TextField(blank=True, null=True)

    #This exists soley so that we can find prohects that don't have a readme.
    bodyFile = models.ForeignKey('filemanager.fileobject', blank=True, null=True, on_delete=models.SET_NULL , related_name='readme')

    created = models.DateTimeField(auto_now_add = True)
    updated = models.DateTimeField(auto_now = True)
    author = models.ForeignKey(User, related_name='author',default=User)
    allow_html = models.BooleanField(default=False)
    ##only used internally, don't set
   #body_rendered = models.TextField('Entry body as HTML', blank=True, null=True)
    tags = TaggableManager(blank=True)
    draft = models.BooleanField(default=False)

    downloadcount = RatingField(range=1,allow_delete = False,allow_anonymous = True,)

    rating = RatingField(range=2, can_change_vote = True,allow_delete = True,)
    ratingSortBest = models.PositiveIntegerField(blank=True, null=True)
    ratingCount = models.IntegerField(blank=True, null=True)
    #Pretends that 0 is -1 and 1 is 1.
    def calc_adjusted_rating(self):
        upvotes = self.rating.votes - self.rating.score
        downvotes = self.rating.score - upvotes
        self.ratingCount = upvotes-downvotes

        self.ratingSortBest = self.ratingCount #fix this later
        super(Project, self).save()

    def __unicode__(self):
        return self.title
    def save(self):
        if not self.thumbnail:
            print(self.thumbnail)
            self.draft=True
        super(Project, self).save()

    def enf_consistancy(self):
        #checks if there's a thumbnail.
        if not self.thumbnail:
            files=fileobject.objects.filter(project=self)
            for fl in files:
                if fl.filetype != 'norender' and fl.filetype != "text":### Look for thumbnailable pic.
                    self.thumbnail = fl
                    super(Project, self).save()
                    break
                else:
                    self.draft = True
                    super(Project, self).save()
                    return False

        #check to see if there's a readme.
        if not self.bodyFile:
            files=fileobject.objects.filter(project=self, filetype="text")
            print(files)
            for fl in files:
                if False:### Look for thumbnailable pic.
                    self.bodyFile = fl.fileobject
                    super(Project, self).save()
                    break
                else:
                    self.draft = True
                    super(Project, self).save()
                    return False
        return True
<commit_msg>Added ratingBestSort to project.project, using http://www.evanmiller.org/how-not-to-sort-by-average-rating.html<commit_after>from django.db import models
from django.contrib.auth.models import User, Group
from datetime import datetime
import thumbnailer.shadowbox
from django.conf import settings
from taggit.managers import TaggableManager
from filemanager.models import fileobject
from djangoratings.fields import RatingField

##Does this actuall work? I don't think it does.... It seems to always return(SET_NULL)
##I've disabled it. Now whenever a fileobject gets deleted, it starts a task checking for null fields.
def select_thumbnail(instance):
   #project=Project.objects.filter(title=title)
    files=fileobject.objects.filter(pk=instance)###  This gets a list of files from the project
    for fl in files:
        if fl.filetype != 'norender' and fl.filetype != "text" and fl.filename != project.thumbnail:### Look for thumbnailable pic.
            project.thumbnail = fl
            return (fl)
    if noThumb:
        #project.thumbnail = fileobject.objects.all()[0] ## !!!!! THIS SETS THE THUMBNAIL. It sets it to whatever the first uploaded image is. This should be something better asap.
        return(SET_NULL)

class Project(models.Model):

    title = models.CharField(max_length=60,blank=True, null=True, unique=True)
    thumbnail = models.ForeignKey('filemanager.fileobject', blank=True, null=True, on_delete=models.SET_NULL , related_name='thumbnail')
    body = models.TextField(blank=True, null=True)

    #This exists soley so that we can find prohects that don't have a readme.
    bodyFile = models.ForeignKey('filemanager.fileobject', blank=True, null=True, on_delete=models.SET_NULL , related_name='readme')

    created = models.DateTimeField(auto_now_add = True)
    updated = models.DateTimeField(auto_now = True)
    author = models.ForeignKey(User, related_name='author',default=User)
    allow_html = models.BooleanField(default=False)
    ##only used internally, don't set
   #body_rendered = models.TextField('Entry body as HTML', blank=True, null=True)
    tags = TaggableManager(blank=True)
    draft = models.BooleanField(default=False)

    downloadcount = RatingField(range=1,allow_delete = False,allow_anonymous = True,)

    rating = RatingField(range=2, can_change_vote = True,allow_delete = True,)
    ratingSortBest = models.PositiveIntegerField(blank=True, null=True)
    ratingCount = models.IntegerField(blank=True, null=True)
    #Pretends that 0 is -1 and 1 is 1.
    def calc_adjusted_rating(self):
        import math

        upvotes = self.rating.votes - self.rating.score
        downvotes = self.rating.score - upvotes
        self.ratingCount = upvotes-downvotes
        votes = self.rating.votes
        self.ratingSortBest = self.ratingCount #fix this later

        if(self.rating.votes==0):
            self.ratingSortBest = 0
        else:
            r=1.0*upvotes/votes
            z=1.95
            self.ratingSortBest = (r+z*z-z*math.sqrt((r*(1-r)+(z*z/4*votes))/votes))/(1+z*z/votes)

        super(Project, self).save()

    def __unicode__(self):
        return self.title
    def save(self):
        if not self.thumbnail:
            print(self.thumbnail)
            self.draft=True
        super(Project, self).save()

    def enf_consistancy(self):
        #checks if there's a thumbnail.
        if not self.thumbnail:
            files=fileobject.objects.filter(project=self)
            for fl in files:
                if fl.filetype != 'norender' and fl.filetype != "text":### Look for thumbnailable pic.
                    self.thumbnail = fl
                    super(Project, self).save()
                    break
                else:
                    self.draft = True
                    super(Project, self).save()
                    return False

        #check to see if there's a readme.
        if not self.bodyFile:
            files=fileobject.objects.filter(project=self, filetype="text")
            print(files)
            for fl in files:
                if False:### Look for thumbnailable pic.
                    self.bodyFile = fl.fileobject
                    super(Project, self).save()
                    break
                else:
                    self.draft = True
                    super(Project, self).save()
                    return False
        return True
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import os
import unittest
import datetime
dbconfig = None
try:
    import dbconfig
    import erppeek_wst
except ImportError:
    pass
from generationkwh.isodates import addDays, localisodate

def datespan(startDate, endDate, delta=datetime.timedelta(hours=1)):
    currentDate = startDate
    while currentDate < endDate:
        yield currentDate
        currentDate += delta

@unittest.skipIf(not dbconfig, "depends on ERP")
class ProductionLoader_Test(unittest.TestCase):
    def setUp(self):
        self.erp = erppeek_wst.ClientWST(**dbconfig.erppeek)
        self.erp.begin()
        self.Plant = self.erp.GenerationkwhProductionPlant
        self.Meter = self.erp.GenerationkwhProductionMeter
        self.Aggregator = self.erp.GenerationkwhProductionAggregator
        self.AggregatorTestHelper = self.erp.GenerationkwhProductionAggregatorTesthelper
        self.ProductionLoader = self.erp.GenerationkwhProductionLoader
        self.TestHelper = self.erp.GenerationkwhTesthelper
        self.setUpAggregator()
        self.setUpMeasurements()
        self.setUpTemp()
        self.clearRemainders() # db

    def tearDown(self):
        self.clearAggregator() # db
        self.clearMeasurements()
        self.clearRemainders() # db
        self.clearTemp()
        self.erp.rollback()
        self.erp.close()

    def setUpAggregator(self):
        self.clearAggregator()

    def clearAggregator(self):
        self.Meter.unlink(self.Meter.search([]))
        self.Plant.unlink(self.Plant.search([]))
        self.Aggregator.unlink(self.Aggregator.search([]))

    def setUpMeasurements(self):
        self.collection = 'tm_profile'
        self.clearMeasurements()

    def clearMeasurements(self):
        self.TestHelper.clear_mongo_collections([self.collection])

    def setUpTemp(self):
        import tempfile
        self.tempdir = tempfile.mkdtemp()

    def clearTemp(self):
        for filename in os.listdir(self.tempdir):
            os.remove(os.path.join(self.tempdir, filename))
        os.removedirs(self.tempdir)

    def setupPlant(self, aggr_id, plant, nshares):
        return self.Plant.create(dict(
            aggr_id=aggr_id,
            name='myplant%d' % plant,
            description='myplant%d' % plant,
            enabled=True,
            nshares=nshares))

    def setupMeter(self, plant_id, plant, meter):
        return self.Meter.create(dict(
            plant_id=plant_id,
            name='mymeter%d%d' % (plant, meter),
            description='mymeter%d%d' % (plant, meter),
            uri='csv://%s/mymeter%d%d' % (self.tempdir, plant, meter),
            enabled=True))

    def setupAggregator(self, nplants, nmeters, nshares):
        aggr = self.Aggregator.create(dict(
            name='GenerationkWh',
            description='myaggr',
            enabled=True))

        for plant in range(nplants):
            plant_id = self.setupPlant(aggr, plant, nshares[plant])
            for meter in range(nmeters):
                self.setupMeter(plant_id, plant, meter)
        return aggr

    def setupRemainders(self, remainders):
        remainder = self.erp.model('generationkwh.remainder.testhelper')
        remainder.updateRemainders(remainders)
        return remainder

    def clearRemainders(self):
        remainder = self.erp.model('generationkwh.remainder')
        remainder.clean()

    def setupLocalMeter(self, name, points):
        import csv
        filename = os.path.join(self.tempdir,name)
        def toStr(date):
            return date.strftime('%Y-%m-%d %H:%M')

        with open(filename, 'w') as tmpfile:
            writer = csv.writer(tmpfile, delimiter=';')
            writer.writerows([[toStr(date),summer,value,0,0]
                for start, end, summer, values in points
                for date,value in zip(datespan(localisodate(start),
                    addDays(localisodate(end),1)),
                    values)])

    def getProduction(self, aggr_id, start, end):
        return self.AggregatorTestHelper.get_kwh(aggr_id, start, end)

    def test_retrieveMeasuresFromPlants_withNoPoints(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')

        production = self.getProduction(aggr_id, '2015-08-16', '2015-08-16')
        self.assertEqual(production, 25*[0])

    def test_retrieveMeasuresFromPlants_onePlant(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')

        production = self.getProduction(aggr_id, '2015-08-16', '2015-08-16')
        self.assertEqual(production, 10*[0]+[1000]+14*[0])

    def test_retrieveMeasuresFromPlants_twoPlant(self):
        aggr_id = self.setupAggregator(
                nplants=2,
                nmeters=1,
                nshares=[1,1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.setupLocalMeter('mymeter10',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')

        production = self.getProduction(aggr_id, '2015-08-16', '2015-08-16')
        self.assertEqual(production, 10*[0]+[2000]+14*[0])

    def test_computeAvailableRights_singleDay(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')
        remainder = self.setupRemainders([(1,'2015-08-16',0)])

        self.ProductionLoader.computeAvailableRights(aggr_id)

        result = self.TestHelper.rights_per_share(1, '2015-08-16', '2015-08-16')
        self.assertEqual(result, +10*[0]+[1000]+14*[0])
        self.assertEqual(remainder.lastRemainders(), [
            [1, '2015-08-17', 0],
            ])

    def test_computeAvailableRights_withManyPlantShares_divides(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[4]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[20000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')
        remainder = self.setupRemainders([(1,'2015-08-16',0)])

        self.ProductionLoader.computeAvailableRights(aggr_id)

        result = self.TestHelper.rights_per_share(1,'2015-08-16','2015-08-16')
        self.assertEqual(result, +10*[0]+[5000]+14*[0])
        self.assertEqual(remainder.lastRemainders(), [
            [1, '2015-08-17', 0],
            ])

    def test_computeAvailableRights_withManyPlantShares_twoDays(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[4]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-17', 'S', 2*(10*[0]+[20000]+13*[0]))
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-17')
        remainder = self.setupRemainders([(1,'2015-08-16',0)])

        self.ProductionLoader.computeAvailableRights(aggr_id)

        result = self.TestHelper.rights_per_share(1,'2015-08-16','2015-08-17')
        self.assertEqual(result, 2*(10*[0]+[5000]+14*[0]))
        self.assertEqual(remainder.lastRemainders(), [
            [1, '2015-08-18', 0],
            ])

unittest.TestCase.__str__ = unittest.TestCase.id

if __name__ == '__main__':
    unittest.main()

# vim: ts=4 sw=4 et
<commit_msg>indentation<commit_after># -*- coding: utf-8 -*-
import os
import unittest
import datetime
dbconfig = None
try:
    import dbconfig
    import erppeek_wst
except ImportError:
    pass
from generationkwh.isodates import addDays, localisodate

def datespan(startDate, endDate, delta=datetime.timedelta(hours=1)):
    currentDate = startDate
    while currentDate < endDate:
        yield currentDate
        currentDate += delta

@unittest.skipIf(not dbconfig, "depends on ERP")
class ProductionLoader_Test(unittest.TestCase):
    def setUp(self):
        self.erp = erppeek_wst.ClientWST(**dbconfig.erppeek)
        self.erp.begin()
        self.Plant = self.erp.GenerationkwhProductionPlant
        self.Meter = self.erp.GenerationkwhProductionMeter
        self.Aggregator = self.erp.GenerationkwhProductionAggregator
        self.AggregatorTestHelper = self.erp.GenerationkwhProductionAggregatorTesthelper
        self.ProductionLoader = self.erp.GenerationkwhProductionLoader
        self.TestHelper = self.erp.GenerationkwhTesthelper
        self.setUpAggregator()
        self.setUpMeasurements()
        self.setUpTemp()
        self.clearRemainders() # db

    def tearDown(self):
        self.clearAggregator() # db
        self.clearMeasurements()
        self.clearRemainders() # db
        self.clearTemp()
        self.erp.rollback()
        self.erp.close()

    def setUpAggregator(self):
        self.clearAggregator()

    def clearAggregator(self):
        self.Meter.unlink(self.Meter.search([]))
        self.Plant.unlink(self.Plant.search([]))
        self.Aggregator.unlink(self.Aggregator.search([]))

    def setUpMeasurements(self):
        self.collection = 'tm_profile'
        self.clearMeasurements()

    def clearMeasurements(self):
        self.TestHelper.clear_mongo_collections([self.collection])

    def setUpTemp(self):
        import tempfile
        self.tempdir = tempfile.mkdtemp()

    def clearTemp(self):
        for filename in os.listdir(self.tempdir):
            os.remove(os.path.join(self.tempdir, filename))
        os.removedirs(self.tempdir)

    def setupPlant(self, aggr_id, plant, nshares):
        return self.Plant.create(dict(
            aggr_id=aggr_id,
            name='myplant%d' % plant,
            description='myplant%d' % plant,
            enabled=True,
            nshares=nshares))

    def setupMeter(self, plant_id, plant, meter):
        return self.Meter.create(dict(
            plant_id=plant_id,
            name='mymeter%d%d' % (plant, meter),
            description='mymeter%d%d' % (plant, meter),
            uri='csv://%s/mymeter%d%d' % (self.tempdir, plant, meter),
            enabled=True))

    def setupAggregator(self, nplants, nmeters, nshares):
        aggr = self.Aggregator.create(dict(
            name='GenerationkWh',
            description='myaggr',
            enabled=True))

        for plant in range(nplants):
            plant_id = self.setupPlant(aggr, plant, nshares[plant])
            for meter in range(nmeters):
                self.setupMeter(plant_id, plant, meter)
        return aggr

    def setupRemainders(self, remainders):
        remainder = self.erp.model('generationkwh.remainder.testhelper')
        remainder.updateRemainders(remainders)
        return remainder

    def clearRemainders(self):
        remainder = self.erp.model('generationkwh.remainder')
        remainder.clean()

    def setupLocalMeter(self, name, points):
        import csv
        filename = os.path.join(self.tempdir,name)
        def toStr(date):
            return date.strftime('%Y-%m-%d %H:%M')

        with open(filename, 'w') as tmpfile:
            writer = csv.writer(tmpfile, delimiter=';')
            writer.writerows([[toStr(date),summer,value,0,0]
                for start, end, summer, values in points
                for date,value in zip(datespan(localisodate(start),
                    addDays(localisodate(end),1)),
                    values)])

    def getProduction(self, aggr_id, start, end):
        return self.AggregatorTestHelper.get_kwh(aggr_id, start, end)

    def test_retrieveMeasuresFromPlants_withNoPoints(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')

        production = self.getProduction(aggr_id, '2015-08-16', '2015-08-16')
        self.assertEqual(production, 25*[0])

    def test_retrieveMeasuresFromPlants_onePlant(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')

        production = self.getProduction(aggr_id, '2015-08-16', '2015-08-16')
        self.assertEqual(production, 10*[0]+[1000]+14*[0])

    def test_retrieveMeasuresFromPlants_twoPlant(self):
        aggr_id = self.setupAggregator(
                nplants=2,
                nmeters=1,
                nshares=[1,1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.setupLocalMeter('mymeter10',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
            '2015-08-16', '2015-08-16')

        production = self.getProduction(aggr_id, '2015-08-16', '2015-08-16')
        self.assertEqual(production, 10*[0]+[2000]+14*[0])

    def test_computeAvailableRights_singleDay(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[1]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[1000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
            '2015-08-16', '2015-08-16')
        remainder = self.setupRemainders([(1,'2015-08-16',0)])

        self.ProductionLoader.computeAvailableRights(aggr_id)

        result = self.TestHelper.rights_per_share(1, '2015-08-16', '2015-08-16')
        self.assertEqual(result, +10*[0]+[1000]+14*[0])
        self.assertEqual(remainder.lastRemainders(), [
            [1, '2015-08-17', 0],
            ])

    def test_computeAvailableRights_withManyPlantShares_divides(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[4]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-16', 'S', 10*[0]+[20000]+13*[0])
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-16')
        remainder = self.setupRemainders([(1,'2015-08-16',0)])

        self.ProductionLoader.computeAvailableRights(aggr_id)

        result = self.TestHelper.rights_per_share(1,'2015-08-16','2015-08-16')
        self.assertEqual(result, +10*[0]+[5000]+14*[0])
        self.assertEqual(remainder.lastRemainders(), [
            [1, '2015-08-17', 0],
            ])

    def test_computeAvailableRights_withManyPlantShares_twoDays(self):
        aggr_id = self.setupAggregator(
                nplants=1,
                nmeters=1,
                nshares=[4]).read(['id'])['id']
        self.setupLocalMeter('mymeter00',[
            ('2015-08-16', '2015-08-17', 'S', 2*(10*[0]+[20000]+13*[0]))
            ])
        self.ProductionLoader.retrieveMeasuresFromPlants(aggr_id,
                '2015-08-16', '2015-08-17')
        remainder = self.setupRemainders([(1,'2015-08-16',0)])

        self.ProductionLoader.computeAvailableRights(aggr_id)

        result = self.TestHelper.rights_per_share(1,'2015-08-16','2015-08-17')
        self.assertEqual(result, 2*(10*[0]+[5000]+14*[0]))
        self.assertEqual(remainder.lastRemainders(), [
            [1, '2015-08-18', 0],
            ])

unittest.TestCase.__str__ = unittest.TestCase.id

if __name__ == '__main__':
    unittest.main()

# vim: ts=4 sw=4 et
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import print_function
import gevent.monkey
gevent.monkey.patch_all()

import gevent
import twitter

from collections import defaultdict
import random
import time
import json
import re

try:
    # Python2
    import HTMLParser
    unescape_html = HTMLParser.HTMLParser().unescape
except ImportError:
    # Python3
    import html.parser
    unescape_html = html.parser.HTMLParser().unescape

# change here, change in setup.py
__version__ = "0.1.1"

class Stop(object):
    # Why did I do this? I just like using my terminal.
    def __str__(self):
        return "<stop>"
    __repr__ = __str__

class Ebooks(object):
    """ Turn your crummy Twitter feed into a top lel _ebooks bot.

        Note: the markov stuff is built into this class, ooh err.
        It's available under _markov_*, but be warned - I might change
        those whenever I get temperamental about my code.

        auth - a dict with tuple/list information from the Twitter dev site:
            {("origin_account", "ebooks_account"): (OAUTH_TOKEN,
                                                    OAUTH_SECRET,
                                                    CONSUMER_KEY,
                                                    CONSUMER_SECRET)}
        dry - do everything, but actually interacting with Twitter.
        verbose - what it says on the tin, debug actually prints stuff.
        chain_length - the quality of the markov output.
            1 is complete gibberish
            2 is reasonably adequate
            3 is perfect (when it works at all)
    """
    auth = None
    dry = False
    verbose = False

    chain_length = 2
    max_words = 30

    def __init__(self):
        if self.auth is None or len(self.auth) == 0:
            raise RuntimeError("No auth given.")
        # Markov junk
        self.stop_word = Stop()
        self.markov = {}  # markov[ebook]
        # Ebooks junk
        self.length_cap = 140
        self.horse()

    def horse(self):
        self.names = {}
        self.t = {}
        self.seen = {}
        self.tweets = {}
        self.settings = {}
        for names, auth in self.auth.items():
            origin, ebooks = names
            self.add(origin, ebooks, auth)

    def _markov_split(self, message, chain_length):
        words = message.split()
        if len(words) < chain_length:
            return
        words.append(self.stop_word)
        for i in xrange(len(words) - chain_length):
            yield words[i:i + chain_length + 1]

    def _markov_add(self, ebooks, message, chain_length):
        s = self.markov[ebooks]
        for words in self._markov_split(message, chain_length):
            key = tuple(words[:-1])
            s.setdefault(key, [])
            s[key].append(words[-1])
        return s

    def _markov_gen(self, ebooks, seed=None, chain_length=None):
        if seed is None:
            seed = random.choice(self.tweets[ebooks])["text"]
        if chain_length is None:
            chain_length = self.chain_length
        key = seed.split()[:chain_length]
        gen_words = []
        for i in xrange(self.max_words):
            gen_words.append(key[0])
            if len(" ".join(gen_words)) > self.length_cap:
                # TODO: this makes the chain crap. What can we do?
                gen_words.pop(-1)
                break
            try:
                next_word = self.markov[ebooks][tuple(key)]
            except KeyError:
                # bail bail bail bail!
                break
            if not next_word:
                break
            next = random.choice(next_word)
            key = key[1:] + [next]
            if next is self.stop_word:
                gen_words.append(key[0])
                break
        message = " ".join(gen_words)  # Join the list
        message = re.sub(r"(?:\.)?@([^\s]+)", r"#\1", message)  # Butcher mentions
        message = unescape_html(message)  # Escape HTML codes
        return message.strip()

    # Ebooks junk
    def add(self, origin, ebooks, auth):
        self.names[ebooks] = origin
        self.t[ebooks] = None if self.dry else twitter.Twitter(auth=twitter.OAuth(*auth))
        self.seen[ebooks] = 0
        self.tweets[ebooks] = self.load(ebooks)
        if len(self.tweets[ebooks]) > 0:
            self.seen[ebooks] = self.tweets[ebooks][-1]["id"]
        self.settings[ebooks] = None if self.dry else self.t[ebooks].account.settings()
        # Markov junk
        self.markov[ebooks] = {}
        for tweet in self.tweets[ebooks]:
            self._markov_add(ebooks, tweet["text"], self.chain_length)

    def load(self, ebooks):
        origin = self.names[ebooks]
        try:
            with open("{0}.json".format(origin), "rb") as f:
                loaded = json.loads(f.read())
                self.seen[ebooks] = loaded["seen"]
                return loaded["tweets"]
        except IOError:
            # We can't find the brain!
            return []

    def save(self, ebooks, tweets=None):
        if tweets is None:
            tweets = self.tweets[ebooks]
        origin = self.names[ebooks]
        self.debug(ebooks, "Saving brain of:", origin)
        with open("{0}.json".format(origin), "wb") as f:
            json.dump({"tweets": tweets, "seen": self.seen[ebooks]}, f, indent=4)

    def fetch(self, ebooks=None):
        if ebooks is None:
            ebooks = self.names.keys()
        for ebook in ebooks:
            origin = self.names[ebook]
            bits = {"screen_name": origin, "include_rts": "false", "count": 200}
            if self.seen[ebook]:
                bits["since_id"] = self.seen[ebook]
            self.debug(ebook, "**bits:?", bits)
            tweets = self.t[ebook].statuses.user_timeline(**bits)
            self.debug(ebook, "Found", len(tweets), "new tweets")
            if len(tweets) > 0:
                self.seen[ebook] = tweets[0]["id"]
            self.debug(ebook, "Last tweet:", self.seen[ebook])
            self.tweets[ebook].extend([{"id":tweet["id"], "text":tweet["text"]} for tweet in tweets])
            self.save(ebook)

    def debug(self, ebooks, *msg):
        if not self.verbose:
            return
        print(u"[{0}] {1}".format(ebooks, u" ".join(map(unicode, msg))))

    """
    def _fetch_tweets(self):
        tweets = self.t.search.tweets(q=" OR ".join(self.phrases), lang="en")
        for t in tweets['statuses']:
            if self.queue.qsize() >= self.max_queue:
                break
            # Why single rather than stacked? It's cleaner.
            if self._in_reply_to_us(t):
                continue
            if self._from_us(t):
                continue
            if self._is_retweet(t):
                continue
            if not self.ignore_display_names and self._is_display_name(t):
                continue
            if t['id'] in self.seen:
                continue

            self.seen.append(t['id'])
            self.queue.put_nowait(t)
        self._next_fetch = time.time() + self._cooldown_fetch

    def do_loop(self):
        # Actually start our produce loop.
        self.producer = gevent.spawn(self._produce)
        while True:
            if self.queue.empty():
                gevent.sleep(0)
            if self._next_tweet > time.time():
                gevent.sleep(0)
                continue
            task = self.queue.get()
            self.take_action(task['text'], task['user']['screen_name'], task['id'])
            self._next_tweet = time.time() + self._cooldown_tweet
    """<commit_msg>Tidy up the Stop thing.<commit_after># -*- coding: utf-8 -*-
from __future__ import print_function
import gevent.monkey
gevent.monkey.patch_all()

import gevent
import twitter

from collections import defaultdict
import random
import time
import json
import re

try:
    # Python2
    import HTMLParser
    unescape_html = HTMLParser.HTMLParser().unescape
except ImportError:
    # Python3
    import html.parser
    unescape_html = html.parser.HTMLParser().unescape

# change here, change in setup.py
__version__ = "0.1.1"

class Stop(object):
    # Why did I do this? I just like using my terminal.
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "_stop_word"):
            cls._stop_word = super(Stop, cls).__new__(cls, *args, **kwargs)
        return cls._stop_word
    def __str__(self):
        return "<stop>"
    __repr__ = __str__

class Ebooks(object):
    """ Turn your crummy Twitter feed into a top lel _ebooks bot.

        Note: the markov stuff is built into this class, ooh err.
        It's available under _markov_*, but be warned - I might change
        those whenever I get temperamental about my code.

        auth - a dict with tuple/list information from the Twitter dev site:
            {("origin_account", "ebooks_account"): (OAUTH_TOKEN,
                                                    OAUTH_SECRET,
                                                    CONSUMER_KEY,
                                                    CONSUMER_SECRET)}
        dry - do everything, but actually interacting with Twitter.
        verbose - what it says on the tin, debug actually prints stuff.
        chain_length - the quality of the markov output.
            1 is complete gibberish
            2 is reasonably adequate
            3 is perfect (when it works at all)
    """
    auth = None
    dry = False
    verbose = False

    chain_length = 2
    max_words = 30

    def __init__(self):
        if self.auth is None or len(self.auth) == 0:
            raise RuntimeError("No auth given.")
        # Markov junk
        self.stop_word = Stop()
        self.markov = {}  # markov[ebook]
        # Ebooks junk
        self.length_cap = 140
        self.horse()

    def horse(self):
        self.names = {}
        self.t = {}
        self.seen = {}
        self.tweets = {}
        self.settings = {}
        for names, auth in self.auth.items():
            origin, ebooks = names
            self.add(origin, ebooks, auth)

    def _markov_split(self, message, chain_length):
        words = message.split()
        if len(words) < chain_length:
            return
        words.append(self.stop_word)
        for i in xrange(len(words) - chain_length):
            yield words[i:i + chain_length + 1]

    def _markov_add(self, ebooks, message, chain_length):
        s = self.markov[ebooks]
        for words in self._markov_split(message, chain_length):
            key = tuple(words[:-1])
            s.setdefault(key, [])
            s[key].append(words[-1])
        return s

    def _markov_gen(self, ebooks, seed=None, chain_length=None):
        if seed is None:
            seed = random.choice(self.tweets[ebooks])["text"]
        if chain_length is None:
            chain_length = self.chain_length
        key = seed.split()[:chain_length]
        gen_words = []
        self.debug(ebooks, seed, key, chain_length)
        for i in xrange(self.max_words):
            gen_words.append(key[0])
            if len(" ".join(gen_words)) > self.length_cap:
                # TODO: this makes the chain crap. What can we do?
                gen_words.pop(-1)
                break
            try:
                next_word = self.markov[ebooks][tuple(key)]
            except KeyError:
                # bail bail bail bail!
                break
            if not next_word:
                break
            next = random.choice(next_word)
            key = key[1:] + [next]
            if next is self.stop_word:
                gen_words.append(key[0])
                break
        message = " ".join(gen_words)  # Join the list
        message = re.sub(r"(?:\.)?@([^\s]+)", r"#\1", message)  # Butcher mentions
        message = unescape_html(message)  # Escape HTML codes
        return message.strip()

    # Ebooks junk
    def add(self, origin, ebooks, auth):
        self.names[ebooks] = origin
        self.t[ebooks] = None if self.dry else twitter.Twitter(auth=twitter.OAuth(*auth))
        self.seen[ebooks] = 0
        self.tweets[ebooks] = self.load(ebooks)
        if len(self.tweets[ebooks]) > 0:
            self.seen[ebooks] = self.tweets[ebooks][-1]["id"]
        self.settings[ebooks] = None if self.dry else self.t[ebooks].account.settings()
        # Markov junk
        self.markov[ebooks] = {}
        for tweet in self.tweets[ebooks]:
            self._markov_add(ebooks, tweet["text"], self.chain_length)

    def load(self, ebooks):
        origin = self.names[ebooks]
        try:
            with open("{0}.json".format(origin), "rb") as f:
                loaded = json.loads(f.read())
                self.seen[ebooks] = loaded["seen"]
                return loaded["tweets"]
        except IOError:
            # We can't find the brain!
            return []

    def save(self, ebooks, tweets=None):
        if tweets is None:
            tweets = self.tweets[ebooks]
        origin = self.names[ebooks]
        self.debug(ebooks, "Saving brain of:", origin)
        with open("{0}.json".format(origin), "wb") as f:
            json.dump({"tweets": tweets, "seen": self.seen[ebooks]}, f, indent=4)

    def fetch(self, ebooks=None):
        if ebooks is None:
            ebooks = self.names.keys()
        for ebook in ebooks:
            origin = self.names[ebook]
            bits = {"screen_name": origin, "include_rts": "false", "count": 200}
            if self.seen[ebook]:
                bits["since_id"] = self.seen[ebook]
            self.debug(ebook, "**bits:?", bits)
            tweets = self.t[ebook].statuses.user_timeline(**bits)
            self.debug(ebook, "Found", len(tweets), "new tweets")
            if len(tweets) > 0:
                self.seen[ebook] = tweets[0]["id"]
            self.debug(ebook, "Last tweet:", self.seen[ebook])
            self.tweets[ebook].extend([{"id":tweet["id"], "text":tweet["text"]} for tweet in tweets])
            self.save(ebook)

    def debug(self, ebooks, *msg):
        if not self.verbose:
            return
        print(u"[@{0}] {1}".format(ebooks, u" ".join(map(unicode, msg))))

    """
    def _fetch_tweets(self):
        tweets = self.t.search.tweets(q=" OR ".join(self.phrases), lang="en")
        for t in tweets['statuses']:
            if self.queue.qsize() >= self.max_queue:
                break
            # Why single rather than stacked? It's cleaner.
            if self._in_reply_to_us(t):
                continue
            if self._from_us(t):
                continue
            if self._is_retweet(t):
                continue
            if not self.ignore_display_names and self._is_display_name(t):
                continue
            if t['id'] in self.seen:
                continue

            self.seen.append(t['id'])
            self.queue.put_nowait(t)
        self._next_fetch = time.time() + self._cooldown_fetch

    def do_loop(self):
        # Actually start our produce loop.
        self.producer = gevent.spawn(self._produce)
        while True:
            if self.queue.empty():
                gevent.sleep(0)
            if self._next_tweet > time.time():
                gevent.sleep(0)
                continue
            task = self.queue.get()
            self.take_action(task['text'], task['user']['screen_name'], task['id'])
            self._next_tweet = time.time() + self._cooldown_tweet
    """<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

from django_autocomplete.meta import AutocompleteMeta

API_FILTER_PATH = 'api/filter'

def get_autocomplete_meta(name):
    return AutocompleteMeta(
        name=name,
        path='%s/%s' % (API_FILTER_PATH, name)
        )

class Timestamped(models.Model):
    """
    The Timestamped model, all models in the application share its attributes.

        >>> obj = Timestamped()
        >>> obj.created

    """
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class Base(models.Model):
    """
    The Base model, all models in the application share its attributes.

        >>> obj = Base(name='base')
        >>> obj.name
        'base'

    """
    name = models.CharField(
        max_length=30
        )

    class Meta:
        abstract = True

    def __unicode__(self):
        return u'%s' % (self.name)

    def __str__(self):
        return '%s' % (self.name)

class Documentation(Base, Timestamped):
    """
    The Documentation model.

        >>> obj = Documentation.objects.create(name='usa')
        >>> obj.autocomplete.name
        'documentation'
        >>> obj.autocomplete.path
        'api/filter/documentation'

        >>> obj.delete()

    """
    autocomplete = get_autocomplete_meta('documentation')

    class Meta:
        verbose_name_plural = 'Documentation'

class HasDoc(models.Model):
    """
    Abstract model class to store documentation to models

    Other classes are expected to subclass this model to contain documents.::

        class ModelHasDocs(HasDocumentation)
            pass

    """
    documentation = models.ManyToManyField(
        Documentation,
        blank=True, null=True,
        related_name="documentation_for_%(class)s"
        )

    class Meta:
        abstract = True

class Country(Base, HasDoc, Timestamped):
    """
    The Country model. Each town has a ForeignKey to its Country.

        >>> obj = Country.objects.create(name='usa')
        >>> obj.autocomplete.name
        'country'
        >>> obj.autocomplete.path
        'api/filter/country'

        >>> obj.delete()

    """
    autocomplete = get_autocomplete_meta('country')

    class Meta:
        verbose_name = 'Country'
        verbose_name_plural = 'Countries'

class Organisation(Base, HasDoc, Timestamped):
    """
    The Organisation model. It has a many to many relationship with Towns.

        >>> obj = Organisation.objects.create(name='microsoft')
        >>> obj.autocomplete.name
        'organisation'
        >>> obj.autocomplete.path
        'api/filter/organisation'

    Has docs:

        >>> obj.documentation.all()
        []

        >>> obj.delete()

    """
    autocomplete = get_autocomplete_meta('organisation')

    class Meta:
        verbose_name = 'Organisation'

class Town(Base, HasDoc, Timestamped):
    """
    The Town model.

        >>> usa = Country.objects.create(name='usa')
        >>> obj = Town.objects.create(name='redmond', country=usa)
        >>> obj.autocomplete.name
        'town'
        >>> obj.autocomplete.path
        'api/filter/town'

    Has a country:

        >>> obj.country
        <Country: usa>

    Has organisations:

        >>> obj.organisations.all()
        []

    Can have sister towns:

        >>> obj.sister_towns.add(Town.objects.create(name='redmond', country=usa))
        >>> obj.sister_towns.all()
        [<Town: redmond>]

    Clean up

        >>> usa.delete()
        >>> obj.delete()

    """
    country = models.ForeignKey(Country, null=True)
    organisations = models.ManyToManyField(
        Organisation,
        through='project.OrganisationTown',
        related_name='towns'
        )
    sister_towns = models.ManyToManyField('self', blank=True)

    autocomplete = AutocompleteMeta(
        name='town',
        path='%s/town' % API_FILTER_PATH
        )

    class Meta:
        verbose_name = 'Town'

class OrganisationTown(HasDoc, Timestamped):
    """
    The OrganisationTown model. It is the `through` model for Towns and
    Organisations.

        >>> usa = Country.objects.create(name='usa')
        >>> town = Town.objects.create(name='redmond', country=usa)
        >>> org = Organisation.objects.create(name='microsoft')

    Join them with the through table:

        >>> import datetime
        >>> join = OrganisationTown.objects.create(
        ...     joined=datetime.date(2014, 7, 10), town=town,
        ...     organisation=org)

    Clean up

        >>> usa.delete()
        >>> town.delete()
        >>> org.delete()
        >>> join.delete()

    """
    organisation = models.ForeignKey(Organisation)
    town = models.ForeignKey(Town)
    joined = models.DateField()

    autocomplete = AutocompleteMeta(
        name='organisationtown',
        path='%s/organisationtown' % API_FILTER_PATH
        )

    class Meta:
        verbose_name = 'Organisation Town Join'

class TaggedItem(Timestamped, models.Model):
    """
    Simple generic content type example from `django generic relations
    <https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#generic-relations>`_

        >>> town = Town.objects.create(name='Twin Peaks')
        >>> tag = TaggedItem(content_object=town, tag='lynch')
        >>> tag.save()
        >>> tag.content_object
        <Town: Twin Peaks>

    Clean up::

        >>> tag.delete()
        >>> town.delete()

    """
    tag = models.SlugField()
    content_type = models.ForeignKey(
        ContentType,
        limit_choices_to=models.Q(model__in=['town', 'country', 'organisation']))
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.tag

class TestMe(models.Model):
    test_ip = models.IPAddressField(help_text="Lorem dolor")
    test_url = models.URLField(help_text="Lorem dolor")
    test_int = models.IntegerField(help_text="Lorem dolor")
    test_img = models.ImageField(upload_to='dummy', blank=True)
    test_file = models.FileField(upload_to='dummy', blank=True)
    test_date = models.DateField(help_text="Lorem dolor")
    test_char = models.CharField(max_length=50, help_text="Lorem dolor")
    test_bool = models.BooleanField(default=False, help_text="Lorem dolor")
    test_time = models.TimeField(help_text="Lorem dolor")
    test_slug = models.SlugField(help_text="Lorem dolor")
    test_text = models.TextField(help_text="Lorem dolor")
    test_email = models.EmailField(help_text="Lorem dolor")
    test_float = models.FloatField(help_text="Lorem dolor")
    test_bigint = models.BigIntegerField(help_text="Lorem dolor")
    test_positive_integer = models.PositiveIntegerField(help_text="Lorem dolor")
    test_decimal = models.DecimalField(max_digits=5, decimal_places=2, help_text="Lorem dolor")
    test_comma_separated_int = models.CommaSeparatedIntegerField(max_length=100, help_text="Lorem dolor")
    test_small_int = models.SmallIntegerField(help_text="Lorem dolor")
    test_nullbool = models.NullBooleanField(help_text="Lorem dolor")
    test_filepath = models.FilePathField(blank=True, help_text="Lorem dolor")
    test_positive_small_int = models.PositiveSmallIntegerField(help_text="Lorem dolor")

    class Meta:
        verbose_name = u'Test me'
        verbose_name_plural = u'Lot of Test me'

class TestSortable(models.Model):
    that = models.ForeignKey(TestMe)
    position = models.PositiveSmallIntegerField("Position")
    test_char = models.CharField(max_length=5)

    class Meta:
        ordering = ('position', )
<commit_msg>updated test models<commit_after># -*- coding: utf-8 -*-
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

from django_autocomplete.meta import AutocompleteMeta

API_FILTER_PATH = 'api/filter'

class Autocomplete(object):

  @property
  def autocomplete(self):
      name = self.__class__.__name__.lower()
      return AutocompleteMeta(
          name=name,
          path='%s/%s' % (API_FILTER_PATH, name),
          permissions=True
          )

class Timestamped(models.Model):
    """
    The Timestamped model, all models in the application share its attributes.

        >>> obj = Timestamped()
        >>> obj.created

    """
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class Base(models.Model, Autocomplete):
    """
    The Base model, all models in the application share its attributes.

        >>> obj = Base(name='base')
        >>> obj.name
        'base'

    """
    name = models.CharField(
        max_length=30
        )

    class Meta:
        abstract = True

    def __unicode__(self):
        return u'%s' % (self.name)

    def __str__(self):
        return '%s' % (self.name)

class Documentation(Base, Timestamped):
    """
    The Documentation model.

        >>> obj = Documentation.objects.create(name='usa')
        >>> obj.autocomplete.name
        'documentation'
        >>> obj.autocomplete.path
        'api/filter/documentation'

        >>> obj.delete()

    """
    class Meta:
        verbose_name_plural = 'Documentation'

class HasDoc(models.Model):
    """
    Abstract model class to store documentation to models

    Other classes are expected to subclass this model to contain documents.::

        class ModelHasDocs(HasDocumentation)
            pass

    """
    documentation = models.ManyToManyField(
        Documentation,
        blank=True, null=True,
        related_name="documentation_for_%(class)s"
        )

    class Meta:
        abstract = True

class Country(Base, HasDoc, Timestamped):
    """
    The Country model. Each town has a ForeignKey to its Country.

        >>> obj = Country.objects.create(name='usa')
        >>> obj.autocomplete.name
        'country'
        >>> obj.autocomplete.path
        'api/filter/country'

        >>> obj.delete()

    """
    class Meta:
        verbose_name = 'Country'
        verbose_name_plural = 'Countries'

class Organisation(Base, HasDoc, Timestamped):
    """
    The Organisation model. It has a many to many relationship with Towns.

        >>> obj = Organisation.objects.create(name='microsoft')
        >>> obj.autocomplete.name
        'organisation'
        >>> obj.autocomplete.path
        'api/filter/organisation'

    Has docs:

        >>> obj.documentation.all()
        []

        >>> obj.delete()

    """
    class Meta:
        verbose_name = 'Organisation'

class Town(Base, HasDoc, Timestamped):
    """
    The Town model.

        >>> usa = Country.objects.create(name='usa')
        >>> obj = Town.objects.create(name='redmond', country=usa)
        >>> obj.autocomplete.name
        'town'
        >>> obj.autocomplete.path
        'api/filter/town'

    Has a country:

        >>> obj.country
        <Country: usa>

    Has organisations:

        >>> obj.organisations.all()
        []

    Can have sister towns:

        >>> obj.sister_towns.add(Town.objects.create(name='redmond', country=usa))
        >>> obj.sister_towns.all()
        [<Town: redmond>]

    Clean up

        >>> usa.delete()
        >>> obj.delete()

    """
    country = models.ForeignKey(Country, null=True)
    organisations = models.ManyToManyField(
        Organisation,
        through='project.OrganisationTown',
        related_name='towns'
        )
    sister_towns = models.ManyToManyField('self', blank=True)

    autocomplete = AutocompleteMeta(
        name='town',
        path='%s/town' % API_FILTER_PATH
        )

    class Meta:
        verbose_name = 'Town'

class OrganisationTown(HasDoc, Timestamped):
    """
    The OrganisationTown model. It is the `through` model for Towns and
    Organisations.

        >>> usa = Country.objects.create(name='usa')
        >>> town = Town.objects.create(name='redmond', country=usa)
        >>> org = Organisation.objects.create(name='microsoft')

    Join them with the through table:

        >>> import datetime
        >>> join = OrganisationTown.objects.create(
        ...     joined=datetime.date(2014, 7, 10), town=town,
        ...     organisation=org)

    Clean up

        >>> usa.delete()
        >>> town.delete()
        >>> org.delete()
        >>> join.delete()

    """
    organisation = models.ForeignKey(Organisation)
    town = models.ForeignKey(Town)
    joined = models.DateField()

    autocomplete = AutocompleteMeta(
        name='organisationtown',
        path='%s/organisationtown' % API_FILTER_PATH
        )

    class Meta:
        verbose_name = 'Organisation Town Join'

class TaggedItem(Timestamped, models.Model):
    """
    Simple generic content type example from `django generic relations
    <https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#generic-relations>`_

        >>> town = Town.objects.create(name='Twin Peaks')
        >>> tag = TaggedItem(content_object=town, tag='lynch')
        >>> tag.save()
        >>> tag.content_object
        <Town: Twin Peaks>

    Clean up::

        >>> tag.delete()
        >>> town.delete()

    """
    tag = models.SlugField()
    content_type = models.ForeignKey(
        ContentType,
        limit_choices_to=models.Q(model__in=['town', 'country', 'organisation']))
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.tag

class TestMe(models.Model):
    test_ip = models.IPAddressField(help_text="Lorem dolor")
    test_url = models.URLField(help_text="Lorem dolor")
    test_int = models.IntegerField(help_text="Lorem dolor")
    test_img = models.ImageField(upload_to='dummy', blank=True)
    test_file = models.FileField(upload_to='dummy', blank=True)
    test_date = models.DateField(help_text="Lorem dolor")
    test_char = models.CharField(max_length=50, help_text="Lorem dolor")
    test_bool = models.BooleanField(default=False, help_text="Lorem dolor")
    test_time = models.TimeField(help_text="Lorem dolor")
    test_slug = models.SlugField(help_text="Lorem dolor")
    test_text = models.TextField(help_text="Lorem dolor")
    test_email = models.EmailField(help_text="Lorem dolor")
    test_float = models.FloatField(help_text="Lorem dolor")
    test_bigint = models.BigIntegerField(help_text="Lorem dolor")
    test_positive_integer = models.PositiveIntegerField(help_text="Lorem dolor")
    test_decimal = models.DecimalField(max_digits=5, decimal_places=2, help_text="Lorem dolor")
    test_comma_separated_int = models.CommaSeparatedIntegerField(max_length=100, help_text="Lorem dolor")
    test_small_int = models.SmallIntegerField(help_text="Lorem dolor")
    test_nullbool = models.NullBooleanField(help_text="Lorem dolor")
    test_filepath = models.FilePathField(blank=True, help_text="Lorem dolor")
    test_positive_small_int = models.PositiveSmallIntegerField(help_text="Lorem dolor")

    class Meta:
        verbose_name = u'Test me'
        verbose_name_plural = u'Lot of Test me'

class TestSortable(models.Model):
    that = models.ForeignKey(TestMe)
    position = models.PositiveSmallIntegerField("Position")
    test_char = models.CharField(max_length=5)

    class Meta:
        ordering = ('position', )
<|endoftext|>


<commit_before>#!/usr/bin/python2

# NOTE: https://pymodbus.readthedocs.io/en/latest/examples/synchronous-client.html

import argparse  # TODO: check if it is too slow
from pymodbus.client.sync import ModbusTcpClient as ModbusClient

from sys import argv

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument('-i', type=str, dest='ip', help='port number')
    parser.add_argument('-p', type=int, dest='port', choices=[502],
            default=502, help='port number')
    parser.add_argument('-u', type=int, dest='unit',
            default=0, help='slave unit number')
    parser.add_argument('-t', type=str, dest='type',
            choices=['DI', 'CO', 'IR', 'HR'],
            help='request type')
    args = parser.parse_args()

    import logging
    logging.basicConfig()
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)

    IP = argv[1]
    PORT = argv[2]  # modbus 502
    UNIT = argv[3]  # slave number 0

    client = ModbusClient(ip, port=port,
            retries=3, retry_on_empty=True)

    client.connect()
<commit_msg>Fix typo<commit_after>#!/usr/bin/python2

# NOTE: https://pymodbus.readthedocs.io/en/latest/examples/synchronous-client.html

import argparse  # TODO: check if it is too slow
from pymodbus.client.sync import ModbusTcpClient as ModbusClient

from sys import argv

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument('-i', type=str, dest='ip', help='request ip')
    parser.add_argument('-p', type=int, dest='port', choices=[502],
            default=502, help='port number')
    parser.add_argument('-u', type=int, dest='unit',
            default=0, help='slave unit number')
    parser.add_argument('-t', type=str, dest='type',
            choices=['DI', 'CO', 'IR', 'HR'],
            help='request type')
    args = parser.parse_args()

    import logging
    logging.basicConfig()
    log = logging.getLogger()
    log.setLevel(logging.DEBUG)

    IP = argv[1]
    PORT = argv[2]  # modbus 502
    UNIT = argv[3]  # slave number 0

    client = ModbusClient(ip, port=port,
            retries=3, retry_on_empty=True)

    client.connect()
<|endoftext|>


<commit_before>import pytest

import randomizer.dice as dice

expected_dice_faces = [
    (set(dice.d4.randomDraw()), set(range(1, 5))),
    (set(dice.d6.randomDraw()), set(range(1, 7))),
    (set(dice.d8.randomDraw()), set(range(1, 9))),
    (set(dice.d10.randomDraw()), set(range(1, 11))),
    (set(dice.d12.randomDraw()), set(range(1, 13))),
]

@pytest.mark.parametrize('dice,expected', expected_dice_faces)
def test_dice_has_proper_num_of_faces(dice, expected):
    assert dice == expected
<commit_msg>Change line separators<commit_after>import pytest

import randomizer.dice as dice

expected_dice_faces = [
    (set(dice.d4.randomDraw()), set(range(1, 5))),
    (set(dice.d6.randomDraw()), set(range(1, 7))),
    (set(dice.d8.randomDraw()), set(range(1, 9))),
    (set(dice.d10.randomDraw()), set(range(1, 11))),
    (set(dice.d12.randomDraw()), set(range(1, 13))),
]

@pytest.mark.parametrize('dice,expected', expected_dice_faces)
def test_dice_has_proper_num_of_faces(dice, expected):
    assert dice == expected
<|endoftext|>


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

#   Copyright 2010-2012 Tuukka Turto
#
#   This file is part of pyherc.
#
#   pyherc is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   pyherc is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with pyherc.  If not, see <http://www.gnu.org/licenses/>.

"""
Main entry point for Herculeum - game
"""
import sys
import os.path
import thread
import time

INSTALL_PATH = os.path.abspath(".")
sys.path.append(INSTALL_PATH)

from pyherc.debug import get_debug_server
from herculeum.application import APP
from PyQt4.QtGui import QPixmap, QSplashScreen
import herculeum.gui.resources

print '#   pyherc is free software: you can redistribute it and/or modify'
print '#   it under the terms of the GNU General Public License as published by'
print '#   the Free Software Foundation, either version 3 of the License, or'
print '#   (at your option) any later version.'
print '#'
print '#   pyherc is distributed in the hope that it will be useful,'
print '#   but WITHOUT ANY WARRANTY; without even the implied warranty of'
print '#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the'
print '#   GNU General Public License for more details.'
print '#'
print '#   You should have received a copy of the GNU General Public License'
print '#   along with pyherc.  If not, see <http://www.gnu.org/licenses/>.'

if __name__ == "__main__":
    APP.detect_resource_directory()

    pixmap = QPixmap(':splash.png');
    splash_screen = QSplashScreen(pixmap)
    splash_screen.show()

    APP.process_command_line()
    APP.start_logging()
    APP.load_configuration()

    server = get_debug_server()
    if server != None:
        thread.start_new_thread(server.run, ())

    APP.run(splash_screen)

<commit_msg>license is not printed during import, only when running the game<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

#   Copyright 2010-2012 Tuukka Turto
#
#   This file is part of pyherc.
#
#   pyherc is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   pyherc is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with pyherc.  If not, see <http://www.gnu.org/licenses/>.

"""
Main entry point for Herculeum - game
"""
import sys
import os.path
import thread
import time

INSTALL_PATH = os.path.abspath(".")
sys.path.append(INSTALL_PATH)

from pyherc.debug import get_debug_server
from herculeum.application import APP
from PyQt4.QtGui import QPixmap, QSplashScreen
import herculeum.gui.resources

if __name__ == "__main__":

    print '#   pyherc is free software: you can redistribute it and/or modify'
    print '#   it under the terms of the GNU General Public License as published by'
    print '#   the Free Software Foundation, either version 3 of the License, or'
    print '#   (at your option) any later version.'
    print '#'
    print '#   pyherc is distributed in the hope that it will be useful,'
    print '#   but WITHOUT ANY WARRANTY; without even the implied warranty of'
    print '#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the'
    print '#   GNU General Public License for more details.'
    print '#'
    print '#   You should have received a copy of the GNU General Public License'
    print '#   along with pyherc.  If not, see <http://www.gnu.org/licenses/>.'

    APP.detect_resource_directory()

    pixmap = QPixmap(':splash.png');
    splash_screen = QSplashScreen(pixmap)
    splash_screen.show()

    APP.process_command_line()
    APP.start_logging()
    APP.load_configuration()

    server = get_debug_server()
    if server != None:
        thread.start_new_thread(server.run, ())

    APP.run(splash_screen)

<|endoftext|>


<commit_before>from project import app

def add_url_routes(routes_tuple):
    for route, view_function in routes_tuple:
        app.add_url_rule(route, view_function.__name__, view_function,
                methods=["GET", "POST"])

add_url_routes((
    ('/internal/call', twilio.call),
    ('/internal/text', twilio.text),
    ('/internal/rec', twilio.rec)
))
<commit_msg>Fix view import<commit_after>from project import app

from project.views import twilio

def add_url_routes(routes_tuple):
    for route, view_function in routes_tuple:
        app.add_url_rule(route, view_function.__name__, view_function,
                methods=["GET", "POST"])

add_url_routes((
    ('/internal/call', twilio.call),
    ('/internal/text', twilio.text),
    ('/internal/rec', twilio.rec)
))
<|endoftext|>