<commit_before>from django.test import TestCase
from django.db.models import (CharField, TextField,
                              BooleanField, ForeignKey,
                              SmallIntegerField)
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _

from deck.models import Event, Proposal, Vote, Jury
from test_utils import get_all_field_names

EVENT_DATA = {
    'title': 'RuPy',
    'slug': 'rupy',
    'description': 'A really good event.',
    'author_id': 1,
    'is_published': False,
    'slots': 30
}

PROPOSAL_DATA = {
    'title': 'Python For Zombies',
    'slug': 'python-for-zombies',
    'description': 'Brain...',
    'author_id': 1
}

ANOTHER_PROPOSAL_DATA = {
    'title': 'A Python 3 Metaprogramming Tutorial',
    'slug': 'python-3-metaprogramming',
    'description': 'An advanced tutorial on Python 3 and Metaprogramming',
    'author_id': 1
}

class EventModelIntegrityTest(TestCase):
    def setUp(self):
        self.fields = {
            field.name: field for field in Event._meta.fields
        }

    def test_assert_event_should_have_a_verbose_name(self):
        self.assertEquals(_('Event'), Event._meta.verbose_name)

    def test_assert_event_should_have_a_verbose_name_plural(self):
        self.assertEquals(_('Events'), Event._meta.verbose_name_plural)

    def test_assert_event_should_have_a_title(self):
        self.assertIn('title', get_all_field_names(Event))

    def test_assert_event_title_should_be_a_CharField(self):
        self.assertIsInstance(self.fields['title'], CharField)

    def test_assert_event_title_should_be_required(self):
        self.assertEquals(False, self.fields['title'].null)
        self.assertEquals(False, self.fields['title'].blank)

    def test_assert_event_title_should_have_at_most_200_characters(self):
        self.assertEquals(200, self.fields['title'].max_length)

    def test_assert_event_should_have_a_description(self):
        self.assertIn('description', get_all_field_names(Event))

    def test_assert_event_description_should_be_a_TextField(self):
        self.assertIsInstance(self.fields['description'], TextField)

    def test_assert_event_description_should_be_nullable_but_needs_to_be_blank(self):
        self.assertEquals(False, self.fields['description'].null)
        self.assertEquals(True, self.fields['description'].blank)

    def test_assert_event_description_should_have_at_most_10000_characters(self):
        self.assertEquals(10000, self.fields['description'].max_length)

    def test_assert_event_should_allow_public_voting(self):
        self.assertIn('allow_public_voting', get_all_field_names(Event))

    def test_assert_event_allow_public_voting_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['allow_public_voting'], BooleanField)

    def test_assert_event_allow_public_voting_should_be_True_as_default(self):
        self.assertEquals(True, self.fields['allow_public_voting'].default)

    def test_assert_event_should_have_a_author(self):
        self.assertIn('author', get_all_field_names(Event))

    def test_assert_event_author_should_be_an_User(self):
        self.assertEquals(User, self.fields['author'].rel.to)

    def test_assert_event_author_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['author'], ForeignKey)

    def test_assert_event_author_should_be_required(self):
        self.assertEquals(False, self.fields['author'].null)
        self.assertEquals(False, self.fields['author'].blank)

    def test_assert_event_author_should_have_a_related_name(self):
        self.assertEquals('events', self.fields['author'].rel.related_name)

    def test_assert_event_should_have_a_publish_flag(self):
        self.assertIn('is_published', get_all_field_names(Event))

    def test_assert_event_is_published_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['is_published'], BooleanField)

    def test_assert_event_is_published_should_be_True_as_default(self):
        self.assertEquals(True, self.fields['is_published'].default)

    def test_assert_event_should_have_a_jury(self):
        self.assertIn('jury', get_all_field_names(Event))

    def test_assert_event_jury_should_be_an_Jury(self):
        self.assertEquals(Jury, self.fields['jury'].rel.to)

    def test_assert_event_jury_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['jury'], ForeignKey)

    def test_assert_event_jury_should_not_be_required(self):
        self.assertEquals(True, self.fields['jury'].null)
        self.assertEquals(True, self.fields['jury'].blank)

    def test_assert_event_jury_should_have_a_related_name(self):
        self.assertEquals('event', self.fields['jury'].rel.related_name)

class EventObjectTest(TestCase):
    def setUp(self):
        self.event = Event(**EVENT_DATA)

    def test_assert_event_unicode_representation(self):
        self.assertEquals(u'RuPy', unicode(self.event))

    def test_assert_event_title(self):
        self.assertEquals(u'RuPy', self.event.title)

    def test_assert_event_description(self):
        self.assertEquals(u'A really good event.', self.event.description)

    def test_assert_event_author(self):
        self.assertEquals(1, self.event.author_id)

    def test_assert_event_allow_public_voting(self):
        self.assertEquals(True, self.event.allow_public_voting)

    def test_assert_event_is_published(self):
        self.assertEquals(False, self.event.is_published)

class ProposalModelIntegrityTest(TestCase):
    def setUp(self):
        self.fields = {
            field.name: field for field in Proposal._meta.fields
        }

    def test_assert_proposal_should_have_a_verbose_name(self):
        self.assertEquals(_('Proposal'), Proposal._meta.verbose_name)

    def test_assert_proposal_should_have_a_verbose_name_plural(self):
        self.assertEquals(_('Proposals'), Proposal._meta.verbose_name_plural)

    def test_assert_proposal_should_have_a_title(self):
        self.assertIn('title', get_all_field_names(Proposal))

    def test_assert_proposal_title_should_be_a_CharField(self):
        self.assertIsInstance(self.fields['title'], CharField)

    def test_assert_proposal_title_should_be_required(self):
        self.assertEquals(False, self.fields['title'].null)
        self.assertEquals(False, self.fields['title'].blank)

    def test_assert_proposal_title_should_have_at_most_200_characters(self):
        self.assertEquals(200, self.fields['title'].max_length)

    def test_assert_proposal_should_have_a_description(self):
        self.assertIn('description', get_all_field_names(Proposal))

    def test_assert_proposal_description_should_be_a_TextField(self):
        self.assertIsInstance(self.fields['description'], TextField)

    def test_assert_proposal_description_should_be_nullable_but_needs_to_be_blank(self):
        self.assertEquals(False, self.fields['description'].null)
        self.assertEquals(True, self.fields['description'].blank)

    def test_assert_proposal_description_should_have_10000_characters(self):
        self.assertEquals(10000, self.fields['description'].max_length)

    def test_assert_proposal_should_have_a_author(self):
        self.assertIn('author', get_all_field_names(Proposal))

    def test_assert_proposal_author_should_be_an_User(self):
        self.assertEquals(User, self.fields['author'].rel.to)

    def test_assert_proposal_author_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['author'], ForeignKey)

    def test_assert_proposal_author_should_be_required(self):
        self.assertEquals(False, self.fields['author'].null)
        self.assertEquals(False, self.fields['author'].blank)

    def test_assert_proposal_event_should_have_a_related_name(self):
        self.assertEquals('proposals', self.fields['event'].rel.related_name)

    def test_assert_proposal_should_have_a_event(self):
        self.assertIn('event', get_all_field_names(Proposal))

    def test_assert_proposal_event_should_be_an_Event(self):
        self.assertEquals(Event, self.fields['event'].rel.to)

    def test_assert_proposal_event_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['event'], ForeignKey)

    def test_assert_proposal_event_should_be_required(self):
        self.assertEquals(False, self.fields['event'].null)
        self.assertEquals(False, self.fields['event'].blank)

    def test_assert_proposal_should_have_a_publish_flag(self):
        self.assertIn('is_published', get_all_field_names(Proposal))

    def test_assert_proposal_is_published_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['is_published'], BooleanField)

    def test_assert_proposal_is_published_should_be_True_as_default(self):
        self.assertEquals(True, self.fields['is_published'].default)

    def test_assert_proposal_is_approved_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['is_approved'], BooleanField)

    def test_assert_proposal_is_approved_should_be_False_as_default(self):
        self.assertEquals(False, self.fields['is_approved'].default)

class ProposalObjectTest(TestCase):
    fixtures = ['user.json']

    def setUp(self):
        self.user = User.objects.first()
        self.event = Event(**EVENT_DATA)
        self.proposal = Proposal(**PROPOSAL_DATA)
        self.vote = Vote(user_id=self.event.author_id,
                         proposal=self.proposal, rate=3)

    def test_assert_proposal_unicode_representation(self):
        self.assertEquals(u'Python For Zombies', unicode(self.proposal))

    def test_assert_proposal_title(self):
        self.assertEquals(u'Python For Zombies', self.proposal.title)

    def test_assert_proposal_description(self):
        self.assertEquals(u'Brain...', self.proposal.description)

    def test_assert_proposal_author(self):
        self.assertEquals(1, self.proposal.author_id)

    def test_assert_proposal_rate(self):
        self.assertEquals(0, self.proposal.get_rate)

    def test_get_absolute_url(self):
        self.proposal.event = self.event
        self.assertEquals('/events/rupy/#python-for-zombies',
                          self.proposal.get_absolute_url())

    def test_assert_user_cannot_vote_multiple_times(self):
        self.event.save()
        self.proposal.event = self.event
        self.proposal.author = User.objects.get(id=2)
        self.proposal.save()
        self.vote.proposal = self.proposal
        self.vote.save()

        self.assertTrue(self.proposal.user_already_voted(self.user))

    def test_assert_proposal_is_published(self):
        self.assertEquals(True, self.proposal.is_published)

    def test_assert_proposal_approve(self):
        self.event.save()
        self.proposal.event = self.event
        self.proposal.save()

        self.assertEquals(False, self.proposal.is_approved)
        self.proposal.approve()
        self.assertEquals(True, self.proposal.is_approved)

    def test_assert_proposal_disapprove(self):
        self.event.save()
        self.proposal.event = self.event
        self.proposal.is_approved = True
        self.proposal.save()

        self.assertEquals(True, self.proposal.is_approved)
        self.proposal.disapprove()
        self.assertEquals(False, self.proposal.is_approved)

class VoteModelIntegrityTest(TestCase):
    def setUp(self):
        self.fields = {
            field.name: field for field in Vote._meta.fields
        }

    def test_assert_vote_should_have_a_verbose_name(self):
        self.assertEquals(_('Vote'), Vote._meta.verbose_name)

    def test_assert_vote_should_have_a_verbose_name_plural(self):
        self.assertEquals(_('Votes'), Vote._meta.verbose_name_plural)

    def test_assert_vote_should_have_a_unique_together_constraint(self):
        self.assertEquals((('proposal', 'user'),), Vote._meta.unique_together)

    def test_assert_vote_should_have_a_rate(self):
        self.assertIn('rate', get_all_field_names(Vote))

    def test_assert_vote_rate_should_be_a_SmallIntegerField(self):
        self.assertIsInstance(self.fields['rate'], SmallIntegerField)

    def test_assert_vote_rate_should_be_required(self):
        self.assertEquals(True, self.fields['rate'].null)
        self.assertEquals(True, self.fields['rate'].blank)

    def test_assert_vote_should_have_a_proposal(self):
        self.assertIn('proposal', get_all_field_names(Vote))

    def test_assert_vote_proposal_should_be_an_Proposal(self):
        self.assertEquals(Proposal, self.fields['proposal'].rel.to)

    def test_assert_vote_proposal_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['proposal'], ForeignKey)

    def test_assert_vote_proposal_should_be_required(self):
        self.assertEquals(False, self.fields['proposal'].null)
        self.assertEquals(False, self.fields['proposal'].blank)

    def test_assert_vote_proposal_should_have_a_related_name(self):
        self.assertEquals('votes', self.fields['proposal'].rel.related_name)

    def test_assert_vote_should_have_a_author(self):
        self.assertIn('user', get_all_field_names(Vote))

    def test_assert_vote_user_should_be_an_User(self):
        self.assertEquals(User, self.fields['user'].rel.to)

    def test_assert_vote_user_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['user'], ForeignKey)

    def test_assert_vote_user_should_be_required(self):
        self.assertEquals(False, self.fields['user'].null)
        self.assertEquals(False, self.fields['user'].blank)

    def test_assert_vote_event_should_have_a_related_name(self):
        self.assertEquals('votes', self.fields['user'].rel.related_name)

class VoteObjectTest(TestCase):
    def setUp(self):
        self.event = Event(**EVENT_DATA)
        self.proposal = Proposal(event=self.event, **PROPOSAL_DATA)
        self.vote = Vote(user_id=self.event.author_id,
                         proposal=self.proposal, rate=3)

    def test_assert_vote_unicode_representation(self):
        self.vote.user = User(username='User')
        self.assertEquals(u'User: 3 in Python For Zombies', unicode(self.vote))

    def test_assert_vote_rate(self):
        self.assertEquals(3, self.vote.rate)

    def test_assert_vote_proposal(self):
        self.assertEquals(self.proposal, self.vote.proposal)

    def test_assert_vote_author(self):
        self.assertEquals(1, self.vote.user_id)
<commit_msg>not test unicode on python3<commit_after>import unittest

from django.test import TestCase
from django.utils import six
from django.db.models import (CharField, TextField,
                              BooleanField, ForeignKey,
                              SmallIntegerField)
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _

from deck.models import Event, Proposal, Vote, Jury
from test_utils import get_all_field_names

EVENT_DATA = {
    'title': 'RuPy',
    'slug': 'rupy',
    'description': 'A really good event.',
    'author_id': 1,
    'is_published': False,
    'slots': 30
}

PROPOSAL_DATA = {
    'title': 'Python For Zombies',
    'slug': 'python-for-zombies',
    'description': 'Brain...',
    'author_id': 1
}

ANOTHER_PROPOSAL_DATA = {
    'title': 'A Python 3 Metaprogramming Tutorial',
    'slug': 'python-3-metaprogramming',
    'description': 'An advanced tutorial on Python 3 and Metaprogramming',
    'author_id': 1
}

class EventModelIntegrityTest(TestCase):
    def setUp(self):
        self.fields = {
            field.name: field for field in Event._meta.fields
        }

    def test_assert_event_should_have_a_verbose_name(self):
        self.assertEquals(_('Event'), Event._meta.verbose_name)

    def test_assert_event_should_have_a_verbose_name_plural(self):
        self.assertEquals(_('Events'), Event._meta.verbose_name_plural)

    def test_assert_event_should_have_a_title(self):
        self.assertIn('title', get_all_field_names(Event))

    def test_assert_event_title_should_be_a_CharField(self):
        self.assertIsInstance(self.fields['title'], CharField)

    def test_assert_event_title_should_be_required(self):
        self.assertEquals(False, self.fields['title'].null)
        self.assertEquals(False, self.fields['title'].blank)

    def test_assert_event_title_should_have_at_most_200_characters(self):
        self.assertEquals(200, self.fields['title'].max_length)

    def test_assert_event_should_have_a_description(self):
        self.assertIn('description', get_all_field_names(Event))

    def test_assert_event_description_should_be_a_TextField(self):
        self.assertIsInstance(self.fields['description'], TextField)

    def test_assert_event_description_should_be_nullable_but_needs_to_be_blank(self):
        self.assertEquals(False, self.fields['description'].null)
        self.assertEquals(True, self.fields['description'].blank)

    def test_assert_event_description_should_have_at_most_10000_characters(self):
        self.assertEquals(10000, self.fields['description'].max_length)

    def test_assert_event_should_allow_public_voting(self):
        self.assertIn('allow_public_voting', get_all_field_names(Event))

    def test_assert_event_allow_public_voting_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['allow_public_voting'], BooleanField)

    def test_assert_event_allow_public_voting_should_be_True_as_default(self):
        self.assertEquals(True, self.fields['allow_public_voting'].default)

    def test_assert_event_should_have_a_author(self):
        self.assertIn('author', get_all_field_names(Event))

    def test_assert_event_author_should_be_an_User(self):
        self.assertEquals(User, self.fields['author'].rel.to)

    def test_assert_event_author_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['author'], ForeignKey)

    def test_assert_event_author_should_be_required(self):
        self.assertEquals(False, self.fields['author'].null)
        self.assertEquals(False, self.fields['author'].blank)

    def test_assert_event_author_should_have_a_related_name(self):
        self.assertEquals('events', self.fields['author'].rel.related_name)

    def test_assert_event_should_have_a_publish_flag(self):
        self.assertIn('is_published', get_all_field_names(Event))

    def test_assert_event_is_published_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['is_published'], BooleanField)

    def test_assert_event_is_published_should_be_True_as_default(self):
        self.assertEquals(True, self.fields['is_published'].default)

    def test_assert_event_should_have_a_jury(self):
        self.assertIn('jury', get_all_field_names(Event))

    def test_assert_event_jury_should_be_an_Jury(self):
        self.assertEquals(Jury, self.fields['jury'].rel.to)

    def test_assert_event_jury_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['jury'], ForeignKey)

    def test_assert_event_jury_should_not_be_required(self):
        self.assertEquals(True, self.fields['jury'].null)
        self.assertEquals(True, self.fields['jury'].blank)

    def test_assert_event_jury_should_have_a_related_name(self):
        self.assertEquals('event', self.fields['jury'].rel.related_name)

class EventObjectTest(TestCase):
    def setUp(self):
        self.event = Event(**EVENT_DATA)

    @unittest.skipIf(six.PY3, 'not test unicode on python3')
    def test_assert_event_unicode_representation(self):
        self.assertEquals(u'RuPy', six.text_type(self.event))

    def test_assert_event_title(self):
        self.assertEquals(u'RuPy', self.event.title)

    def test_assert_event_description(self):
        self.assertEquals(u'A really good event.', self.event.description)

    def test_assert_event_author(self):
        self.assertEquals(1, self.event.author_id)

    def test_assert_event_allow_public_voting(self):
        self.assertEquals(True, self.event.allow_public_voting)

    def test_assert_event_is_published(self):
        self.assertEquals(False, self.event.is_published)

class ProposalModelIntegrityTest(TestCase):
    def setUp(self):
        self.fields = {
            field.name: field for field in Proposal._meta.fields
        }

    def test_assert_proposal_should_have_a_verbose_name(self):
        self.assertEquals(_('Proposal'), Proposal._meta.verbose_name)

    def test_assert_proposal_should_have_a_verbose_name_plural(self):
        self.assertEquals(_('Proposals'), Proposal._meta.verbose_name_plural)

    def test_assert_proposal_should_have_a_title(self):
        self.assertIn('title', get_all_field_names(Proposal))

    def test_assert_proposal_title_should_be_a_CharField(self):
        self.assertIsInstance(self.fields['title'], CharField)

    def test_assert_proposal_title_should_be_required(self):
        self.assertEquals(False, self.fields['title'].null)
        self.assertEquals(False, self.fields['title'].blank)

    def test_assert_proposal_title_should_have_at_most_200_characters(self):
        self.assertEquals(200, self.fields['title'].max_length)

    def test_assert_proposal_should_have_a_description(self):
        self.assertIn('description', get_all_field_names(Proposal))

    def test_assert_proposal_description_should_be_a_TextField(self):
        self.assertIsInstance(self.fields['description'], TextField)

    def test_assert_proposal_description_should_be_nullable_but_needs_to_be_blank(self):
        self.assertEquals(False, self.fields['description'].null)
        self.assertEquals(True, self.fields['description'].blank)

    def test_assert_proposal_description_should_have_10000_characters(self):
        self.assertEquals(10000, self.fields['description'].max_length)

    def test_assert_proposal_should_have_a_author(self):
        self.assertIn('author', get_all_field_names(Proposal))

    def test_assert_proposal_author_should_be_an_User(self):
        self.assertEquals(User, self.fields['author'].rel.to)

    def test_assert_proposal_author_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['author'], ForeignKey)

    def test_assert_proposal_author_should_be_required(self):
        self.assertEquals(False, self.fields['author'].null)
        self.assertEquals(False, self.fields['author'].blank)

    def test_assert_proposal_event_should_have_a_related_name(self):
        self.assertEquals('proposals', self.fields['event'].rel.related_name)

    def test_assert_proposal_should_have_a_event(self):
        self.assertIn('event', get_all_field_names(Proposal))

    def test_assert_proposal_event_should_be_an_Event(self):
        self.assertEquals(Event, self.fields['event'].rel.to)

    def test_assert_proposal_event_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['event'], ForeignKey)

    def test_assert_proposal_event_should_be_required(self):
        self.assertEquals(False, self.fields['event'].null)
        self.assertEquals(False, self.fields['event'].blank)

    def test_assert_proposal_should_have_a_publish_flag(self):
        self.assertIn('is_published', get_all_field_names(Proposal))

    def test_assert_proposal_is_published_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['is_published'], BooleanField)

    def test_assert_proposal_is_published_should_be_True_as_default(self):
        self.assertEquals(True, self.fields['is_published'].default)

    def test_assert_proposal_is_approved_should_be_a_BooleanField(self):
        self.assertIsInstance(self.fields['is_approved'], BooleanField)

    def test_assert_proposal_is_approved_should_be_False_as_default(self):
        self.assertEquals(False, self.fields['is_approved'].default)

class ProposalObjectTest(TestCase):
    fixtures = ['user.json']

    def setUp(self):
        self.user = User.objects.first()
        self.event = Event(**EVENT_DATA)
        self.proposal = Proposal(**PROPOSAL_DATA)
        self.vote = Vote(user_id=self.event.author_id,
                         proposal=self.proposal, rate=3)

    @unittest.skipIf(six.PY3, 'not test unicode on python3')
    def test_assert_proposal_unicode_representation(self):
        self.assertEquals(u'Python For Zombies', six.text_type(self.proposal))

    def test_assert_proposal_title(self):
        self.assertEquals(u'Python For Zombies', self.proposal.title)

    def test_assert_proposal_description(self):
        self.assertEquals(u'Brain...', self.proposal.description)

    def test_assert_proposal_author(self):
        self.assertEquals(1, self.proposal.author_id)

    def test_assert_proposal_rate(self):
        self.assertEquals(0, self.proposal.get_rate)

    def test_get_absolute_url(self):
        self.proposal.event = self.event
        self.assertEquals('/events/rupy/#python-for-zombies',
                          self.proposal.get_absolute_url())

    def test_assert_user_cannot_vote_multiple_times(self):
        self.event.save()
        self.proposal.event = self.event
        self.proposal.author = User.objects.get(id=2)
        self.proposal.save()
        self.vote.proposal = self.proposal
        self.vote.save()

        self.assertTrue(self.proposal.user_already_voted(self.user))

    def test_assert_proposal_is_published(self):
        self.assertEquals(True, self.proposal.is_published)

    def test_assert_proposal_approve(self):
        self.event.save()
        self.proposal.event = self.event
        self.proposal.save()

        self.assertEquals(False, self.proposal.is_approved)
        self.proposal.approve()
        self.assertEquals(True, self.proposal.is_approved)

    def test_assert_proposal_disapprove(self):
        self.event.save()
        self.proposal.event = self.event
        self.proposal.is_approved = True
        self.proposal.save()

        self.assertEquals(True, self.proposal.is_approved)
        self.proposal.disapprove()
        self.assertEquals(False, self.proposal.is_approved)

class VoteModelIntegrityTest(TestCase):
    def setUp(self):
        self.fields = {
            field.name: field for field in Vote._meta.fields
        }

    def test_assert_vote_should_have_a_verbose_name(self):
        self.assertEquals(_('Vote'), Vote._meta.verbose_name)

    def test_assert_vote_should_have_a_verbose_name_plural(self):
        self.assertEquals(_('Votes'), Vote._meta.verbose_name_plural)

    def test_assert_vote_should_have_a_unique_together_constraint(self):
        self.assertEquals((('proposal', 'user'),), Vote._meta.unique_together)

    def test_assert_vote_should_have_a_rate(self):
        self.assertIn('rate', get_all_field_names(Vote))

    def test_assert_vote_rate_should_be_a_SmallIntegerField(self):
        self.assertIsInstance(self.fields['rate'], SmallIntegerField)

    def test_assert_vote_rate_should_be_required(self):
        self.assertEquals(True, self.fields['rate'].null)
        self.assertEquals(True, self.fields['rate'].blank)

    def test_assert_vote_should_have_a_proposal(self):
        self.assertIn('proposal', get_all_field_names(Vote))

    def test_assert_vote_proposal_should_be_an_Proposal(self):
        self.assertEquals(Proposal, self.fields['proposal'].rel.to)

    def test_assert_vote_proposal_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['proposal'], ForeignKey)

    def test_assert_vote_proposal_should_be_required(self):
        self.assertEquals(False, self.fields['proposal'].null)
        self.assertEquals(False, self.fields['proposal'].blank)

    def test_assert_vote_proposal_should_have_a_related_name(self):
        self.assertEquals('votes', self.fields['proposal'].rel.related_name)

    def test_assert_vote_should_have_a_author(self):
        self.assertIn('user', get_all_field_names(Vote))

    def test_assert_vote_user_should_be_an_User(self):
        self.assertEquals(User, self.fields['user'].rel.to)

    def test_assert_vote_user_should_be_a_ForeignKey(self):
        self.assertIsInstance(self.fields['user'], ForeignKey)

    def test_assert_vote_user_should_be_required(self):
        self.assertEquals(False, self.fields['user'].null)
        self.assertEquals(False, self.fields['user'].blank)

    def test_assert_vote_event_should_have_a_related_name(self):
        self.assertEquals('votes', self.fields['user'].rel.related_name)

class VoteObjectTest(TestCase):
    def setUp(self):
        self.event = Event(**EVENT_DATA)
        self.proposal = Proposal(event=self.event, **PROPOSAL_DATA)
        self.vote = Vote(user_id=self.event.author_id,
                         proposal=self.proposal, rate=3)

    @unittest.skipIf(six.PY3, 'not test unicode on python3')
    def test_assert_vote_unicode_representation(self):
        self.vote.user = User(username='User')
        self.assertEquals(u'User: 3 in Python For Zombies', six.text_type(self.vote))

    def test_assert_vote_rate(self):
        self.assertEquals(3, self.vote.rate)

    def test_assert_vote_proposal(self):
        self.assertEquals(self.proposal, self.vote.proposal)

    def test_assert_vote_author(self):
        self.assertEquals(1, self.vote.user_id)
<|endoftext|>


<commit_before>import markdown

from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask import Markup
from flask.ext.login import current_user

from application import db
from application.page.models import Page, PageRevision

page_module = Blueprint('page', __name__)

@page_module.route('/page/')
@page_module.route('/page/<path:page_path>')
def view_page(page_path=''):
	revision = retrieve_page(page_path)

	if not revision:
		return render_template('page/page_not_found.htm', page=page_path)

	return render_template('page/view_page.htm', revision=revision, page=page_path)

def retrieve_page(page_path=''):
	page = Page.query.filter(Page.path==page_path).first()

	if not page:
		return False

	revision = PageRevision.query.filter(PageRevision.page_id==page.id).order_by(
		PageRevision.id.desc()).first()

	revision.content = Markup(markdown.markdown(revision.content,
		safe_mode='escape', enable_attributes=False))

	return revision

@page_module.route('/page/delete/<path:page_path>')
def delete_page(page_path='', revision=''):
	page = Page.query.filter(Page.path==page_path).first()
	db.session.delete(page)

	db.session.commit()

	return redirect('/')

@page_module.route('/page/edit/', methods=['GET', 'POST'])
@page_module.route('/page/edit/<path:page_path>', methods=['GET', 'POST'])
def edit_page(page_path=''):
	page = Page.query.filter(Page.path==page_path).first()
	revision = None

	if page:
		revision = PageRevision.query.filter(PageRevision.page_id==page.id).order_by(
			PageRevision.id.desc()).first()

	if request.method == 'POST':
		title = request.form['title'].strip()
		content = request.form['content'].strip()

		if not page:
			page = Page(page_path)

			db.session.add(page)
			db.session.commit()

		revision = PageRevision(page, current_user, title, content)

		db.session.add(revision)
		db.session.commit()

		flash('The page has been saved.', 'success')

		return redirect(url_for('page.view_page', page_path=page_path))

	return render_template('page/edit_page.htm', revision=revision, page=page_path)

<commit_msg>another try<commit_after>import markdown

from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask import Markup
from flask.ext.login import current_user

from application import db
from application.page.models import Page, PageRevision

page_module = Blueprint('page', __name__)

@page_module.route('/page/')
@page_module.route('/page/<path:page_path>')
def view_page(page_path=''):
	revision = retrieve_page(page_path)

	if not revision:
		return render_template('page/page_not_found.htm', page=page_path)

	return render_template('page/view_page.htm', revision=revision, page=page_path)

def retrieve_page(page_path=''):
	page = Page.query.filter(Page.path==page_path).first()

	if not page:
		return False

	revision = PageRevision.query.filter(PageRevision.page_id==page.id).order_by(
		PageRevision.id.desc()).first()

	revision.content = Markup(markdown.markdown(revision.content,
		safe_mode='escape', enable_attributes=False))

	return revision

@page_module.route('/page/delete/<path:page_path>')
def delete_page(page_path='', revision=''):
	page = Page.query.filter(Page.path==page_path).first()
	db.session.delete(page)
	db.session.commit()
	return redirect('/')

@page_module.route('/page/edit/', methods=['GET', 'POST'])
@page_module.route('/page/edit/<path:page_path>', methods=['GET', 'POST'])
def edit_page(page_path=''):
	page = Page.query.filter(Page.path==page_path).first()
	revision = None

	if page:
		revision = PageRevision.query.filter(PageRevision.page_id==page.id).order_by(
			PageRevision.id.desc()).first()

	if request.method == 'POST':
		title = request.form['title'].strip()
		content = request.form['content'].strip()

		if not page:
			page = Page(page_path)

			db.session.add(page)
			db.session.commit()

		revision = PageRevision(page, current_user, title, content)

		db.session.add(revision)
		db.session.commit()

		flash('The page has been saved.', 'success')

		return redirect(url_for('page.view_page', page_path=page_path))

	return render_template('page/edit_page.htm', revision=revision, page=page_path)

<|endoftext|>


<commit_before>from multiprocessing import Array, Value, Queue
import cPickle as pickle
import sys

class Messenger(object):
  """
    Manages messaging between local processes

    NOTE: Logging cannot be used here because the logging system relies on
    Messenger.
    NOTE: Messenger is intended to be used by the main process only.
  """

  class Queues(object):
    """
      Enum for messenger queues
    """
    uavStatus = 'uavStatus'
    toBelief = 'toBelief'
    fromRadio = 'fromRadio'
    logging = 'logging'

  class Mailbox(object):
    """
      A lock-protected bit of shared state that can be used to send a single
      value between processes. Thanks to Pickle, it can store pretty much
      anything.
    """

    # The size of the array that stores data.
    _SIZE = 1024

    def __init__(self, name):
      # Where we write the element.
      self.__state = Array('c', self._SIZE)
      # Whether the slot is in use. If it's not, it's zero, otherwise it's the
      # length of whatever's in it.
      self.__used = Value('i', 0)

    def __clear_queue(self):
      if not self.__used.value:
        return

      self.__used.value = 0

    def set(self, obj):
      if self.__used.value:
        self.__clear_queue()

      # Pickle the data and write it in.
      pickled = pickle.dumps(obj)
      if len(pickled) > self._SIZE:
        print "Object of size %d exceeds maximum size of %d!" % \
              (len(pickled), self._SIZE)
        sys.exit(1)

      self.__state.value = pickled
      self.__used.value = len(pickled)

    def get(self):
      if not self.__used.value:
        return None

      # Get the pickled item.
      pickled = self.__state.value
      pickled = pickled[:self.__used.value]
      self.__used.value = 0

      return pickle.loads(pickled)

  def __init__(self):
    self._queue_map = {}
    # Set up lockable data structures for local belief generation
    self._queue_map[self.Queues.uavStatus] = self.Mailbox(self.Queues.uavStatus)
    self._queue_map[self.Queues.toBelief] = self.Mailbox(self.Queues.toBelief)
    self._queue_map[self.Queues.fromRadio] = self.Mailbox(self.Queues.fromRadio)

    self._queue_map[self.Queues.logging] = Queue()

  def get_queue(self, queue_name):
    return self._queue_map[queue_name]
<commit_msg>Make uavStatus and radioStatus queues.<commit_after>from multiprocessing import Array, Queue, Value
import cPickle as pickle
import sys

class Messenger(object):
  """
    Manages messaging between local processes

    NOTE: Logging cannot be used here because the logging system relies on
    Messenger.
    NOTE: Messenger is intended to be used by the main process only.
  """

  class Queues(object):
    """
      Enum for messenger queues
    """
    uavStatus = 'uavStatus'
    toBelief = 'toBelief'
    fromRadio = 'fromRadio'
    logging = 'logging'

  class Mailbox(object):
    """
      A lock-protected bit of shared state that can be used to send a single
      value between processes. Thanks to Pickle, it can store pretty much
      anything.
    """

    # The size of the array that stores data.
    _SIZE = 1024

    def __init__(self, name):
      # Where we write the element.
      self.__state = Array('c', self._SIZE)
      # Whether the slot is in use. If it's not, it's zero, otherwise it's the
      # length of whatever's in it.
      self.__used = Value('i', 0)

    def __clear_queue(self):
      if not self.__used.value:
        return

      self.__used.value = 0

    def set(self, obj):
      if self.__used.value:
        self.__clear_queue()

      # Pickle the data and write it in.
      pickled = pickle.dumps(obj)
      if len(pickled) > self._SIZE:
        print "Object of size %d exceeds maximum size of %d!" % \
              (len(pickled), self._SIZE)
        sys.exit(1)

      self.__state.value = pickled
      self.__used.value = len(pickled)

    def get(self):
      if not self.__used.value:
        return None

      # Get the pickled item.
      pickled = self.__state.value
      pickled = pickled[:self.__used.value]
      self.__used.value = 0

      return pickle.loads(pickled)

  def __init__(self):
    self._queue_map = {}
    # Set up lockable data structures for local belief generation
    self._queue_map[self.Queues.uavStatus] = Queue()
    self._queue_map[self.Queues.toBelief] = self.Mailbox(self.Queues.toBelief)
    self._queue_map[self.Queues.fromRadio] = Queue()

    self._queue_map[self.Queues.logging] = Queue()

  def get_queue(self, queue_name):
    return self._queue_map[queue_name]
<|endoftext|>


<commit_before>#-------------------------------------------------------------------------------
#
#  Copyright (c) 2013, Enthought, Inc.
#  All rights reserved.
#
#  This software is provided without warranty under the terms of the BSD
#  license included in /LICENSE.txt and may be redistributed only
#  under the conditions described in the aforementioned license.  The license
#  is also available online at http://www.enthought.com/licenses/BSD.txt
#
#  Thanks for using Enthought open source!
#
#-------------------------------------------------------------------------------

from __future__ import absolute_import

import unittest

from ..trait_types import Int
from ..has_traits import HasTraits

class Foo(HasTraits):

    bar = Int

    def _bar_default(self):
        return 4

class DefaultMethodTestCase(unittest.TestCase):
    """ Test basic usage of the default trait value behaviour.

    """

    def test_default_value(self):
        foo = Foo()
        self.assertEqual(foo.bar, 4)

    def test_default_value_override(self):
        foo = Foo(bar=3)
        self.assertEqual(foo.bar, 3)

    def test_reset_to_default(self):
        foo = Foo(bar=3)
        foo.reset_traits(traits=['bar'])
        self.assertEqual(foo.bar, 4)

    def test_error_propagation_in_default_methods(self):

        class FooException(Foo):

            def _bar_default(self):
                1 / 0

        foo = FooException()
        with self.assertRaises(ZeroDivisionError):
            foo.bar

        class FooKeyError(Foo):

            def _bar_default(self):
                raise KeyError

        # Check that KeyError is propagated (issue #70).
        foo = FooKeyError()
        with self.assertRaises(KeyError):
            foo.bar
<commit_msg>minor cleanup<commit_after>#-------------------------------------------------------------------------------
#
#  Copyright (c) 2013, Enthought, Inc.
#  All rights reserved.
#
#  This software is provided without warranty under the terms of the BSD
#  license included in /LICENSE.txt and may be redistributed only
#  under the conditions described in the aforementioned license.  The license
#  is also available online at http://www.enthought.com/licenses/BSD.txt
#
#  Thanks for using Enthought open source!
#
#-------------------------------------------------------------------------------

from __future__ import absolute_import

import unittest

from ..trait_types import Int
from ..has_traits import HasTraits

class Foo(HasTraits):

    bar = Int

    def _bar_default(self):
        return 4

class DefaultMethodTestCase(unittest.TestCase):
    """ Test basic usage of the default trait value behaviour.

    """

    def test_default_value(self):
        foo = Foo()
        self.assertEqual(foo.bar, 4)

    def test_default_value_override(self):
        foo = Foo(bar=3)
        self.assertEqual(foo.bar, 3)

    def test_reset_to_default(self):
        foo = Foo(bar=3)
        foo.reset_traits(traits=['bar'])
        self.assertEqual(foo.bar, 4)

    def test_error_propagation_in_default_methods(self):

        class FooException(Foo):

            def _bar_default(self):
                1 / 0

        foo = FooException()
        with self.assertRaises(ZeroDivisionError):
            foo.bar

        class FooKeyError(Foo):

            def _bar_default(self):
                raise KeyError()

        # Check that KeyError is propagated (issue #70).
        foo = FooKeyError()
        with self.assertRaises(KeyError):
            foo.bar
<|endoftext|>


<commit_before>from collections import namedtuple
from optparse import OptionParser

import requests
from lxml import etree
from fabric.api import run

from perfrunner.logger import logger
from perfrunner.utils.remote import RemoteHelper, all_hosts

Build = namedtuple('Build', ['arch', 'pkg', 'version', 'toy'])

class BuildIterator(object):

    BUILDS_URL = 'http://builds.hq.northscale.net/latestbuilds/'

    def __init__(self):
        pass

    @classmethod
    def _parse_build_tree(cls):
        logger.info('Getting list of builds')
        try:
            headers = {'Accept-Encoding': 'gzip, deflate'}
            html = requests.get(url=cls.BUILDS_URL, headers=headers).text
        except requests.exceptions.ConnectionError:
            logger.interrupt('Could not connect to build repository')
        return etree.HTML(html)

    def __iter__(self):
        tree = self._parse_build_tree()
        for li in tree.xpath('/html/body/ul/li'):
            yield li.xpath('a/@href')[0]

class CouchbaseInstaller(RemoteHelper):

    @staticmethod
    def _get_expected_filename(build):
        if build.toy:
            return 'couchbase-server-community_toy-{0}-{1}_{2}-toy.{3}'.format(
                build.toy, build.arch, build.version, build.pkg
            )
        else:
            return 'couchbase-server-enterprise_{0}_{1}-rel.{2}'.format(
                build.arch, build.version, build.pkg
            )

    @staticmethod
    def _check_if_exists(target):
        for filename, url in BuildIterator():
            if filename == target:
                logger.info('Found "{0}"'.format(filename))
        logger.interrupt('Target build not found')

    @all_hosts
    def _uninstall_package(self, pkg):
        if pkg == 'deb':
            run('yes | apt-get remove couchbase-server')
        else:
            run('yes | yum remove couchbase-server')
        run('rm -fr /opt/couchbase')

    @all_hosts
    def _install_package(self, pkg, filename):
        url = BuildIterator.BUILDS_URL + filename
        self.wget(url, outdir='/tmp')

        if pkg == 'deb':
            run('yes | apt-get install gdebi')
            run('yes | gdebi /tmp/{0}'.format(filename))
        else:
            run('yes | rpm -i /tmp/{0}'.format(filename))

    def install(self, options):
        arch = self.detect_arch()
        pkg = self.detect_pkg()
        build = Build(arch, pkg, options.version, options.toy)

        filename = self._get_expected_filename(build)
        self._check_if_exists(filename)

        self._uninstall_package(pkg)
        self._install_package(pkg, filename)

def main():
    usage = '%prog -c cluster -v version [-t toy]'

    parser = OptionParser(usage)

    parser.add_option('-c', dest='cluster',
                      help='path to cluster specification file',
                      metavar='cluster.spec')
    parser.add_option('-v', dest='version',
                      help='build version', metavar='2.0.0-1976')
    parser.add_option('-t', dest='toy',
                      help='optional toy build ID', metavar='couchstore')

    options, _ = parser.parse_args()
    if not options.cluster or not options.version:
        parser.error('Missing mandatory parameter')

    installer = CouchbaseInstaller(options.cluster)
    installer.install(options)

if __name__ == '__main__':
    main()
<commit_msg>fix package checker<commit_after>from collections import namedtuple
from optparse import OptionParser

import requests
from lxml import etree
from fabric.api import run

from perfrunner.logger import logger
from perfrunner.utils.remote import RemoteHelper, all_hosts

Build = namedtuple('Build', ['arch', 'pkg', 'version', 'toy'])

class BuildIterator(object):

    BUILDS_URL = 'http://builds.hq.northscale.net/latestbuilds/'

    def __init__(self):
        pass

    @classmethod
    def _parse_build_tree(cls):
        logger.info('Getting list of builds')
        try:
            headers = {'Accept-Encoding': 'gzip, deflate'}
            html = requests.get(url=cls.BUILDS_URL, headers=headers).text
        except requests.exceptions.ConnectionError:
            logger.interrupt('Could not connect to build repository')
        return etree.HTML(html)

    def __iter__(self):
        tree = self._parse_build_tree()
        for li in tree.xpath('/html/body/ul/li'):
            yield li.xpath('a/@href')[0]

class CouchbaseInstaller(RemoteHelper):

    @staticmethod
    def _get_expected_filename(build):
        if build.toy:
            return 'couchbase-server-community_toy-{0}-{1}_{2}-toy.{3}'.format(
                build.toy, build.arch, build.version, build.pkg
            )
        else:
            return 'couchbase-server-enterprise_{0}_{1}-rel.{2}'.format(
                build.arch, build.version, build.pkg
            )

    @staticmethod
    def _check_if_exists(target):
        for filename in BuildIterator():
            if filename == target:
                logger.info('Found "{0}"'.format(filename))
                break
        else:
            logger.interrupt('Target build not found')

    @all_hosts
    def _uninstall_package(self, pkg):
        if pkg == 'deb':
            run('yes | apt-get remove couchbase-server')
        else:
            run('yes | yum remove couchbase-server')
        run('rm -fr /opt/couchbase')

    @all_hosts
    def _install_package(self, pkg, filename):
        url = BuildIterator.BUILDS_URL + filename
        self.wget(url, outdir='/tmp')

        if pkg == 'deb':
            run('yes | apt-get install gdebi')
            run('yes | gdebi /tmp/{0}'.format(filename))
        else:
            run('yes | rpm -i /tmp/{0}'.format(filename))

    def install(self, options):
        arch = self.detect_arch()
        pkg = self.detect_pkg()
        build = Build(arch, pkg, options.version, options.toy)

        filename = self._get_expected_filename(build)
        self._check_if_exists(filename)

        self._uninstall_package(pkg)
        self._install_package(pkg, filename)

def main():
    usage = '%prog -c cluster -v version [-t toy]'

    parser = OptionParser(usage)

    parser.add_option('-c', dest='cluster',
                      help='path to cluster specification file',
                      metavar='cluster.spec')
    parser.add_option('-v', dest='version',
                      help='build version', metavar='2.0.0-1976')
    parser.add_option('-t', dest='toy',
                      help='optional toy build ID', metavar='couchstore')

    options, _ = parser.parse_args()
    if not options.cluster or not options.version:
        parser.error('Missing mandatory parameter')

    installer = CouchbaseInstaller(options.cluster)
    installer.install(options)

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#  Copyright 2011 Takeshi KOMIYA
#
#  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.

try:
    from PIL import Image
    from PIL import ImageDraw
    from PIL import ImageFont
except ImportError:
    import Image
    import ImageDraw
    import ImageFont
import base
from fontmap import parse_fontpath, FontMap

class TextFolder(base.TextFolder):
    def __init__(self, box, string, font, **kwargs):
        if font.path:
            path, index = parse_fontpath(font.path)
            if index:
                self.ttfont = ImageFont.truetype(path, font.size, index=index)
            else:
                self.ttfont = ImageFont.truetype(path, font.size)
        else:
            self.ttfont = None

        image = Image.new('1', (1, 1))
        self.draw = ImageDraw.Draw(image)
        self.fontsize = font.size

        super(PILTextFolder, self).__init__(box, string, font, **kwargs)

    def textsize(self, string):
        if self.ttfont is None:
            size = self.draw.textsize(string, font=self.ttfont)

            font_ratio = self.fontsize * 1.0 / FontMap.BASE_FONTSIZE
            size = (int(size[0] * font_ratio), int(size[1] * font_ratio))
        else:
            size = self.draw.textsize(string, font=self.ttfont)

        return size
<commit_msg>Fix importing error<commit_after># -*- coding: utf-8 -*-
#  Copyright 2011 Takeshi KOMIYA
#
#  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.

try:
    from PIL import Image
    from PIL import ImageDraw
    from PIL import ImageFont
except ImportError:
    import Image
    import ImageDraw
    import ImageFont
import base
from blockdiag.utils.fontmap import parse_fontpath, FontMap

class TextFolder(base.TextFolder):
    def __init__(self, box, string, font, **kwargs):
        if font.path:
            path, index = parse_fontpath(font.path)
            if index:
                self.ttfont = ImageFont.truetype(path, font.size, index=index)
            else:
                self.ttfont = ImageFont.truetype(path, font.size)
        else:
            self.ttfont = None

        image = Image.new('1', (1, 1))
        self.draw = ImageDraw.Draw(image)
        self.fontsize = font.size

        super(PILTextFolder, self).__init__(box, string, font, **kwargs)

    def textsize(self, string):
        if self.ttfont is None:
            size = self.draw.textsize(string, font=self.ttfont)

            font_ratio = self.fontsize * 1.0 / FontMap.BASE_FONTSIZE
            size = (int(size[0] * font_ratio), int(size[1] * font_ratio))
        else:
            size = self.draw.textsize(string, font=self.ttfont)

        return size
<|endoftext|>


<commit_before>from charter.models import DataRow

from urllib import quote
from urlparse import urlunparse

_cht = dict({
    'pie': 'p',
})

def get_graph_url(dataset,cht='p3'):
    api = "http://chart.apis.google.com/chart?"
    data = dict()
    data['cht'] = cht
    data['chs'] = '600x480'
    chd = []
    chl = []
    for data_item in dataset.data_rows:
        row = DataRow.get(data_item)
        chd.append(row.data_value)
        chl.append(row.data_key)
    data['chd'] = 't:' + ','.join(chd)
    data['chl'] = '|'.join(chl)
    query = '&'.join([k+'='+quote(str(v)) for (k,v) in data.items()])
    return urlunparse((
        'http',
        'chart.apis.google.com',
        '/chart',
        '',
        query,
        ''
    ))
<commit_msg>use real numbers 0-100 for pie charts<commit_after>from charter.models import DataRow

from urllib import quote
from urlparse import urlunparse

_cht = dict({
    'pie': 'p3',
})

def get_graph_url(dataset,cht='p3'):
    api = "http://chart.apis.google.com/chart?"
    data = dict()
    data['cht'] = cht
    data['chs'] = '600x480'
    values = []
    chl = []
    chd = []
    summation = 0
    for data_item in dataset.data_rows:
        row = DataRow.get(data_item)
        values.append(float(row.data_value))
        chl.append(row.data_key)
    for value in values:
        summation += value
    for value in values:
        chd.append(str(value/summation))
    data['chd'] = 't:' + ','.join(chd)
    data['chl'] = '|'.join(chl)
    query = '&'.join([k+'='+quote(str(v)) for (k,v) in data.items()])
    return urlunparse((
        'http',
        'chart.apis.google.com',
        '/chart',
        '',
        query,
        ''
    ))
<|endoftext|>


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

"""
Copyright 2016 Fedele Mantuano (https://twitter.com/fedelemantuano)

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.
"""

__version__ = "3.0.0"

if __name__ == "__main__":
    print(__version__)
<commit_msg>New minor version<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Copyright 2016 Fedele Mantuano (https://twitter.com/fedelemantuano)

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.
"""

__version__ = "3.0.1"

if __name__ == "__main__":
    print(__version__)
<|endoftext|>


<commit_before><commit_msg>Placeholders for prod email settings.<commit_after>
EMAIL_HOST = ''
EMAIL_PORT = ''
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = ''
EMAIL_USE_SSL = ''
<|endoftext|>


<commit_before>#!/usr/bin/python
# (c) 2017 Jim Hawkins. MIT licensed, see https://opensource.org/licenses/MIT
# Part of Blender Driver, see https://github.com/sjjhsjjh/blender-driver
"""Python module for Blender Driver demonstration application.

This code illustrates:

-   Basic use of the Blender Game Engine (BGE) KX_GameObject interface, to
    change the size of a game object.
-   Termination of BGE when any key is pressed.
-   Spawning a single thread at the start of BGE execution. The thread is
    joined before terminating BGE.
-   Use of a thread lock to indicate termination is due.

This application doesn't override the Blender Driver game_tick, which is then a
pass in the base class.

This module can only be used from within the Blender Game Engine."""
# Exit if run other than as a module.
if __name__ == '__main__':
    print(__doc__)
    raise SystemExit(1)

# Standard library imports, in alphabetic order.
#
# Module for command line switches.
# https://docs.python.org/3.5/library/argparse.html
# The import isn't needed because this class uses the base class to get an
# object.
# import argparse
#
# This module uses the Thread class.
# https://docs.python.org/3.4/library/threading.html#thread-objects
import threading
#
# Module for sleep.
# https://docs.python.org/3.5/library/time.html
import time
#
# Third party modules, in alphabetic order.
#
# Blender library imports, in alphabetic order.
#
# Main Blender Python interface, which is used to get the size of a mesh.
# Import isn't needed because the base class keeps a reference to the interface
# object.
# import bpy
#
# Blender Game Engine KX_GameObject
# Import isn't needed because this class gets an object that has been created
# elsewhere.
# https://www.blender.org/api/blender_python_api_current/bge.types.KX_GameObject.html
#
# Blender Game Engine maths utilities, which can only be imported if running
# from within the Blender Game Engine.
# Import isn't needed because this class gets a Vector from the bpy layer.
# http://www.blender.org/api/blender_python_api_current/mathutils.html
#
# Local imports.
#
# Blender Driver application with threads and locks.
from . import demonstration

from path_store.rest import RestInterface
from path_store.hosted import HostedProperty

# Diagnostic print to show when it's imported. Only printed if all its own
# imports run OK.
print('"'.join(('Application module ', __name__, '.')))

# ToDo:
# -   Have three objects, each using a different set mechanism.
# -   Move Wrapper class somewhere, and rename.

class Wrapper(object):
    @property
    def bgeObject(self):
        return self._bgeObject

    worldScale = HostedProperty('worldScale', 'bgeObject')

    def __init__(self, bgeObject):
        self._bgeObject = bgeObject
        self.worldScale = None

class Application(demonstration.Application):

    # Overriden.
    def game_initialise(self):
        super().game_initialise()
        threading.Thread(
            target=self.pulse_object_scale, name="pulse_object_scale" ).start()

    def _get_scales(self):
        minScale = self.arguments.minScale
        changeScale = self.arguments.changeScale
        increments = self.arguments.increments
        cycleDec = 0
        scale = 0

        yield_ = [None] * 3
        while True:
            # Set list and indexes
            #
            # What was decrementing will be unchanging.
            yield_[cycleDec] = minScale
            #
            # Next dimension will be decrementing.
            cycleDec = (cycleDec + 1) % 3
            #
            # Next next dimension will be incrementing.
            cycleInc = (cycleDec + 1) % 3

            for scale in range(increments):
                yield_[cycleDec] = (
                    minScale
                    + (changeScale * (increments - scale) / increments))
                yield_[cycleInc] = (
                    minScale
                    + (changeScale * (scale + 1) / increments))

                yield yield_

    def pulse_object_scale(self):
        """Pulse the scale of a game object for ever. Run as a thread."""
        objectName = self.arguments.pulsar
        #
        # Get the underlying dimensions of the Blender mesh, from the data
        # layer. It's a mathutils.Vector instance.
        dimensions = tuple(self.bpy.data.objects[objectName].dimensions)
        #
        # Get a reference to the game object.
        object_ = Wrapper(self.gameScene.objects[objectName])

        objin = RestInterface()
        objin.verbose = self.arguments.verbose
        objin.rest_put(object_)

        get_scales = self._get_scales()
        while True:
            self.verbosely(__name__ , 'pulse_object_scale', "locking ...")
            self.mainLock.acquire()
            try:
                self.verbosely(__name__, 'pulse_object_scale', "locked.")
                if self.terminating():
                    self.verbosely(__name__, 'pulse_object_scale', "Stop.")
                    get_scales.close()
                    return
                scales = next(get_scales)
                # worldScale = dimensions.copy()
                worldScale = list(dimensions)
                # for index in range(3):
                    # objin.rest_patch(
                    #     worldScale[index] * scales[(cycle+index)%3]
                    #     , ('worldScale', index))
                    #
                    #
                    # object_.worldScale = worldScale
                    #
                    # objin.rest_patch(
                    #     worldScale[index] * scales[index]
                    #     , ('worldScale', index))
                for index, value in enumerate(scales):
                    worldScale[index] *= value

                objin.rest_put(worldScale, 'worldScale')
            finally:
                self.verbosely(__name__, 'pulse_object_scale', "releasing.")
                self.mainLock.release()

            if self.arguments.sleep is not None:
                time.sleep(self.arguments.sleep)

    def game_keyboard(self, keyEvents):
        self.verbosely(__name__, 'game_keyboard', "Terminating.")
        self.game_terminate()

    def get_argument_parser(self):
        """Method that returns an ArgumentParser. Overriden."""
        parser = super().get_argument_parser()
        parser.prog = ".".join((__name__, self.__class__.__name__))
        parser.add_argument(
            '--increments', type=int, default=40, help=
            "Number of increments. Default: 40.")
        parser.add_argument(
            '--changeScale', type=float, default=2.0,
            help="Change of scale. Default: 2.0.")
        parser.add_argument(
            '--minScale', type=float, default=0.5,
            help="Minimum scale. Default: 0.5.")
        parser.add_argument(
            '--pulsar', default="Cube",
            help="Name of the object to pulse.")
        parser.add_argument(
            '--sleep', type=float, help=
            "Sleep after each increment, for a floating point number of"
            " seconds. Default is not to sleep.")
        return parser
<commit_msg>Late commit of a couple of ToDo items.<commit_after>#!/usr/bin/python
# (c) 2017 Jim Hawkins. MIT licensed, see https://opensource.org/licenses/MIT
# Part of Blender Driver, see https://github.com/sjjhsjjh/blender-driver
"""Python module for Blender Driver demonstration application.

This code illustrates:

-   Basic use of the Blender Game Engine (BGE) KX_GameObject interface, to
    change the size of a game object.
-   Termination of BGE when any key is pressed.
-   Spawning a single thread at the start of BGE execution. The thread is
    joined before terminating BGE.
-   Use of a thread lock to indicate termination is due.

This application doesn't override the Blender Driver game_tick, which is then a
pass in the base class.

This module can only be used from within the Blender Game Engine."""
# Exit if run other than as a module.
if __name__ == '__main__':
    print(__doc__)
    raise SystemExit(1)

# Standard library imports, in alphabetic order.
#
# Module for command line switches.
# https://docs.python.org/3.5/library/argparse.html
# The import isn't needed because this class uses the base class to get an
# object.
# import argparse
#
# This module uses the Thread class.
# https://docs.python.org/3.4/library/threading.html#thread-objects
import threading
#
# Module for sleep.
# https://docs.python.org/3.5/library/time.html
import time
#
# Third party modules, in alphabetic order.
#
# Blender library imports, in alphabetic order.
#
# Main Blender Python interface, which is used to get the size of a mesh.
# Import isn't needed because the base class keeps a reference to the interface
# object.
# import bpy
#
# Blender Game Engine KX_GameObject
# Import isn't needed because this class gets an object that has been created
# elsewhere.
# https://www.blender.org/api/blender_python_api_current/bge.types.KX_GameObject.html
#
# Blender Game Engine maths utilities, which can only be imported if running
# from within the Blender Game Engine.
# Import isn't needed because this class gets a Vector from the bpy layer.
# http://www.blender.org/api/blender_python_api_current/mathutils.html
#
# Local imports.
#
# Blender Driver application with threads and locks.
from . import demonstration

from path_store.rest import RestInterface
from path_store.hosted import HostedProperty

# Diagnostic print to show when it's imported. Only printed if all its own
# imports run OK.
print('"'.join(('Application module ', __name__, '.')))

# ToDo:
# -   Have three objects, each using a different set mechanism.
# -   Move Wrapper class somewhere, and rename.
# -   Back fit _get_scales into pulsar.
# -   Use the Python logging module.

class Wrapper(object):
    @property
    def bgeObject(self):
        return self._bgeObject

    worldScale = HostedProperty('worldScale', 'bgeObject')

    def __init__(self, bgeObject):
        self._bgeObject = bgeObject
        self.worldScale = None

class Application(demonstration.Application):

    # Overriden.
    def game_initialise(self):
        super().game_initialise()
        threading.Thread(
            target=self.pulse_object_scale, name="pulse_object_scale" ).start()

    def _get_scales(self):
        minScale = self.arguments.minScale
        changeScale = self.arguments.changeScale
        increments = self.arguments.increments
        cycleDec = 0
        scale = 0

        yield_ = [None] * 3
        while True:
            # Set list and indexes
            #
            # What was decrementing will be unchanging.
            yield_[cycleDec] = minScale
            #
            # Next dimension will be decrementing.
            cycleDec = (cycleDec + 1) % 3
            #
            # Next next dimension will be incrementing.
            cycleInc = (cycleDec + 1) % 3

            for scale in range(increments):
                yield_[cycleDec] = (
                    minScale
                    + (changeScale * (increments - scale) / increments))
                yield_[cycleInc] = (
                    minScale
                    + (changeScale * (scale + 1) / increments))

                yield yield_

    def pulse_object_scale(self):
        """Pulse the scale of a game object for ever. Run as a thread."""
        objectName = self.arguments.pulsar
        #
        # Get the underlying dimensions of the Blender mesh, from the data
        # layer. It's a mathutils.Vector instance.
        dimensions = tuple(self.bpy.data.objects[objectName].dimensions)
        #
        # Get a reference to the game object.
        object_ = Wrapper(self.gameScene.objects[objectName])

        objin = RestInterface()
        objin.verbose = self.arguments.verbose
        objin.rest_put(object_)

        get_scales = self._get_scales()
        while True:
            self.verbosely(__name__ , 'pulse_object_scale', "locking ...")
            self.mainLock.acquire()
            try:
                self.verbosely(__name__, 'pulse_object_scale', "locked.")
                if self.terminating():
                    self.verbosely(__name__, 'pulse_object_scale', "Stop.")
                    get_scales.close()
                    return
                scales = next(get_scales)
                # worldScale = dimensions.copy()
                worldScale = list(dimensions)
                # for index in range(3):
                    # objin.rest_patch(
                    #     worldScale[index] * scales[(cycle+index)%3]
                    #     , ('worldScale', index))
                    #
                    #
                    # object_.worldScale = worldScale
                    #
                    # objin.rest_patch(
                    #     worldScale[index] * scales[index]
                    #     , ('worldScale', index))
                for index, value in enumerate(scales):
                    worldScale[index] *= value

                objin.rest_put(worldScale, 'worldScale')
            finally:
                self.verbosely(__name__, 'pulse_object_scale', "releasing.")
                self.mainLock.release()

            if self.arguments.sleep is not None:
                time.sleep(self.arguments.sleep)

    def game_keyboard(self, keyEvents):
        self.verbosely(__name__, 'game_keyboard', "Terminating.")
        self.game_terminate()

    def get_argument_parser(self):
        """Method that returns an ArgumentParser. Overriden."""
        parser = super().get_argument_parser()
        parser.prog = ".".join((__name__, self.__class__.__name__))
        parser.add_argument(
            '--increments', type=int, default=40, help=
            "Number of increments. Default: 40.")
        parser.add_argument(
            '--changeScale', type=float, default=2.0,
            help="Change of scale. Default: 2.0.")
        parser.add_argument(
            '--minScale', type=float, default=0.5,
            help="Minimum scale. Default: 0.5.")
        parser.add_argument(
            '--pulsar', default="Cube",
            help="Name of the object to pulse.")
        parser.add_argument(
            '--sleep', type=float, help=
            "Sleep after each increment, for a floating point number of"
            " seconds. Default is not to sleep.")
        return parser
<|endoftext|>


<commit_before># This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
"""

Script to purge user records that have been replaced.

This script takes a tokenserver config file, uses it to load the assignment
backend, and then purges any obsolete user records from that backend.
Obsolete records are those that have been replaced by a newer record for
the same user.

Note that this is a purely optional administrative task, since replaced records
are handled internally by the assignment backend.  But it should help reduce
overheads, improve performance etc if run regularly.

"""

import os
import time
import random
import logging
import optparse

import requests
import tokenlib
import hawkauthlib

import tokenserver.scripts
from tokenserver.assignment import INodeAssignment
from tokenserver.util import format_key_id

logger = logging.getLogger("tokenserver.scripts.purge_old_records")

def purge_old_records(config_file, grace_period=-1, max_per_loop=10,
                      max_offset=0, request_timeout=60, settings=None):
    """Purge old records from the assignment backend in the given config file.

    This function iterates through each storage backend in the given config
    file and calls its purge_expired_items() method.  The result is a
    gradual pruning of expired items from each database.

    `max_offset` is used to select a random offset into the list of purgeable
    records. With multiple tasks running concurrently, this will provide each
    a (likely) different set of records to work on. A cheap, imperfect
    randomization.
    """
    logger.info("Purging old user records")
    logger.debug("Using config file %r", config_file)
    config = tokenserver.scripts.load_configurator(config_file)
    config.begin()
    try:
        backend = config.registry.getUtility(INodeAssignment)
        patterns = config.registry['endpoints_patterns']
        for service in patterns:
            logger.debug("Purging old user records for service: %s", service)
            # Process batches of <max_per_loop> items, until we run out.
            while True:
                offset = random.randint(0, max_offset)
                kwds = {
                    "grace_period": grace_period,
                    "limit": max_per_loop,
                    "offset": offset,
                }
                rows = list(backend.get_old_user_records(service, **kwds))
                logger.info("Fetched %d rows at offset %d", len(rows), offset)
                counter = 0
                for row in rows:
                    # Don't attempt to purge data from downed nodes.
                    # Instead wait for them to either come back up or to be
                    # completely removed from service.
                    if row.node is None:
                        logger.info("Deleting user record for uid %s on %s",
                                    row.uid, row.node)
                        if settings and not settings.dryrun:
                            backend.delete_user_record(service, row.uid)
                    elif not row.downed:
                        logger.info("Purging uid %s on %s", row.uid, row.node)
                        delete_service_data(config, service, row,
                                            timeout=request_timeout,
                                            settings=settings)
                        if settings and not settings.dryrun:
                            backend.delete_user_record(service, row.uid)
                        counter += 1
                    elif row.downed and settings and settings.force:
                        logger.info(
                            "Forcing tokenserver record delete: {}".format(
                                row.uid
                            )
                        )
                        if not settings.dryrun:
                            backend.delete_user_record(service, row.uid)
                        counter += 1
                    if settings and settings.max_records:
                        if counter >= settings.max_records:
                            logger.info("Reached max_records, exiting")
                            return True
                if len(rows) < max_per_loop:
                    break
    except Exception:
        logger.exception("Error while purging old user records")
        return False
    else:
        logger.info("Finished purging old user records")
        return True
    finally:
        config.end()

def delete_service_data(config, service, user, timeout=60, settings=None):
    """Send a data-deletion request to the user's service node.

    This is a little bit of hackery to cause the user's service node to
    remove any data it still has stored for the user.  We simulate a DELETE
    request from the user's own account.
    """
    secrets = config.registry.settings['tokenserver.secrets']
    pattern = config.registry['endpoints_patterns'][service]
    node_secrets = secrets.get(user.node)
    if not node_secrets:
        msg = "The node %r does not have any shared secret" % (user.node,)
        raise ValueError(msg)
    token = tokenlib.make_token({
        "uid": user.uid,
        "node": user.node,
        "fxa_uid": user.email.split("@", 1)[0],
        "fxa_kid": format_key_id(
            user.keys_changed_at or user.generation,
            user.client_state.decode('hex')
        ),
    }, secret=node_secrets[-1])
    secret = tokenlib.get_derived_secret(token, secret=node_secrets[-1])
    endpoint = pattern.format(uid=user.uid, service=service, node=user.node)
    auth = HawkAuth(token, secret)
    if settings and settings.dryrun:
        return
    resp = requests.delete(endpoint, auth=auth, timeout=timeout)
    if resp.status_code >= 400 and resp.status_code != 404:
        resp.raise_for_status()

class HawkAuth(requests.auth.AuthBase):
    """Hawk-signing auth helper class."""

    def __init__(self, token, secret):
        self.token = token
        self.secret = secret

    def __call__(self, req):
        hawkauthlib.sign_request(req, self.token, self.secret)
        return req

def main(args=None):
    """Main entry-point for running this script.

    This function parses command-line arguments and passes them on
    to the purge_old_records() function.
    """
    usage = "usage: %prog [options] config_file"
    parser = optparse.OptionParser(usage=usage)
    parser.add_option("", "--purge-interval", type="int", default=3600,
                      help="Interval to sleep between purging runs")
    parser.add_option("", "--grace-period", type="int", default=86400,
                      help="Number of seconds grace to allow on replacement")
    parser.add_option("", "--max-per-loop", type="int", default=10,
                      help="Maximum number of items to fetch in one go")
    # N.B., if the number of purgeable rows is <<< max_offset then most
    # selects will return zero rows. Choose this value accordingly.
    parser.add_option("", "--max-offset", type="int", default=0,
                      help="Use random offset from 0 to max_offset")
    parser.add_option("", "--request-timeout", type="int", default=60,
                      help="Timeout for service deletion requests")
    parser.add_option("", "--oneshot", action="store_true",
                      help="Do a single purge run and then exit")
    parser.add_option("", "--max-records", type="int", default=0,
                      help="Max records to delete")
    parser.add_option("", "--dryrun", action="store_true",
                      help="Don't do destructive things")
    parser.add_option("", "--force", action="store_true",
                      help="force record to be deleted from TS db,"
                      " even if node is down")
    parser.add_option("-v", "--verbose", action="count", dest="verbosity",
                      help="Control verbosity of log messages")

    opts, args = parser.parse_args(args)
    if len(args) != 1:
        parser.print_usage()
        return 1

    tokenserver.scripts.configure_script_logging(opts)

    config_file = os.path.abspath(args[0])

    purge_old_records(config_file,
                      grace_period=opts.grace_period,
                      max_per_loop=opts.max_per_loop,
                      max_offset=opts.max_offset,
                      request_timeout=opts.request_timeout,
                      settings=opts)
    if not opts.oneshot:
        while True:
            # Randomize sleep interval +/- thirty percent to desynchronize
            # instances of this script running on multiple webheads.
            sleep_time = opts.purge_interval
            sleep_time += random.randint(-0.3 * sleep_time, 0.3 * sleep_time)
            logger.debug("Sleeping for %d seconds", sleep_time)
            time.sleep(sleep_time)
            purge_old_records(config_file,
                              grace_period=opts.grace_period,
                              max_per_loop=opts.max_per_loop,
                              max_offset=opts.max_offset,
                              request_timeout=opts.request_timeout,
                              settings=opts)
    return 0

if __name__ == "__main__":
    tokenserver.scripts.run_script(main)
<commit_msg>fix: Detect potential loops, don't eat errors (#230)<commit_after># This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
"""

Script to purge user records that have been replaced.

This script takes a tokenserver config file, uses it to load the assignment
backend, and then purges any obsolete user records from that backend.
Obsolete records are those that have been replaced by a newer record for
the same user.

Note that this is a purely optional administrative task, since replaced records
are handled internally by the assignment backend.  But it should help reduce
overheads, improve performance etc if run regularly.

"""

import os
import time
import random
import logging
import optparse

import requests
import tokenlib
import hawkauthlib

import tokenserver.scripts
from tokenserver.assignment import INodeAssignment
from tokenserver.util import format_key_id

logger = logging.getLogger("tokenserver.scripts.purge_old_records")

def purge_old_records(config_file, grace_period=-1, max_per_loop=10,
                      max_offset=0, request_timeout=60, settings=None):
    """Purge old records from the assignment backend in the given config file.

    This function iterates through each storage backend in the given config
    file and calls its purge_expired_items() method.  The result is a
    gradual pruning of expired items from each database.

    `max_offset` is used to select a random offset into the list of purgeable
    records. With multiple tasks running concurrently, this will provide each
    a (likely) different set of records to work on. A cheap, imperfect
    randomization.
    """
    logger.info("Purging old user records")
    logger.debug("Using config file %r", config_file)
    config = tokenserver.scripts.load_configurator(config_file)
    config.begin()
    try:
        backend = config.registry.getUtility(INodeAssignment)
        patterns = config.registry['endpoints_patterns']
        for service in patterns:
            previous_list = []
            logger.debug("Purging old user records for service: %s", service)
            # Process batches of <max_per_loop> items, until we run out.
            while True:
                offset = random.randint(0, max_offset)
                kwds = {
                    "grace_period": grace_period,
                    "limit": max_per_loop,
                    "offset": offset,
                }
                rows = list(backend.get_old_user_records(service, **kwds))
                if not rows:
                    logger.info("No more data for %s", service)
                    break
                if rows == previous_list:
                    raise Exception("Loop detected")
                previous_list = rows
                logger.info("Fetched %d rows at offset %d", len(rows), offset)
                counter = 0
                for row in rows:
                    # Don't attempt to purge data from downed nodes.
                    # Instead wait for them to either come back up or to be
                    # completely removed from service.
                    if row.node is None:
                        logger.info("Deleting user record for uid %s on %s",
                                    row.uid, row.node)
                        if settings and not settings.dryrun:
                            backend.delete_user_record(service, row.uid)
                    elif not row.downed:
                        logger.info("Purging uid %s on %s", row.uid, row.node)
                        delete_service_data(config, service, row,
                                            timeout=request_timeout,
                                            settings=settings)
                        if settings and not settings.dryrun:
                            backend.delete_user_record(service, row.uid)
                        counter += 1
                    elif row.downed and settings and settings.force:
                        logger.info(
                            "Forcing tokenserver record delete: {}".format(
                                row.uid
                            )
                        )
                        if not settings.dryrun:
                            backend.delete_user_record(service, row.uid)
                        counter += 1
                    if settings and settings.max_records:
                        if counter >= settings.max_records:
                            logger.info("Reached max_records, exiting")
                            return True
                if len(rows) < max_per_loop:
                    break
    except Exception as e:
        logger.exception("Error while purging old user records: {}".format(e))
        return False
    else:
        logger.info("Finished purging old user records")
        return True
    finally:
        config.end()

def delete_service_data(config, service, user, timeout=60, settings=None):
    """Send a data-deletion request to the user's service node.

    This is a little bit of hackery to cause the user's service node to
    remove any data it still has stored for the user.  We simulate a DELETE
    request from the user's own account.
    """
    secrets = config.registry.settings['tokenserver.secrets']
    pattern = config.registry['endpoints_patterns'][service]
    node_secrets = secrets.get(user.node)
    if not node_secrets:
        msg = "The node %r does not have any shared secret" % (user.node,)
        raise ValueError(msg)
    token = tokenlib.make_token({
        "uid": user.uid,
        "node": user.node,
        "fxa_uid": user.email.split("@", 1)[0],
        "fxa_kid": format_key_id(
            user.keys_changed_at or user.generation,
            user.client_state.decode('hex')
        ),
    }, secret=node_secrets[-1])
    secret = tokenlib.get_derived_secret(token, secret=node_secrets[-1])
    endpoint = pattern.format(uid=user.uid, service=service, node=user.node)
    auth = HawkAuth(token, secret)
    if settings and settings.dryrun:
        return
    resp = requests.delete(endpoint, auth=auth, timeout=timeout)
    if resp.status_code >= 400 and resp.status_code != 404:
        resp.raise_for_status()

class HawkAuth(requests.auth.AuthBase):
    """Hawk-signing auth helper class."""

    def __init__(self, token, secret):
        self.token = token
        self.secret = secret

    def __call__(self, req):
        hawkauthlib.sign_request(req, self.token, self.secret)
        return req

def main(args=None):
    """Main entry-point for running this script.

    This function parses command-line arguments and passes them on
    to the purge_old_records() function.
    """
    usage = "usage: %prog [options] config_file"
    parser = optparse.OptionParser(usage=usage)
    parser.add_option("", "--purge-interval", type="int", default=3600,
                      help="Interval to sleep between purging runs")
    parser.add_option("", "--grace-period", type="int", default=86400,
                      help="Number of seconds grace to allow on replacement")
    parser.add_option("", "--max-per-loop", type="int", default=10,
                      help="Maximum number of items to fetch in one go")
    # N.B., if the number of purgeable rows is <<< max_offset then most
    # selects will return zero rows. Choose this value accordingly.
    parser.add_option("", "--max-offset", type="int", default=0,
                      help="Use random offset from 0 to max_offset")
    parser.add_option("", "--request-timeout", type="int", default=60,
                      help="Timeout for service deletion requests")
    parser.add_option("", "--oneshot", action="store_true",
                      help="Do a single purge run and then exit")
    parser.add_option("", "--max-records", type="int", default=0,
                      help="Max records to delete")
    parser.add_option("", "--dryrun", action="store_true",
                      help="Don't do destructive things")
    parser.add_option("", "--force", action="store_true",
                      help="force record to be deleted from TS db,"
                      " even if node is down")
    parser.add_option("-v", "--verbose", action="count", dest="verbosity",
                      help="Control verbosity of log messages")

    opts, args = parser.parse_args(args)
    if len(args) != 1:
        parser.print_usage()
        return 1

    tokenserver.scripts.configure_script_logging(opts)

    config_file = os.path.abspath(args[0])

    purge_old_records(config_file,
                      grace_period=opts.grace_period,
                      max_per_loop=opts.max_per_loop,
                      max_offset=opts.max_offset,
                      request_timeout=opts.request_timeout,
                      settings=opts)
    if not opts.oneshot:
        while True:
            # Randomize sleep interval +/- thirty percent to desynchronize
            # instances of this script running on multiple webheads.
            sleep_time = opts.purge_interval
            sleep_time += random.randint(-0.3 * sleep_time, 0.3 * sleep_time)
            logger.debug("Sleeping for %d seconds", sleep_time)
            time.sleep(sleep_time)
            purge_old_records(config_file,
                              grace_period=opts.grace_period,
                              max_per_loop=opts.max_per_loop,
                              max_offset=opts.max_offset,
                              request_timeout=opts.request_timeout,
                              settings=opts)
    return 0

if __name__ == "__main__":
    tokenserver.scripts.run_script(main)
<|endoftext|>


<commit_before>"""Leetcode Treasure Island
Medium

URL: https://leetcode.com/discuss/interview-question/347457

Note: Amazon OA 2019.

You have a map that marks the location of a treasure island.
Some of the map area has jagged rocks and dangerous reefs.
Other areas are safe to sail in.
There are other explorers trying to find the treasure.
So you must figure out a shortest route to the treasure island.

Assume the map area is a two dimensional grid,
represented by a matrix of characters.
You must start from the top-left corner of the map and
can move one block up, down, left or right at a time.
The treasure island is marked as 'X' in a block of the matrix.
'X' will not be at the top-left corner.
Any block with dangerous rocks or reefs will be marked as 'D'.
You must not enter dangerous blocks.
You cannot leave the map area. Other areas 'O' are safe to sail in.
The top-left corner is always safe.
Output the minimum number of steps to get to the treasure.

Example:
Input:
[['O', 'O', 'O', 'O'],
 ['D', 'O', 'D', 'O'],
 ['O', 'O', 'O', 'O'],
 ['X', 'D', 'D', 'O']]
Output: 5
Explanation: Route is (0, 0), (0, 1), (1, 1), (2, 1), (2, 0), (3, 0)
The minimum route takes 5 steps.
"""

class SolutionSteps(object):
    def treasureIsland(self, grid):
        """
        :type logs: List[list[str]]
        :rtype: int
        """
        if not grid or not grid[0]:
            return -1

        n_rows, n_cols = len(grid), len(grid[0])

        # Apply BFS using queue for shortest route.
        queue = [(0, 0)]

        # Update grid to mark (0, 0) as visited.
        grid[0][0] = 'D'

        steps = 0

        while queue:
            size = len(queue)

            for _ in range(size):
                r, c = queue.pop()

                dirs = [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)]

                for r_neighbor, c_neighbor in dirs:
                    if (r_neighbor < 0 or r_neighbor >= n_rows or
                        c_neighbor < 0 or c_neighbor >= n_cols or
                        grid[r_neighbor][c_neighbor] == 'D'):
                        continue

                    if grid[r_neighbor][c_neighbor] == 'X':
                        return steps + 1

                    if grid[r_neighbor][c_neighbor] == 'O':
                        # Update grid to mark as visited.
                        grid[r_neighbor][c_neighbor] = 'D'
                        queue.insert(0, (r_neighbor, c_neighbor))

            steps += 1

        return -1

def main():
    # Ans: 5.
    grid = [['O', 'O', 'O', 'O'],
            ['D', 'O', 'D', 'O'],
            ['O', 'O', 'O', 'O'],
            ['X', 'D', 'D', 'O']]
    print SolutionSteps().treasureIsland(grid)

if __name__ == '__main__':
    main()
<commit_msg>Complete sol by distances<commit_after>"""Leetcode Treasure Island
Medium

URL: https://leetcode.com/discuss/interview-question/347457

Note: Amazon OA 2019.

You have a map that marks the location of a treasure island.
Some of the map area has jagged rocks and dangerous reefs.
Other areas are safe to sail in.
There are other explorers trying to find the treasure.
So you must figure out a shortest route to the treasure island.

Assume the map area is a two dimensional grid,
represented by a matrix of characters.
You must start from the top-left corner of the map and
can move one block up, down, left or right at a time.
The treasure island is marked as 'X' in a block of the matrix.
'X' will not be at the top-left corner.
Any block with dangerous rocks or reefs will be marked as 'D'.
You must not enter dangerous blocks.
You cannot leave the map area. Other areas 'O' are safe to sail in.
The top-left corner is always safe.
Output the minimum number of steps to get to the treasure.

Example:
Input:
[['O', 'O', 'O', 'O'],
 ['D', 'O', 'D', 'O'],
 ['O', 'O', 'O', 'O'],
 ['X', 'D', 'D', 'O']]
Output: 5
Explanation: Route is (0, 0), (0, 1), (1, 1), (2, 1), (2, 0), (3, 0)
The minimum route takes 5 steps.
"""

class SolutionSteps(object):
    def treasureIsland(self, grid):
        """
        :type logs: List[list[str]]
        :rtype: int
        """
        if not grid or not grid[0]:
            return -1

        n_rows, n_cols = len(grid), len(grid[0])

        # Apply BFS using queue for shortest route.
        queue = [(0, 0)]

        # Update grid to mark (0, 0) as visited.
        grid[0][0] = 'D'

        steps = 0

        while queue:
            size = len(queue)

            for _ in range(size):
                r, c = queue.pop()

                dirs = [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)]

                for r_neighbor, c_neighbor in dirs:
                    if (r_neighbor < 0 or r_neighbor >= n_rows or
                        c_neighbor < 0 or c_neighbor >= n_cols or
                        grid[r_neighbor][c_neighbor] == 'D'):
                        continue

                    if grid[r_neighbor][c_neighbor] == 'X':
                        return steps + 1

                    if grid[r_neighbor][c_neighbor] == 'O':
                        # Update grid to mark as visited.
                        grid[r_neighbor][c_neighbor] = 'D'
                        queue.insert(0, (r_neighbor, c_neighbor))

            steps += 1

        return -1

class SolutionDistances(object):
    def treasureIsland(self, grid):
        """
        :type logs: List[list[str]]
        :rtype: int
        """
        from collections import defaultdict

        if not grid or not grid[0]:
            return -1

        n_rows, n_cols = len(grid), len(grid[0])

        # Apply BFS using queue for shortest route.
        queue = [(0, 0)]

        # Update grid to mark (0, 0) as visited.
        grid[0][0] = 'D'

        steps_d = defaultdict(int)
        steps_d[(0, 0)] = 0

        while queue:
            size = len(queue)

            for _ in range(size):
                r, c = queue.pop()

                dirs = [(r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)]

                for r_neighbor, c_neighbor in dirs:
                    if (r_neighbor < 0 or r_neighbor >= n_rows or
                        c_neighbor < 0 or c_neighbor >= n_cols or
                        grid[r_neighbor][c_neighbor] == 'D'):
                        continue

                    if grid[r_neighbor][c_neighbor] == 'X':
                        steps_d[(r_neighbor, c_neighbor)] =  steps_d[(r, c)] + 1
                        break

                    if grid[r_neighbor][c_neighbor] == 'O':
                        # Update grid to mark as visited.
                        grid[r_neighbor][c_neighbor] = 'D'

                        steps_d[(r_neighbor, c_neighbor)] =  steps_d[(r, c)] + 1
                        queue.insert(0, (r_neighbor, c_neighbor))

        if steps_d.get((n_rows - 1, 0)):
            return steps_d[(n_rows - 1, 0)]
        else:
            return -1

def main():
    # Ans: 5.
    grid = [['O', 'O', 'O', 'O'],
            ['D', 'O', 'D', 'O'],
            ['O', 'O', 'O', 'O'],
            ['X', 'D', 'D', 'O']]
    print SolutionSteps().treasureIsland(grid)

    grid = [['O', 'O', 'O', 'O'],
            ['D', 'D', 'D', 'O'],
            ['O', 'O', 'O', 'O'],
            ['X', 'D', 'D', 'O']]
    print SolutionDistances().treasureIsland(grid)

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before># coding: utf-8

import flask

import auth
import config
import model
import util

from main import app

facebook_config = dict(
    access_token_url='/oauth/access_token',
    authorize_url='https://www.facebook.com/dialog/oauth',
    base_url='https://graph.facebook.com/',
    consumer_key=config.CONFIG_DB.facebook_app_id,
    consumer_secret=config.CONFIG_DB.facebook_app_secret,
    request_token_params={'scope': 'email'},
  )

facebook = auth.create_oauth_app(facebook_config, 'facebook')

@app.route('/api/auth/callback/facebook/')
def facebook_authorized():
  response = facebook.authorized_response()
  if response is None:
    flask.flash('You denied the request to sign in.')
    return flask.redirect(util.get_next_url())

  flask.session['oauth_token'] = (response['access_token'], '')
  me = facebook.get('/me')
  user_db = retrieve_user_from_facebook(me.data)
  return auth.signin_user_db(user_db)

@facebook.tokengetter
def get_facebook_oauth_token():
  return flask.session.get('oauth_token')

@app.route('/signin/facebook/')
def signin_facebook():
  return auth.signin_oauth(facebook)

def retrieve_user_from_facebook(response):
  auth_id = 'facebook_%s' % response['id']
  user_db = model.User.get_by('auth_ids', auth_id)
  return user_db or auth.create_user_db(
      auth_id=auth_id,
      name=response['name'],
      username=response.get('username', response['name']),
      email=response.get('email', ''),
      verified=bool(response.get('email', '')),
    )
<commit_msg>Updated Facebook authorize URL<commit_after># coding: utf-8

import flask

import auth
import config
import model
import util

from main import app

facebook_config = dict(
    access_token_url='/oauth/access_token',
    authorize_url='/oauth/authorize',
    base_url='https://graph.facebook.com/',
    consumer_key=config.CONFIG_DB.facebook_app_id,
    consumer_secret=config.CONFIG_DB.facebook_app_secret,
    request_token_params={'scope': 'email'},
  )

facebook = auth.create_oauth_app(facebook_config, 'facebook')

@app.route('/api/auth/callback/facebook/')
def facebook_authorized():
  response = facebook.authorized_response()
  if response is None:
    flask.flash('You denied the request to sign in.')
    return flask.redirect(util.get_next_url())

  flask.session['oauth_token'] = (response['access_token'], '')
  me = facebook.get('/me')
  user_db = retrieve_user_from_facebook(me.data)
  return auth.signin_user_db(user_db)

@facebook.tokengetter
def get_facebook_oauth_token():
  return flask.session.get('oauth_token')

@app.route('/signin/facebook/')
def signin_facebook():
  return auth.signin_oauth(facebook)

def retrieve_user_from_facebook(response):
  auth_id = 'facebook_%s' % response['id']
  user_db = model.User.get_by('auth_ids', auth_id)
  return user_db or auth.create_user_db(
      auth_id=auth_id,
      name=response['name'],
      username=response.get('username', response['name']),
      email=response.get('email', ''),
      verified=bool(response.get('email', '')),
    )
<|endoftext|>