<commit_before># -*- coding: utf-8 -*-
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import ValidationError
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db import models, transaction
from django.db.models import Count
from django.db.models.aggregates import Sum
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.utils import timezone, six
from django.utils.encoding import python_2_unicode_compatible

from django_extensions.db.fields import AutoSlugField

from allauth.account.signals import user_signed_up

from textwrap import dedent

from jury.models import Jury

class DeckBaseManager(models.QuerySet):
    def cached_authors(self):
        return super(DeckBaseManager, self).select_related('author')

    def published_ones(self):
        return self.cached_authors().filter(is_published=True)

    def upcoming(self, published_only=True):
        return self.filter(due_date__gte=timezone.now(), is_published=published_only)

    def order_by_never_voted(self, user_id):
        if self.model != Proposal:
            raise AttributeError(
                "%s object has no attribute %s" % (
                    self.model, 'order_by_never_voted'))

        order_by_criteria = dedent("""
            SELECT 1
              FROM deck_vote
             WHERE deck_vote.user_id = %s AND
                   deck_vote.proposal_id = deck_proposal.activity_ptr_id
             LIMIT 1
        """)

        new_ordering = ['-never_voted']
        if settings.DATABASES['default'].get('ENGINE') == 'django.db.backends.sqlite3':
            new_ordering = ['never_voted']
        new_ordering.extend(Proposal._meta.ordering)
        return self.extra(
            select=dict(never_voted=order_by_criteria % user_id),
            order_by=new_ordering
        )

@python_2_unicode_compatible
class DeckBaseModel(models.Model):
    title = models.CharField(_('Title'), max_length=200)
    slug = AutoSlugField(populate_from='title', overwrite=True,
                         max_length=200, unique=True, db_index=True)
    description = models.TextField(
        _('Description'), max_length=10000, blank=True)
    created_at = models.DateTimeField(_('Created At'), auto_now_add=True)
    is_published = models.BooleanField(_('Publish'), default=True)

    # relations
    author = models.ForeignKey(to=settings.AUTH_USER_MODEL,
                               related_name='%(class)ss')

    # managers
    objects = DeckBaseManager.as_manager()

    class Meta:
        abstract = True

    def __str__(self):
        return six.text_type(self.title)

@python_2_unicode_compatible
class Vote(models.Model):
    ANGRY, SLEEPY, SAD, HAPPY, LAUGHING = range(-1, 4)
    VOTE_TITLES = dict(
        angry=_('Angry'), sad=_('Sad'),
        sleepy=_('Sleepy'), happy=_('Happy'),
        laughing=_('Laughing')
    )
    VOTE_RATES = ((ANGRY, 'angry'),
                  (SAD, 'sad'),
                  (SLEEPY, 'sleepy'),
                  (HAPPY, 'happy'),
                  (LAUGHING, 'laughing'))
    rate = models.SmallIntegerField(_('Rate Index'), null=True, blank=True,
                                    choices=VOTE_RATES)

    # relations
    proposal = models.ForeignKey(to='deck.Proposal', related_name='votes')
    user = models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='votes')

    class Meta:
        verbose_name = _('Vote')
        verbose_name_plural = _('Votes')
        unique_together = (('proposal', 'user'),)

    def __str__(self):
        return six.text_type("{0.user}: {0.rate} in {0.proposal}".format(self))

    def save(self, *args, **kwargs):
        validation_message = None

        user_is_in_jury = self.proposal.event.jury.users.filter(
            pk=self.user.pk).exists()
        if (self.user.is_superuser or user_is_in_jury):
            pass
        elif self.user == self.proposal.author:
            validation_message = _(u'You cannot Rate your own proposals.')
        elif not self.proposal.event.allow_public_voting:
            validation_message = _(u"Proposal doesn't accept Public Voting.")

        if validation_message:
            raise ValidationError(_(validation_message))

        return super(Vote, self).save(*args, **kwargs)

class Activity(DeckBaseModel):
    PROPOSAL = 'proposal'
    WORKSHOP = 'workshop'
    OPENNING = 'openning'
    COFFEEBREAK = 'coffee-break'
    LUNCH = 'lunch'
    LIGHTNINGTALKS = 'lightning-talks'
    ENDING = 'ending'
    ACTIVITY_TYPES = (
        (PROPOSAL, _('Proposal')),
        (WORKSHOP, _('Workshop')),
        (OPENNING, _('Openning')),
        (COFFEEBREAK, _('Coffee Break')),
        (LUNCH, _('Lunch')),
        (LIGHTNINGTALKS, _('Lightning Talks')),
        (ENDING, _('Ending')),
    )
    start_timetable = models.TimeField(
        _('Start Timetable'), null=True, blank=False)
    end_timetable = models.TimeField(
        _('End Timetable'), null=True, blank=False)
    track_order = models.SmallIntegerField(_('Order'), null=True, blank=True)
    activity_type = models.CharField(
        _('Type'), choices=ACTIVITY_TYPES, default=PROPOSAL, max_length=50)

    # relations
    track = models.ForeignKey(to='deck.Track', related_name='activities',
                              null=True, blank=True)

    class Meta:
        ordering = ('track_order', 'start_timetable', 'pk')
        verbose_name = _('Activity')
        verbose_name_plural = _('Activities')

    @property
    def timetable(self):
        if all([self.start_timetable is None, self.end_timetable is None]):
            return '--:--'

        return '{0} - {1}'.format(
            self.start_timetable.strftime('%H:%M'),
            self.end_timetable.strftime('%H:%M')
        )

class Proposal(Activity):
    is_approved = models.BooleanField(_('Is approved'), default=False)
    more_information = models.TextField(
        _('More information'), max_length=10000, null=True, blank=True)

    # relations
    event = models.ForeignKey(to='deck.Event', related_name='proposals')

    class Meta:
        ordering = ['title']
        verbose_name = _('Proposal')
        verbose_name_plural = _('Proposals')

    def save(self, *args, **kwargs):
        if not self.pk and self.event.closing_date_is_passed:
            raise ValidationError(
                _("This Event doesn't accept Proposals anymore."))
        return super(Proposal, self).save(*args, **kwargs)

    @property
    def get_rate(self):
        rate = None
        try:
            rate = self.votes__rate__sum
        except AttributeError:
            rate = self.votes.aggregate(Sum('rate'))['rate__sum']
        finally:
            return rate or 0

    def rate(self, user, rate):
        rate_int = [r[0] for r in Vote.VOTE_RATES if rate in r][0]
        with transaction.atomic():
            self.votes.update_or_create(user=user, defaults={'rate': rate_int})

    def user_already_voted(self, user):
        if isinstance(user, AnonymousUser):
            return False
        return self.votes.filter(user=user).exists()

    def user_can_vote(self, user):
        can_vote = False
        if self.author == user and not self.event.author == user:
            pass
        elif self.event.allow_public_voting:
            can_vote = True
        elif user.is_superuser:
            can_vote = True
        elif self.event.jury.users.filter(pk=user.pk).exists():
            can_vote = True
        return can_vote

    def user_can_approve(self, user):
        can_approve = False
        if user.is_superuser:
            can_approve = True
        elif self.event.jury.users.filter(pk=user.pk).exists():
            can_approve = True
        return can_approve

    def get_absolute_url(self):
        return reverse('view_event', kwargs={'slug': self.event.slug}) + \
            '#' + self.slug

    def approve(self):
        if self.is_approved:
            raise ValidationError(_("This Proposal was already approved."))
        self.is_approved = True
        self.save()

    def disapprove(self):
        if not self.is_approved:
            raise ValidationError(_("This Proposal was already disapproved."))
        self.is_approved = False
        self.save()

@python_2_unicode_compatible
class Track(models.Model):
    title = models.CharField(_('Title'), max_length=200)
    slug = AutoSlugField(populate_from='title', overwrite=True,
                         max_length=200, unique=True, db_index=True)

    # relations
    event = models.ForeignKey(to='deck.Event', related_name='tracks')

    class Meta:
        verbose_name = _('Track')
        verbose_name_plural = _('Tracks')

    def __str__(self):
        return six.text_type('Track for: "%s"' % self.event.title)

    @property
    def proposals(self):
        return Proposal.objects.filter(
            pk__in=self.activities.values_list('pk', flat=True)
        )

class Event(DeckBaseModel):
    allow_public_voting = models.BooleanField(_('Allow Public Voting'),
                                              default=True)
    closing_date = models.DateTimeField(null=False, blank=False)
    slots = models.SmallIntegerField(_('Slots'), default=10)

    # relations
    jury = models.OneToOneField(to='jury.Jury', related_name='event',
                                null=True, blank=True)
    anonymous_voting = models.BooleanField(
        _('Anonymous Voting?'), default=False)

    class Meta:
        ordering = ['-closing_date', '-created_at']
        verbose_name = _('Event')
        verbose_name_plural = _('Events')

    @property
    def closing_date_is_passed(self):
        return timezone.now() > self.closing_date

    @property
    def closing_date_is_close(self):
        if self.closing_date_is_passed:
            return False
        return timezone.now() > self.closing_date - timezone.timedelta(days=7)

    def get_absolute_url(self):
        return reverse('view_event', kwargs={'slug': self.slug})

    def user_can_see_proposals(self, user):
        can_see_proposals = False
        if user.is_superuser or self.author == user:
            can_see_proposals = True
        elif self.allow_public_voting:
            can_see_proposals = True
        elif (not user.is_anonymous() and
              self.jury.users.filter(pk=user.pk).exists()):
            can_see_proposals = True
        return can_see_proposals

    def get_proposers_count(self):
        return self.proposals.values_list(
            'author', flat=True).distinct().count()

    def get_votes_count(self):
        return self.proposals.values_list('votes', flat=True).count()

    def get_votes_to_export(self):
        return self.proposals.values(
            'id', 'title', 'author__username', 'author__email'
        ).annotate(
            Sum('votes__rate')
        ).annotate(Count('votes'))

    def get_schedule(self):
        schedule = Activity.objects.filter(track__event=self)\
            .cached_authors()\
            .annotate(Sum('proposal__votes__rate'))\
            .extra(select=dict(track_isnull='track_id IS NULL'))\
            .order_by('track_isnull', 'track_order',
                      '-proposal__votes__rate__sum')
        return schedule

    def get_not_approved_schedule(self):
        return self.proposals\
            .cached_authors()\
            .filter(
                models.Q(is_approved=False) |
                models.Q(track__isnull=True))

@receiver(user_signed_up)
def send_welcome_mail(request, user, **kwargs):
    if not settings.SEND_NOTIFICATIONS:
        return
    message = render_to_string('mailing/welcome.txt')
    subject = _(u'Welcome')
    recipients = [user.email]
    send_mail(subject, message, settings.NO_REPLY_EMAIL, recipients)

@receiver(post_save, sender=Event)
def create_initial_jury(sender, instance, signal, created, **kwargs):
    if not created:
        return
    jury = Jury()
    jury.save()
    jury.users.add(instance.author)
    instance.jury = jury
    instance.save()

@receiver(post_save, sender=Event)
def create_initial_track(sender, instance, signal, created, **kwargs):
    if not created:
        return
    Track.objects.create(event=instance)

@receiver(post_delete, sender=Proposal)
def send_proposal_deleted_mail(sender, instance, **kwargs):
    if not settings.SEND_NOTIFICATIONS:
        return
    context = {'event_title': instance.event.title,
               'proposal_title': instance.title}
    message = render_to_string('mailing/jury_deleted_proposal.txt', context)
    subject = _(u'Proposal from %s just got deleted' % instance.event.title)
    recipients = instance.event.jury.users.values_list('email', flat=True)
    send_mail(subject, message, settings.NO_REPLY_EMAIL, recipients)
<commit_msg>Replace missing field<commit_after># -*- coding: utf-8 -*-
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.core.exceptions import ValidationError
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db import models, transaction
from django.db.models import Count
from django.db.models.aggregates import Sum
from django.db.models.signals import post_delete, post_save
from django.dispatch import receiver
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.utils import timezone, six
from django.utils.encoding import python_2_unicode_compatible

from django_extensions.db.fields import AutoSlugField

from allauth.account.signals import user_signed_up

from textwrap import dedent

from jury.models import Jury

class DeckBaseManager(models.QuerySet):
    def cached_authors(self):
        return super(DeckBaseManager, self).select_related('author')

    def published_ones(self):
        return self.cached_authors().filter(is_published=True)

    def upcoming(self, published_only=True):
        return self.filter(closing_date__gte=timezone.now(), is_published=published_only)

    def order_by_never_voted(self, user_id):
        if self.model != Proposal:
            raise AttributeError(
                "%s object has no attribute %s" % (
                    self.model, 'order_by_never_voted'))

        order_by_criteria = dedent("""
            SELECT 1
              FROM deck_vote
             WHERE deck_vote.user_id = %s AND
                   deck_vote.proposal_id = deck_proposal.activity_ptr_id
             LIMIT 1
        """)

        new_ordering = ['-never_voted']
        if settings.DATABASES['default'].get('ENGINE') == 'django.db.backends.sqlite3':
            new_ordering = ['never_voted']
        new_ordering.extend(Proposal._meta.ordering)
        return self.extra(
            select=dict(never_voted=order_by_criteria % user_id),
            order_by=new_ordering
        )

@python_2_unicode_compatible
class DeckBaseModel(models.Model):
    title = models.CharField(_('Title'), max_length=200)
    slug = AutoSlugField(populate_from='title', overwrite=True,
                         max_length=200, unique=True, db_index=True)
    description = models.TextField(
        _('Description'), max_length=10000, blank=True)
    created_at = models.DateTimeField(_('Created At'), auto_now_add=True)
    is_published = models.BooleanField(_('Publish'), default=True)

    # relations
    author = models.ForeignKey(to=settings.AUTH_USER_MODEL,
                               related_name='%(class)ss')

    # managers
    objects = DeckBaseManager.as_manager()

    class Meta:
        abstract = True

    def __str__(self):
        return six.text_type(self.title)

@python_2_unicode_compatible
class Vote(models.Model):
    ANGRY, SLEEPY, SAD, HAPPY, LAUGHING = range(-1, 4)
    VOTE_TITLES = dict(
        angry=_('Angry'), sad=_('Sad'),
        sleepy=_('Sleepy'), happy=_('Happy'),
        laughing=_('Laughing')
    )
    VOTE_RATES = ((ANGRY, 'angry'),
                  (SAD, 'sad'),
                  (SLEEPY, 'sleepy'),
                  (HAPPY, 'happy'),
                  (LAUGHING, 'laughing'))
    rate = models.SmallIntegerField(_('Rate Index'), null=True, blank=True,
                                    choices=VOTE_RATES)

    # relations
    proposal = models.ForeignKey(to='deck.Proposal', related_name='votes')
    user = models.ForeignKey(to=settings.AUTH_USER_MODEL, related_name='votes')

    class Meta:
        verbose_name = _('Vote')
        verbose_name_plural = _('Votes')
        unique_together = (('proposal', 'user'),)

    def __str__(self):
        return six.text_type("{0.user}: {0.rate} in {0.proposal}".format(self))

    def save(self, *args, **kwargs):
        validation_message = None

        user_is_in_jury = self.proposal.event.jury.users.filter(
            pk=self.user.pk).exists()
        if (self.user.is_superuser or user_is_in_jury):
            pass
        elif self.user == self.proposal.author:
            validation_message = _(u'You cannot Rate your own proposals.')
        elif not self.proposal.event.allow_public_voting:
            validation_message = _(u"Proposal doesn't accept Public Voting.")

        if validation_message:
            raise ValidationError(_(validation_message))

        return super(Vote, self).save(*args, **kwargs)

class Activity(DeckBaseModel):
    PROPOSAL = 'proposal'
    WORKSHOP = 'workshop'
    OPENNING = 'openning'
    COFFEEBREAK = 'coffee-break'
    LUNCH = 'lunch'
    LIGHTNINGTALKS = 'lightning-talks'
    ENDING = 'ending'
    ACTIVITY_TYPES = (
        (PROPOSAL, _('Proposal')),
        (WORKSHOP, _('Workshop')),
        (OPENNING, _('Openning')),
        (COFFEEBREAK, _('Coffee Break')),
        (LUNCH, _('Lunch')),
        (LIGHTNINGTALKS, _('Lightning Talks')),
        (ENDING, _('Ending')),
    )
    start_timetable = models.TimeField(
        _('Start Timetable'), null=True, blank=False)
    end_timetable = models.TimeField(
        _('End Timetable'), null=True, blank=False)
    track_order = models.SmallIntegerField(_('Order'), null=True, blank=True)
    activity_type = models.CharField(
        _('Type'), choices=ACTIVITY_TYPES, default=PROPOSAL, max_length=50)

    # relations
    track = models.ForeignKey(to='deck.Track', related_name='activities',
                              null=True, blank=True)

    class Meta:
        ordering = ('track_order', 'start_timetable', 'pk')
        verbose_name = _('Activity')
        verbose_name_plural = _('Activities')

    @property
    def timetable(self):
        if all([self.start_timetable is None, self.end_timetable is None]):
            return '--:--'

        return '{0} - {1}'.format(
            self.start_timetable.strftime('%H:%M'),
            self.end_timetable.strftime('%H:%M')
        )

class Proposal(Activity):
    is_approved = models.BooleanField(_('Is approved'), default=False)
    more_information = models.TextField(
        _('More information'), max_length=10000, null=True, blank=True)

    # relations
    event = models.ForeignKey(to='deck.Event', related_name='proposals')

    class Meta:
        ordering = ['title']
        verbose_name = _('Proposal')
        verbose_name_plural = _('Proposals')

    def save(self, *args, **kwargs):
        if not self.pk and self.event.closing_date_is_passed:
            raise ValidationError(
                _("This Event doesn't accept Proposals anymore."))
        return super(Proposal, self).save(*args, **kwargs)

    @property
    def get_rate(self):
        rate = None
        try:
            rate = self.votes__rate__sum
        except AttributeError:
            rate = self.votes.aggregate(Sum('rate'))['rate__sum']
        finally:
            return rate or 0

    def rate(self, user, rate):
        rate_int = [r[0] for r in Vote.VOTE_RATES if rate in r][0]
        with transaction.atomic():
            self.votes.update_or_create(user=user, defaults={'rate': rate_int})

    def user_already_voted(self, user):
        if isinstance(user, AnonymousUser):
            return False
        return self.votes.filter(user=user).exists()

    def user_can_vote(self, user):
        can_vote = False
        if self.author == user and not self.event.author == user:
            pass
        elif self.event.allow_public_voting:
            can_vote = True
        elif user.is_superuser:
            can_vote = True
        elif self.event.jury.users.filter(pk=user.pk).exists():
            can_vote = True
        return can_vote

    def user_can_approve(self, user):
        can_approve = False
        if user.is_superuser:
            can_approve = True
        elif self.event.jury.users.filter(pk=user.pk).exists():
            can_approve = True
        return can_approve

    def get_absolute_url(self):
        return reverse('view_event', kwargs={'slug': self.event.slug}) + \
            '#' + self.slug

    def approve(self):
        if self.is_approved:
            raise ValidationError(_("This Proposal was already approved."))
        self.is_approved = True
        self.save()

    def disapprove(self):
        if not self.is_approved:
            raise ValidationError(_("This Proposal was already disapproved."))
        self.is_approved = False
        self.save()

@python_2_unicode_compatible
class Track(models.Model):
    title = models.CharField(_('Title'), max_length=200)
    slug = AutoSlugField(populate_from='title', overwrite=True,
                         max_length=200, unique=True, db_index=True)

    # relations
    event = models.ForeignKey(to='deck.Event', related_name='tracks')

    class Meta:
        verbose_name = _('Track')
        verbose_name_plural = _('Tracks')

    def __str__(self):
        return six.text_type('Track for: "%s"' % self.event.title)

    @property
    def proposals(self):
        return Proposal.objects.filter(
            pk__in=self.activities.values_list('pk', flat=True)
        )

class Event(DeckBaseModel):
    allow_public_voting = models.BooleanField(_('Allow Public Voting'),
                                              default=True)
    closing_date = models.DateTimeField(null=False, blank=False)
    slots = models.SmallIntegerField(_('Slots'), default=10)

    # relations
    jury = models.OneToOneField(to='jury.Jury', related_name='event',
                                null=True, blank=True)
    anonymous_voting = models.BooleanField(
        _('Anonymous Voting?'), default=False)

    class Meta:
        ordering = ['-closing_date', '-created_at']
        verbose_name = _('Event')
        verbose_name_plural = _('Events')

    @property
    def closing_date_is_passed(self):
        return timezone.now() > self.closing_date

    @property
    def closing_date_is_close(self):
        if self.closing_date_is_passed:
            return False
        return timezone.now() > self.closing_date - timezone.timedelta(days=7)

    def get_absolute_url(self):
        return reverse('view_event', kwargs={'slug': self.slug})

    def user_can_see_proposals(self, user):
        can_see_proposals = False
        if user.is_superuser or self.author == user:
            can_see_proposals = True
        elif self.allow_public_voting:
            can_see_proposals = True
        elif (not user.is_anonymous() and
              self.jury.users.filter(pk=user.pk).exists()):
            can_see_proposals = True
        return can_see_proposals

    def get_proposers_count(self):
        return self.proposals.values_list(
            'author', flat=True).distinct().count()

    def get_votes_count(self):
        return self.proposals.values_list('votes', flat=True).count()

    def get_votes_to_export(self):
        return self.proposals.values(
            'id', 'title', 'author__username', 'author__email'
        ).annotate(
            Sum('votes__rate')
        ).annotate(Count('votes'))

    def get_schedule(self):
        schedule = Activity.objects.filter(track__event=self)\
            .cached_authors()\
            .annotate(Sum('proposal__votes__rate'))\
            .extra(select=dict(track_isnull='track_id IS NULL'))\
            .order_by('track_isnull', 'track_order',
                      '-proposal__votes__rate__sum')
        return schedule

    def get_not_approved_schedule(self):
        return self.proposals\
            .cached_authors()\
            .filter(
                models.Q(is_approved=False) |
                models.Q(track__isnull=True))

@receiver(user_signed_up)
def send_welcome_mail(request, user, **kwargs):
    if not settings.SEND_NOTIFICATIONS:
        return
    message = render_to_string('mailing/welcome.txt')
    subject = _(u'Welcome')
    recipients = [user.email]
    send_mail(subject, message, settings.NO_REPLY_EMAIL, recipients)

@receiver(post_save, sender=Event)
def create_initial_jury(sender, instance, signal, created, **kwargs):
    if not created:
        return
    jury = Jury()
    jury.save()
    jury.users.add(instance.author)
    instance.jury = jury
    instance.save()

@receiver(post_save, sender=Event)
def create_initial_track(sender, instance, signal, created, **kwargs):
    if not created:
        return
    Track.objects.create(event=instance)

@receiver(post_delete, sender=Proposal)
def send_proposal_deleted_mail(sender, instance, **kwargs):
    if not settings.SEND_NOTIFICATIONS:
        return
    context = {'event_title': instance.event.title,
               'proposal_title': instance.title}
    message = render_to_string('mailing/jury_deleted_proposal.txt', context)
    subject = _(u'Proposal from %s just got deleted' % instance.event.title)
    recipients = instance.event.jury.users.values_list('email', flat=True)
    send_mail(subject, message, settings.NO_REPLY_EMAIL, recipients)
<|endoftext|>


<commit_before>from __future__ import print_function
from PySide import QtCore
from xml.etree import ElementTree
from collections import OrderedDict

try:
    from urllib2 import build_opener, URLError
    from urlparse import urljoin
except ImportError:  # >= 3.x
    from urllib.error import URLError
    from urllib.parse import urljoin

class Modem(QtCore.QObject):
    """Modem - class that represents HiLink modem"""
    levelChanged = QtCore.Signal(int)
    statusChanged = QtCore.Signal(str, str)
    signalParamsChanged = QtCore.Signal(OrderedDict)
    unreadMessagesCountChanged = QtCore.Signal(int)
    finished = QtCore.Signal()

    def __init__(self, ip):
        super(Modem, self).__init__()
        self._opener = build_opener()
        self._baseUrl = "http://{}".format(ip)

    def finish(self):
        self.finished.emit()

    def connect_(self):
        msg = """<?xml version="1.0" encoding="UTF-8"?><request><dataswitch>1</dataswitch></request>"""

        self._post("/api/dialup/mobile-dataswitch", msg)

    def disconnect(self):
        msg = """<?xml version="1.0" encoding="UTF-8"?><request><dataswitch>0</dataswitch></request>"""

        self._post("/api/dialup/mobile-dataswitch", msg)

    def reboot(self):
        msg = """<?xml version="1.0" encoding="UTF-8"?><request><Control>1</Control></request>"""
        self._post("/api/device/control", msg)

    def _post(self, section, msg):
        response = self._opener.open(urljoin(self._baseUrl, section),
                                     data=msg).read()
        print("[Response]", response)

    def _getXml(self, section):
        response = self._opener.open(urljoin(self._baseUrl, section),
                                     timeout=1).read()
        return ElementTree.fromstring(response)

    def _getTokens(self):
        """Get access tokens"""
        try:
            xml = self._getXml("/api/webserver/SesTokInfo")
        except URLError:
            return ("", "")
        else:
            return (xml.findtext("SesInfo", ""), xml.findtext("TokInfo", ""))

    def _updateTokens(self):
        session, postToken = self._getTokens()
        self._opener.addheaders = [("__RequestVerificationToken", postToken),
                                   ("Cookie", session)]

    def getSignalLevel(self, xml):
        return int(xml.findtext("SignalIcon", "0"))

    def getNetworkType(self, xml):
        types = {"0": "No Service", "1": "GSM", "2": "GPRS", "3": "EDGE",
                 "21": "IS-95A", "22": "IS-95B", "23": "CDMA 1X",
                 "24": "EV-DO Rev. 0", "25": "EV-DO Rev. A",
                 "26": "EV-DO Rev. A", "27": "Hybrid CDMA 1X",
                 "28": "Hybrid EV-DO Rev. 0", "29": "Hybrid EV-DO Rev. A",
                 "30": "Hybrid EV-DO Rev. A", "31": "eHPRD Rel. 0",
                 "32": "eHPRD Rel. A", "33": "eHPRD Rel. B",
                 "34": "Hybrid eHPRD Rel. 0", "35": "Hybrid eHPRD Rel. A",
                 "36": "Hybrid eHPRD Rel. B", "41": "WCDMA", "42": "HSDPA",
                 "43": "HSUPA", "44": "HSPA", "45": "HSPA+", "46": "DC-HSPA+",
                 "61": "TD-SCDMA", "62": "TD-HSDPA", "63": "TD-HSUPA",
                 "64": "TD-HSPA", "65": "TD-HSPA+", "81": "802.16e",
                 "101": "LTE"}
        return types[xml.findtext("CurrentNetworkTypeEx", "")]

    def getStatus(self, xml):
        states = {"900": "Connecting", "901": "Connected",
                  "902": "Disconnected", "903": "Disconnecting"}
        return states[xml.findtext("ConnectionStatus", "")]

    def getOperator(self, xml):
        shortName = xml.find("ShortName")
        if shortName is not None:
            return shortName.text
        else:
            fullName = xml.find("FullName")
            if fullName is not None:
                return fullName.text
        return ""

    def getSignalParams(self, xml):
        params = ["rssi", "rsrp", "rsrq", "rscp", "ecio", "sinr",
                  "cell_id", "pci"]
        values = OrderedDict()

        for key in params:
            value = xml.find(key).text
            if value:
                values[key] = "{key}: {val}".format(key=key.upper(),
                                                    val=value)
        return values

    def getUnreadMessageCount(self, xml):
        """Get number of unreaded messages"""
        return int(xml.find("UnreadMessage").text)

    def monitorMessages(self):
        """Monitor count of unreaded messages"""
        try:
            notifyXml = self._getXml("/api/monitoring/check-notifications")
            messageCount = self.getUnreadMessageCount(notifyXml)
        except URLError:
            import random
            self.unreadMessagesCountChanged.emit(random.randint(0, 100))
        else:
            self.unreadMessagesCountChanged.emit(messageCount)

    def monitorStatus(self):
        """Monitor connection status"""
        try:
            statusXml = self._getXml("/api/monitoring/status")
            plmnXml = self._getXml("/api/net/current-plmn")
        except URLError:
            import random
            self.levelChanged.emit(random.randint(0, 6))
            self.statusChanged.emit("No HiLink Detected", "")
        else:
            signalLevel = self.getSignalLevel(statusXml)
            self.levelChanged.emit(signalLevel)

            status = self.getStatus(statusXml)
            networkType = self.getNetworkType(statusXml)
            operator = self.getOperator(plmnXml)

            # fix space if we don't have op name
            op = networkType
            if operator:
                op = "%s %s" % (operator, networkType)
            self.statusChanged.emit(status, op)

    def monitorSignalParams(self):
        """Monitor signal parameters"""
        try:
            signalXml = self._getXml("/api/device/signal")
        except URLError:
            self.signalParamsChanged.emit({})
        else:
            params = self.getSignalParams(signalXml)
            self.signalParamsChanged.emit(params)

    def monitor(self):
        self._updateTokens()
        self.monitorMessages()
        self.monitorStatus()
        self.monitorSignalParams()
<commit_msg>fix import error for python3<commit_after>from __future__ import print_function
from PySide import QtCore
from xml.etree import ElementTree
from collections import OrderedDict

try:
    from urllib2 import build_opener, URLError
    from urlparse import urljoin
except ImportError:  # >= 3.x
    from urllib.error import URLError
    from urllib.parse import urljoin
    from urllib.request import build_opener

class Modem(QtCore.QObject):
    """Modem - class that represents HiLink modem"""
    levelChanged = QtCore.Signal(int)
    statusChanged = QtCore.Signal(str, str)
    signalParamsChanged = QtCore.Signal(OrderedDict)
    unreadMessagesCountChanged = QtCore.Signal(int)
    finished = QtCore.Signal()

    def __init__(self, ip):
        super(Modem, self).__init__()
        self._opener = build_opener()
        self._baseUrl = "http://{}".format(ip)

    def finish(self):
        self.finished.emit()

    def connect_(self):
        msg = """<?xml version="1.0" encoding="UTF-8"?><request><dataswitch>1</dataswitch></request>"""

        self._post("/api/dialup/mobile-dataswitch", msg)

    def disconnect(self):
        msg = """<?xml version="1.0" encoding="UTF-8"?><request><dataswitch>0</dataswitch></request>"""

        self._post("/api/dialup/mobile-dataswitch", msg)

    def reboot(self):
        msg = """<?xml version="1.0" encoding="UTF-8"?><request><Control>1</Control></request>"""
        self._post("/api/device/control", msg)

    def _post(self, section, msg):
        response = self._opener.open(urljoin(self._baseUrl, section),
                                     data=msg).read()
        print("[Response]", response)

    def _getXml(self, section):
        response = self._opener.open(urljoin(self._baseUrl, section),
                                     timeout=1).read()
        return ElementTree.fromstring(response)

    def _getTokens(self):
        """Get access tokens"""
        try:
            xml = self._getXml("/api/webserver/SesTokInfo")
        except URLError:
            return ("", "")
        else:
            return (xml.findtext("SesInfo", ""), xml.findtext("TokInfo", ""))

    def _updateTokens(self):
        session, postToken = self._getTokens()
        self._opener.addheaders = [("__RequestVerificationToken", postToken),
                                   ("Cookie", session)]

    def getSignalLevel(self, xml):
        return int(xml.findtext("SignalIcon", "0"))

    def getNetworkType(self, xml):
        types = {"0": "No Service", "1": "GSM", "2": "GPRS", "3": "EDGE",
                 "21": "IS-95A", "22": "IS-95B", "23": "CDMA 1X",
                 "24": "EV-DO Rev. 0", "25": "EV-DO Rev. A",
                 "26": "EV-DO Rev. A", "27": "Hybrid CDMA 1X",
                 "28": "Hybrid EV-DO Rev. 0", "29": "Hybrid EV-DO Rev. A",
                 "30": "Hybrid EV-DO Rev. A", "31": "eHPRD Rel. 0",
                 "32": "eHPRD Rel. A", "33": "eHPRD Rel. B",
                 "34": "Hybrid eHPRD Rel. 0", "35": "Hybrid eHPRD Rel. A",
                 "36": "Hybrid eHPRD Rel. B", "41": "WCDMA", "42": "HSDPA",
                 "43": "HSUPA", "44": "HSPA", "45": "HSPA+", "46": "DC-HSPA+",
                 "61": "TD-SCDMA", "62": "TD-HSDPA", "63": "TD-HSUPA",
                 "64": "TD-HSPA", "65": "TD-HSPA+", "81": "802.16e",
                 "101": "LTE"}
        return types[xml.findtext("CurrentNetworkTypeEx", "")]

    def getStatus(self, xml):
        states = {"900": "Connecting", "901": "Connected",
                  "902": "Disconnected", "903": "Disconnecting"}
        return states[xml.findtext("ConnectionStatus", "")]

    def getOperator(self, xml):
        shortName = xml.find("ShortName")
        if shortName is not None:
            return shortName.text
        else:
            fullName = xml.find("FullName")
            if fullName is not None:
                return fullName.text
        return ""

    def getSignalParams(self, xml):
        params = ["rssi", "rsrp", "rsrq", "rscp", "ecio", "sinr",
                  "cell_id", "pci"]
        values = OrderedDict()

        for key in params:
            value = xml.find(key).text
            if value:
                values[key] = "{key}: {val}".format(key=key.upper(),
                                                    val=value)
        return values

    def getUnreadMessageCount(self, xml):
        """Get number of unreaded messages"""
        return int(xml.find("UnreadMessage").text)

    def monitorMessages(self):
        """Monitor count of unreaded messages"""
        try:
            notifyXml = self._getXml("/api/monitoring/check-notifications")
            messageCount = self.getUnreadMessageCount(notifyXml)
        except URLError:
            import random
            self.unreadMessagesCountChanged.emit(random.randint(0, 100))
        else:
            self.unreadMessagesCountChanged.emit(messageCount)

    def monitorStatus(self):
        """Monitor connection status"""
        try:
            statusXml = self._getXml("/api/monitoring/status")
            plmnXml = self._getXml("/api/net/current-plmn")
        except URLError:
            import random
            self.levelChanged.emit(random.randint(0, 6))
            self.statusChanged.emit("No HiLink Detected", "")
        else:
            signalLevel = self.getSignalLevel(statusXml)
            self.levelChanged.emit(signalLevel)

            status = self.getStatus(statusXml)
            networkType = self.getNetworkType(statusXml)
            operator = self.getOperator(plmnXml)

            # fix space if we don't have op name
            op = networkType
            if operator:
                op = "%s %s" % (operator, networkType)
            self.statusChanged.emit(status, op)

    def monitorSignalParams(self):
        """Monitor signal parameters"""
        try:
            signalXml = self._getXml("/api/device/signal")
        except URLError:
            self.signalParamsChanged.emit({})
        else:
            params = self.getSignalParams(signalXml)
            self.signalParamsChanged.emit(params)

    def monitor(self):
        self._updateTokens()
        self.monitorMessages()
        self.monitorStatus()
        self.monitorSignalParams()
<|endoftext|>


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

# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from abc import ABCMeta, abstractmethod

from six import with_metaclass

try:
    from __main__ import display
except ImportError:
    from ansible.utils.display import Display
    display = Display()

__all__ = ['LookupBase']

class LookupBase(with_metaclass(ABCMeta, object)):
    def __init__(self, loader=None, templar=None, **kwargs):
        self._loader = loader
        self._templar = templar
        self._display = display

    def get_basedir(self, variables):
        if 'role_path' in variables:
            return variables['role_path']
        else:
            return self._loader.get_basedir()

    @staticmethod
    def _flatten(self, terms):
        ret = []
        for term in terms:
            if isinstance(term, (list, tuple)):
                ret.extend(term)
            else:
                ret.append(term)
        return ret

    @staticmethod
    def _combine(a, b):
        results = []
        for x in a:
            for y in b:
                results.append(self._flatten([x,y]))
        return results

    @staticmethod
    def _flatten_hash_to_list(terms):
        ret = []
        for key in terms:
            ret.append({'key': key, 'value': terms[key]})
        return ret

    @abstractmethod
    def run(self, terms, variables=None, **kwargs):
        """
        When the playbook specifies a lookup, this method is run.  The
        arguments to the lookup become the arguments to this method.  One
        additional keyword argument named ``variables`` is added to the method
        call.  It contains the variables available to ansible at the time the
        lookup is templated.  For instance::

            "{{ lookup('url', 'https://toshio.fedorapeople.org/one.txt', validate_certs=True) }}"

        would end up calling the lookup plugin named url's run method like this::
            run(['https://toshio.fedorapeople.org/one.txt'], variables=available_variables, validate_certs=True)

        Lookup plugins can be used within playbooks for looping.  When this
        happens, the first argument is a list containing the terms.  Lookup
        plugins can also be called from within playbooks to return their
        values into a variable or parameter.  If the user passes a string in
        this case, it is converted into a list.

        Errors encountered during execution should be returned by raising
        AnsibleError() with a message describing the error.

        Any strings returned by this method that could ever contain non-ascii
        must be converted into python's unicode type as the strings will be run
        through jinja2 which has this requirement.  You can use::

            from ansible.module_utils.unicode import to_unicode
            result_string = to_unicode(result_string)
        """
        pass
<commit_msg>Cleanup bug from moving base lookup methods to staticmethods<commit_after># (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.

# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from abc import ABCMeta, abstractmethod

from six import with_metaclass

try:
    from __main__ import display
except ImportError:
    from ansible.utils.display import Display
    display = Display()

__all__ = ['LookupBase']

class LookupBase(with_metaclass(ABCMeta, object)):
    def __init__(self, loader=None, templar=None, **kwargs):
        self._loader = loader
        self._templar = templar
        self._display = display

    def get_basedir(self, variables):
        if 'role_path' in variables:
            return variables['role_path']
        else:
            return self._loader.get_basedir()

    @staticmethod
    def _flatten(terms):
        ret = []
        for term in terms:
            if isinstance(term, (list, tuple)):
                ret.extend(term)
            else:
                ret.append(term)
        return ret

    @staticmethod
    def _combine(a, b):
        results = []
        for x in a:
            for y in b:
                results.append(self._flatten([x,y]))
        return results

    @staticmethod
    def _flatten_hash_to_list(terms):
        ret = []
        for key in terms:
            ret.append({'key': key, 'value': terms[key]})
        return ret

    @abstractmethod
    def run(self, terms, variables=None, **kwargs):
        """
        When the playbook specifies a lookup, this method is run.  The
        arguments to the lookup become the arguments to this method.  One
        additional keyword argument named ``variables`` is added to the method
        call.  It contains the variables available to ansible at the time the
        lookup is templated.  For instance::

            "{{ lookup('url', 'https://toshio.fedorapeople.org/one.txt', validate_certs=True) }}"

        would end up calling the lookup plugin named url's run method like this::
            run(['https://toshio.fedorapeople.org/one.txt'], variables=available_variables, validate_certs=True)

        Lookup plugins can be used within playbooks for looping.  When this
        happens, the first argument is a list containing the terms.  Lookup
        plugins can also be called from within playbooks to return their
        values into a variable or parameter.  If the user passes a string in
        this case, it is converted into a list.

        Errors encountered during execution should be returned by raising
        AnsibleError() with a message describing the error.

        Any strings returned by this method that could ever contain non-ascii
        must be converted into python's unicode type as the strings will be run
        through jinja2 which has this requirement.  You can use::

            from ansible.module_utils.unicode import to_unicode
            result_string = to_unicode(result_string)
        """
        pass
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import datetime

from concurrency.views import ConflictResponse
from digg_paginator import DiggPaginator
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import JsonResponse
from django.template import loader
from django.template.context import RequestContext
from django.views.generic import DetailView
from django.views.generic import FormView, ListView

from advertising.mixins import AdsMixin
from .forms import AddNewsForm
from .mixins import FeedItemsMixin, CacheMixin, FavoriteItemsMixin
from .models import Issue, Item

def conflict(request, target=None, template_name='409.html'):
    template = loader.get_template(template_name)
    message = 'Вот незадача! Кажется эту новость обновили раньше =( \
            Нужно обновить новость для того чтобы внести правки.'

    ctx = RequestContext(request, {'message': message})
    return ConflictResponse(template.render(ctx))

class IssuesList(CacheMixin, ListView):
    """Список выпусков."""
    template_name = 'digest/pages/issues_list.html'
    queryset = Issue.objects.filter(status='active').order_by('-published_at')
    context_object_name = 'items'
    paginate_by = 12
    paginator_class = DiggPaginator
    cache_timeout = 300

    def get_context_data(self, **kwargs):
        context = super(IssuesList, self).get_context_data(**kwargs)
        context['active_menu_item'] = 'issues_list'
        return context

class IssueView(CacheMixin, FavoriteItemsMixin, FeedItemsMixin, AdsMixin,
                DetailView):
    """Просмотр выпуска."""
    template_name = 'digest/pages/issue.html'
    model = Issue
    cache_timeout = 300

    def get_context_data(self, **kwargs):
        context = super(IssueView, self).get_context_data(**kwargs)

        items = self.object.item_set.filter(status='active').order_by(
            '-section__priority', '-priority')

        context.update({
            'items': items,
            'active_menu_item': 'issue_view',
        })

        return context

class ItemView(FavoriteItemsMixin, CacheMixin, DetailView):
    """Просмотр отдельной новости."""
    template_name = 'digest/pages/news_item.html'
    context_object_name = 'item'
    model = Item
    cache_timeout = 300

class ItemsByTagView(AdsMixin, FavoriteItemsMixin, CacheMixin, ListView):
    """Лента новостей."""
    template_name = 'news_by_tag.html'
    context_object_name = 'items'
    paginate_by = 20
    paginator_class = DiggPaginator
    model = Item
    cache_timeout = 300

    def get_queryset(self):
        items = super(ItemsByTagView, self).get_queryset() \
            .filter(status='active',
                    activated_at__lte=datetime.datetime.now())
        tag = self.request.GET.get('tag')
        if tag in ['ru', 'en']:
            items = items.filter(tags__name__in=tag)

        items = items.prefetch_related('issue', 'section')
        items = items.order_by('-created_at', '-related_to_date')
        return items

class NewsList(FavoriteItemsMixin, CacheMixin, ListView):
    """Лента новостей."""
    template_name = 'digest/pages/news_list.html'
    context_object_name = 'items'
    paginate_by = 20
    paginator_class = DiggPaginator
    model = Item
    cache_timeout = 300

    def get_queryset(self):
        items = super(NewsList, self).get_queryset() \
            .filter(status='active',
                    activated_at__lte=datetime.datetime.now())
        lang = self.request.GET.get('lang')
        if lang in ['ru', 'en']:
            items = items.filter(language=lang)

        search = self.request.GET.get('q')
        if search:
            filters = Q(title__icontains=search) | Q(
                description__icontains=search)
            items = items.filter(filters)

        tag = self.request.GET.get('tag')
        if tag:
            items = items.filter(tags__name__in=[tag])

        section = self.request.GET.get('section', '')
        if section.isdigit():
            items = items.filter(section__pk=section)

        items = items.prefetch_related('issue', 'section')
        items = items.order_by('-created_at', '-related_to_date')
        return items

    def get_context_data(self, **kwargs):
        context = super(NewsList, self).get_context_data(**kwargs)
        context['active_menu_item'] = 'feed'
        return context

class AddNews(FormView):
    template_name = 'digest/pages/add_news.html'
    form_class = AddNewsForm

    def get_success_url(self):
        title = self.request.POST['title'].strip() or 'Без заголовка'
        link = self.request.POST['link']
        description = self.request.POST['description']
        section = self.request.POST['section']
        Item.objects.create(title=title,
                            link=link,
                            description=description,
                            status='pending',
                            related_to_date=datetime.datetime.now(),
                            section_id=section)
        messages.info(self.request,
                      'Ваша ссылка успешно добавлена на рассмотрение')
        return reverse('frontend:index')

def get_items_json(request, year, month, day):
    result = {}
    items = Item.objects.filter(
        status='active',
        is_editors_choice=True,
        related_to_date__year=int(year),
        related_to_date__month=int(month),
        related_to_date__day=int(day),
    )
    result['ok'] = bool(items)
    if items:
        keys = [
            'title',
            'description',
            'section__title',
            'link',
            'language',
        ]
        result['items'] = list(items.values(*keys))
    return JsonResponse(result)
<commit_msg>change ordering news in /feed<commit_after># -*- coding: utf-8 -*-

import datetime

from concurrency.views import ConflictResponse
from digg_paginator import DiggPaginator
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.http import JsonResponse
from django.template import loader
from django.template.context import RequestContext
from django.views.generic import DetailView
from django.views.generic import FormView, ListView

from advertising.mixins import AdsMixin
from .forms import AddNewsForm
from .mixins import FeedItemsMixin, CacheMixin, FavoriteItemsMixin
from .models import Issue, Item

def conflict(request, target=None, template_name='409.html'):
    template = loader.get_template(template_name)
    message = 'Вот незадача! Кажется эту новость обновили раньше =( \
            Нужно обновить новость для того чтобы внести правки.'

    ctx = RequestContext(request, {'message': message})
    return ConflictResponse(template.render(ctx))

class IssuesList(CacheMixin, ListView):
    """Список выпусков."""
    template_name = 'digest/pages/issues_list.html'
    queryset = Issue.objects.filter(status='active').order_by('-published_at')
    context_object_name = 'items'
    paginate_by = 12
    paginator_class = DiggPaginator
    cache_timeout = 300

    def get_context_data(self, **kwargs):
        context = super(IssuesList, self).get_context_data(**kwargs)
        context['active_menu_item'] = 'issues_list'
        return context

class IssueView(CacheMixin, FavoriteItemsMixin, FeedItemsMixin, AdsMixin,
                DetailView):
    """Просмотр выпуска."""
    template_name = 'digest/pages/issue.html'
    model = Issue
    cache_timeout = 300

    def get_context_data(self, **kwargs):
        context = super(IssueView, self).get_context_data(**kwargs)

        items = self.object.item_set.filter(status='active').order_by(
            '-section__priority', '-priority')

        context.update({
            'items': items,
            'active_menu_item': 'issue_view',
        })

        return context

class ItemView(FavoriteItemsMixin, CacheMixin, DetailView):
    """Просмотр отдельной новости."""
    template_name = 'digest/pages/news_item.html'
    context_object_name = 'item'
    model = Item
    cache_timeout = 300

class ItemsByTagView(AdsMixin, FavoriteItemsMixin, CacheMixin, ListView):
    """Лента новостей."""
    template_name = 'news_by_tag.html'
    context_object_name = 'items'
    paginate_by = 20
    paginator_class = DiggPaginator
    model = Item
    cache_timeout = 300

    def get_queryset(self):
        items = super(ItemsByTagView, self).get_queryset() \
            .filter(status='active',
                    activated_at__lte=datetime.datetime.now())
        tag = self.request.GET.get('tag')
        if tag in ['ru', 'en']:
            items = items.filter(tags__name__in=tag)

        items = items.prefetch_related('issue', 'section')
        items = items.order_by('-activated_at', '-related_to_date')
        return items

class NewsList(FavoriteItemsMixin, CacheMixin, ListView):
    """Лента новостей."""
    template_name = 'digest/pages/news_list.html'
    context_object_name = 'items'
    paginate_by = 20
    paginator_class = DiggPaginator
    model = Item
    cache_timeout = 300

    def get_queryset(self):
        items = super(NewsList, self).get_queryset() \
            .filter(status='active',
                    activated_at__lte=datetime.datetime.now())
        lang = self.request.GET.get('lang')
        if lang in ['ru', 'en']:
            items = items.filter(language=lang)

        search = self.request.GET.get('q')
        if search:
            filters = Q(title__icontains=search) | Q(
                description__icontains=search)
            items = items.filter(filters)

        tag = self.request.GET.get('tag')
        if tag:
            items = items.filter(tags__name__in=[tag])

        section = self.request.GET.get('section', '')
        if section.isdigit():
            items = items.filter(section__pk=section)

        items = items.prefetch_related('issue', 'section')
        items = items.order_by('-activated_at', '-related_to_date')
        return items

    def get_context_data(self, **kwargs):
        context = super(NewsList, self).get_context_data(**kwargs)
        context['active_menu_item'] = 'feed'
        return context

class AddNews(FormView):
    template_name = 'digest/pages/add_news.html'
    form_class = AddNewsForm

    def get_success_url(self):
        title = self.request.POST['title'].strip() or 'Без заголовка'
        link = self.request.POST['link']
        description = self.request.POST['description']
        section = self.request.POST['section']
        Item.objects.create(title=title,
                            link=link,
                            description=description,
                            status='pending',
                            related_to_date=datetime.datetime.now(),
                            section_id=section)
        messages.info(self.request,
                      'Ваша ссылка успешно добавлена на рассмотрение')
        return reverse('frontend:index')

def get_items_json(request, year, month, day):
    result = {}
    items = Item.objects.filter(
        status='active',
        is_editors_choice=True,
        related_to_date__year=int(year),
        related_to_date__month=int(month),
        related_to_date__day=int(day),
    )
    result['ok'] = bool(items)
    if items:
        keys = [
            'title',
            'description',
            'section__title',
            'link',
            'language',
        ]
        result['items'] = list(items.values(*keys))
    return JsonResponse(result)
<|endoftext|>


<commit_before># coding=UTF8
__author__ = 'daedaluschan'

# importing libraries

import sys, time
import telepot
from telepot.delegate import per_chat_id, create_open

from datetime import date
from types import *
from enum import Enum
import uuid

from types import  *

# Constants & global data

allPoll = {}
botName = 'HKGathering_bot'
start_private_url = 'https://telegram.me/' + botName + '?start='
start_group_url = 'https://telegram.me/' + botName + '?startgroup='

# Defining enums

class ConverType(Enum):
    nothing = 1
    create_poll = 2
    response_poll = 3

class CreatePollFlow(Enum):
    not_start = 1
    poll_question = 2
    poll_choice = 3

# Response data structure

class Response():
    def __init__(self):
        self.userid = 0
        self.display_name = ''
        self.preference = []

    def __str__(self):
        return '[response_obj][' + self.userid.__str__() + '][' + self.display_name + '][' + \
               len(self.preference).__str__() + ']'

    @property
    def userid(self):
        return self._userid

    @userid.setter
    def userid(self, value):
        self._userid = value

    @property
    def preference(self):
        return self._preference

    @preference.setter
    def preference(self, value):
        self._preference = value

    @property
    def display_name(self):
        return self._display_name

    @display_name.setter
    def display_name(self, value):
        self._display_name = value

# Poll data structure

class Poll():
    def __init__(self):
        self.question = ''
        self.creatorId = 0
        self.choices = []
        self.groupId = 0
        self.response = {}

    def __str__(self):
        choice_str = ''
        response_str = ''
        for each_choice in self.choices:
            choice_str = choice_str + ' - ' + each_choice
        for each_response in self.response:
            response_str = response_str + '<' + self.response[each_response].__str__() + '>'
        return '[Poll_obj][question: ' + self.question + '][choice: ' + choice_str + '][group: ' + \
               self.groupId.__str__() + '][all_resp: ' + response_str + ']'

    @property
    def question(self):
        return self._question

    @question.setter
    def question(self, value):
        self._question = value

    @property
    def creatorId(self):
        return self._creatorId

    @creatorId.setter
    def creatorId(self, value):
        self._creatorId = value

    @property
    def choices(self):
        return self._choices

    @choices.setter
    def choices(self, value):
        self._choices = value

    @property
    def groupId(self):
        return self._groupId

    @groupId.setter
    def groupId(self, value):
        self._groupId = value

    @property
    def survey_str(self, response_attached=[]):
        choice_str = ''
        i = 1
        for choice in self.choices:
            if len(response_attached) == 0:
                choice_str = choice_str + '- ' + choice.encode('utf-8') + '\n'
            else:
                choice_str = choice_str + '- /' + i.__str__() + ' ' + choice.encode('utf-8') + \
                ' -- 現在回應：' + 'Yes' if response_attached[i-1] else 'No' +' \n'
            i += 1

        survey_text = '依家問你：' + self.question.encode('utf-8') + '\n\n' + '現有選擇係：\n\n' + choice_str + '\n'

        return survey_text

    @property
    def response(self):
        return self._response

    @response.setter
    def response(self, value):
        self._response = value

    def genNullResponse(self):
        preference_vector = []
        for each_choice in self.choices:
            preference_vector.append(False)
        return preference_vector

# main class of message handling

class HKGathering(telepot.helper.ChatHandler):
    def __init__(self, seed_tuple, timeout):
        super(HKGathering, self).__init__(seed_tuple, timeout)
        print('constructor is being called')
        self._converType = ConverType.nothing
        self._createPollFlow = CreatePollFlow.not_start
        self.__uid = ''
        self._poll = Poll()

    def complte_poll_creation(self):
        self.__uid = uuid.uuid4().hex
        allPoll[self.__uid] = self._poll
        self.sender.sendMessage(text='用呢條 link 將問題放落 chat group 裡邊：\n' +
                                     start_group_url + self.__uid)
        self._converType = ConverType.nothing

    def get_invited(self, poll_id):
        self._poll = allPoll[poll_id]
        print('Linked poll: ' + self._poll.__str__())
        choice_str = ''
        for choice in self._poll.choices:
            choice_str = choice_str + choice.encode('utf-8') + '\n'
        ans_link = '/answer' +'_' + poll_id.encode(encoding='utf-8')
        show_keyboard = {'keyboard': [['開始回應']]}

        self.sender.sendMessage(text=self._poll.survey_str + '\n' +
                                     '請用 ' + ans_link +  ' 回應問題。\n' +
                                     '或者用 pop up 鍵盤開始回應。',
                                reply_markup=show_keyboard)

    def initiate_survey(self, poll_id, target_id, display_name):
        print('answer to: ' + target_id.__str__())
        new_response = Response()
        new_response.userid = target_id
        new_response.display_name = display_name
        new_response.preference = allPoll[poll_id].genNullResponse()
        allPoll[poll_id].response[target_id.__str__()] = new_response
        # allPoll[poll_id].response.append({target_id.__str__(): new_response})

        print ('new_response: ' + new_response.__str__())
        print ('saved resposne: ' + allPoll[poll_id].response[target_id.__str__()].__str__())

        show_keyboard = {'keyboard': [['開始']]}
        self.bot.sendMessage(target_id,
                             text=self._poll.survey_str + '\n' +
                                  '請用 /begin 或者用 pop up 鍵盤開始。',
                             reply_markup=show_keyboard)

    def start_survey(self, poll_id, userid):
        print('start survey with poll id: ' + poll_id)
        self._poll = allPoll[poll_id]
        self.sender.sendMessage(text=self._poll.survey_str(response_attached=allPoll[poll_id].response[userid.__str__()]) +
                                     '\n' + '或者用 /add_pref 加入新選項。')

    def on_message(self, msg):
        print('on_message() is being called')
        print('==== all poll in cache ====')
        if len(allPoll) == 0:
            print('No poll yet')
        else:
            for each_poll in allPoll:
                print(allPoll[each_poll].__str__())
        print('========== END ============')
        flavor = telepot.flavor(msg)

        print('flavor: ' + flavor)

        # normal message
        if flavor == 'normal':
            content_type, chat_type, _chat_id = telepot.glance2(msg)
            print('Normal Message:', content_type, chat_type, _chat_id, '; message content: ', msg)

            if content_type == 'text' and chat_type == 'private':

                if self._converType == ConverType.nothing:

                    if msg['text'] == '/start':
                        self.sender.sendMessage(text='今日的日期係：' + str(date.today()) + '. \n' +
                                                     '用 /new 黎 create 一個新問題，' +
                                                     '或者用 /help 睇其他選項。')
                    elif msg['text'] == '/new':
                        self._converType = ConverType.create_poll
                        self._createPollFlow = CreatePollFlow.poll_question
                        self._poll.creatorId = msg['from']['id']
                        self.sender.sendMessage(text='唔該 send 你個問題俾我。')

                    elif msg['text'] == '/help':
                        self.sender.sendMessage(text='用 /new 黎 create 一個新問題，\n' +
                                                     '或者用 /result 黎查詢回應統計。\n')

                    elif msg['text'].encode(encoding='utf-8') == '開始' or msg['text'].startswith('/begin'):
                        found_poll = 0
                        for poll_key in allPoll.keys():
                            print ('in_all_poll: ' + allPoll[poll_key].__str__())
                            for each_resp in allPoll[poll_key].response:
                                print('each_resp: ' + allPoll[poll_key].reponse[each_resp].__str__())
                                if allPoll[poll_key].reponse[each_resp].userid == msg['from']['id']:
                                    found_poll = poll_key
                        if found_poll != 0:
                            self._converType = ConverType.response_poll
                            self.start_survey(found_poll, msg['from']['id'])
                        else:
                            self.sender.sendMessage(text='搵唔到你的問題。')
                    else:
                        self.sender.sendMessage(text='唔知你想點，麻煩你再試過。\n' +
                                                     '或者用 /help 睇其他選項。')
                elif self._converType == ConverType.create_poll:
                    if msg['text'] == '/done':
                        self.complte_poll_creation()
                    elif msg['text'] != '':
                        if self._createPollFlow == CreatePollFlow.poll_question:
                            self._poll.question = msg['text']
                            self._createPollFlow = CreatePollFlow.poll_choice
                            self.sender.sendMessage(text='好，咁你自己有乜意見？')
                        elif self._createPollFlow == CreatePollFlow.poll_choice:
                            self._poll.choices.append(msg['text'])
                            self.sender.sendMessage(text='好，仲有冇？有就繼續 send 下個個選擇。\n' +
                                                         '如果冇就用 /done 完成建立問題。')

            elif content_type == 'text' and chat_type == 'group':
                if msg['text'].startswith('/start@' + botName):
                    print('invited into group')
                    poll_id = msg['text'].split(' ')[1]
                    self.get_invited(poll_id)
                    allPoll[poll_id].groupId = _chat_id
                elif msg['text'].startswith('/answer_'):
                    poll_id = msg['text'].split('_')[1].split('@')[0]
                    self.initiate_survey(poll_id,
                                         target_id=msg['from']['id'],
                                         display_name=msg['from']['first_name'] + ' ' + msg['from']['last_name'])
                elif msg['text'].encode(encoding='utf-8') == '開始回應':
                    orig_text = msg['reply_to_message']['text']
                    poll_id = orig_text.split('/answer_')[1].split(' ')[0]
                    self.initiate_survey(poll_id,
                                         target_id=msg['from']['id'],
                                         display_name=msg['from']['first_name'] + ' ' + msg['from']['last_name'])

            print('Poll:' + self._poll.__str__())
        else:
            raise telepot.BadFlavor(msg)

TOKEN = sys.argv[1]  # get token from command-line

bot = telepot.DelegatorBot(TOKEN, [
    (per_chat_id(), create_open(HKGathering, timeout=20)), ])
print('Listening ...')
bot.notifyOnMessage(run_forever=True)
<commit_msg>typo on response<commit_after># coding=UTF8
__author__ = 'daedaluschan'

# importing libraries

import sys, time
import telepot
from telepot.delegate import per_chat_id, create_open

from datetime import date
from types import *
from enum import Enum
import uuid

from types import  *

# Constants & global data

allPoll = {}
botName = 'HKGathering_bot'
start_private_url = 'https://telegram.me/' + botName + '?start='
start_group_url = 'https://telegram.me/' + botName + '?startgroup='

# Defining enums

class ConverType(Enum):
    nothing = 1
    create_poll = 2
    response_poll = 3

class CreatePollFlow(Enum):
    not_start = 1
    poll_question = 2
    poll_choice = 3

# Response data structure

class Response():
    def __init__(self):
        self.userid = 0
        self.display_name = ''
        self.preference = []

    def __str__(self):
        return '[response_obj][' + self.userid.__str__() + '][' + self.display_name + '][' + \
               len(self.preference).__str__() + ']'

    @property
    def userid(self):
        return self._userid

    @userid.setter
    def userid(self, value):
        self._userid = value

    @property
    def preference(self):
        return self._preference

    @preference.setter
    def preference(self, value):
        self._preference = value

    @property
    def display_name(self):
        return self._display_name

    @display_name.setter
    def display_name(self, value):
        self._display_name = value

# Poll data structure

class Poll():
    def __init__(self):
        self.question = ''
        self.creatorId = 0
        self.choices = []
        self.groupId = 0
        self.response = {}

    def __str__(self):
        choice_str = ''
        response_str = ''
        for each_choice in self.choices:
            choice_str = choice_str + ' - ' + each_choice
        for each_response in self.response:
            response_str = response_str + '<' + self.response[each_response].__str__() + '>'
        return '[Poll_obj][question: ' + self.question + '][choice: ' + choice_str + '][group: ' + \
               self.groupId.__str__() + '][all_resp: ' + response_str + ']'

    @property
    def question(self):
        return self._question

    @question.setter
    def question(self, value):
        self._question = value

    @property
    def creatorId(self):
        return self._creatorId

    @creatorId.setter
    def creatorId(self, value):
        self._creatorId = value

    @property
    def choices(self):
        return self._choices

    @choices.setter
    def choices(self, value):
        self._choices = value

    @property
    def groupId(self):
        return self._groupId

    @groupId.setter
    def groupId(self, value):
        self._groupId = value

    @property
    def survey_str(self, response_attached=[]):
        choice_str = ''
        i = 1
        for choice in self.choices:
            if len(response_attached) == 0:
                choice_str = choice_str + '- ' + choice.encode('utf-8') + '\n'
            else:
                choice_str = choice_str + '- /' + i.__str__() + ' ' + choice.encode('utf-8') + \
                ' -- 現在回應：' + 'Yes' if response_attached[i-1] else 'No' +' \n'
            i += 1

        survey_text = '依家問你：' + self.question.encode('utf-8') + '\n\n' + '現有選擇係：\n\n' + choice_str + '\n'

        return survey_text

    @property
    def response(self):
        return self._response

    @response.setter
    def response(self, value):
        self._response = value

    def genNullResponse(self):
        preference_vector = []
        for each_choice in self.choices:
            preference_vector.append(False)
        return preference_vector

# main class of message handling

class HKGathering(telepot.helper.ChatHandler):
    def __init__(self, seed_tuple, timeout):
        super(HKGathering, self).__init__(seed_tuple, timeout)
        print('constructor is being called')
        self._converType = ConverType.nothing
        self._createPollFlow = CreatePollFlow.not_start
        self.__uid = ''
        self._poll = Poll()

    def complte_poll_creation(self):
        self.__uid = uuid.uuid4().hex
        allPoll[self.__uid] = self._poll
        self.sender.sendMessage(text='用呢條 link 將問題放落 chat group 裡邊：\n' +
                                     start_group_url + self.__uid)
        self._converType = ConverType.nothing

    def get_invited(self, poll_id):
        self._poll = allPoll[poll_id]
        print('Linked poll: ' + self._poll.__str__())
        choice_str = ''
        for choice in self._poll.choices:
            choice_str = choice_str + choice.encode('utf-8') + '\n'
        ans_link = '/answer' +'_' + poll_id.encode(encoding='utf-8')
        show_keyboard = {'keyboard': [['開始回應']]}

        self.sender.sendMessage(text=self._poll.survey_str + '\n' +
                                     '請用 ' + ans_link +  ' 回應問題。\n' +
                                     '或者用 pop up 鍵盤開始回應。',
                                reply_markup=show_keyboard)

    def initiate_survey(self, poll_id, target_id, display_name):
        print('answer to: ' + target_id.__str__())
        new_response = Response()
        new_response.userid = target_id
        new_response.display_name = display_name
        new_response.preference = allPoll[poll_id].genNullResponse()
        allPoll[poll_id].response[target_id.__str__()] = new_response
        # allPoll[poll_id].response.append({target_id.__str__(): new_response})

        print ('new_response: ' + new_response.__str__())
        print ('saved resposne: ' + allPoll[poll_id].response[target_id.__str__()].__str__())

        show_keyboard = {'keyboard': [['開始']]}
        self.bot.sendMessage(target_id,
                             text=self._poll.survey_str + '\n' +
                                  '請用 /begin 或者用 pop up 鍵盤開始。',
                             reply_markup=show_keyboard)

    def start_survey(self, poll_id, userid):
        print('start survey with poll id: ' + poll_id)
        self._poll = allPoll[poll_id]
        self.sender.sendMessage(text=self._poll.survey_str(response_attached=allPoll[poll_id].response[userid.__str__()]) +
                                     '\n' + '或者用 /add_pref 加入新選項。')

    def on_message(self, msg):
        print('on_message() is being called')
        print('==== all poll in cache ====')
        if len(allPoll) == 0:
            print('No poll yet')
        else:
            for each_poll in allPoll:
                print(allPoll[each_poll].__str__())
        print('========== END ============')
        flavor = telepot.flavor(msg)

        print('flavor: ' + flavor)

        # normal message
        if flavor == 'normal':
            content_type, chat_type, _chat_id = telepot.glance2(msg)
            print('Normal Message:', content_type, chat_type, _chat_id, '; message content: ', msg)

            if content_type == 'text' and chat_type == 'private':

                if self._converType == ConverType.nothing:

                    if msg['text'] == '/start':
                        self.sender.sendMessage(text='今日的日期係：' + str(date.today()) + '. \n' +
                                                     '用 /new 黎 create 一個新問題，' +
                                                     '或者用 /help 睇其他選項。')
                    elif msg['text'] == '/new':
                        self._converType = ConverType.create_poll
                        self._createPollFlow = CreatePollFlow.poll_question
                        self._poll.creatorId = msg['from']['id']
                        self.sender.sendMessage(text='唔該 send 你個問題俾我。')

                    elif msg['text'] == '/help':
                        self.sender.sendMessage(text='用 /new 黎 create 一個新問題，\n' +
                                                     '或者用 /result 黎查詢回應統計。\n')

                    elif msg['text'].encode(encoding='utf-8') == '開始' or msg['text'].startswith('/begin'):
                        found_poll = 0
                        for poll_key in allPoll.keys():
                            print ('in_all_poll: ' + allPoll[poll_key].__str__())
                            for each_resp in allPoll[poll_key].response:
                                print('each_resp: ' + allPoll[poll_key].response[each_resp].__str__())
                                if allPoll[poll_key].response[each_resp].userid == msg['from']['id']:
                                    found_poll = poll_key
                        if found_poll != 0:
                            self._converType = ConverType.response_poll
                            self.start_survey(found_poll, msg['from']['id'])
                        else:
                            self.sender.sendMessage(text='搵唔到你的問題。')
                    else:
                        self.sender.sendMessage(text='唔知你想點，麻煩你再試過。\n' +
                                                     '或者用 /help 睇其他選項。')
                elif self._converType == ConverType.create_poll:
                    if msg['text'] == '/done':
                        self.complte_poll_creation()
                    elif msg['text'] != '':
                        if self._createPollFlow == CreatePollFlow.poll_question:
                            self._poll.question = msg['text']
                            self._createPollFlow = CreatePollFlow.poll_choice
                            self.sender.sendMessage(text='好，咁你自己有乜意見？')
                        elif self._createPollFlow == CreatePollFlow.poll_choice:
                            self._poll.choices.append(msg['text'])
                            self.sender.sendMessage(text='好，仲有冇？有就繼續 send 下個個選擇。\n' +
                                                         '如果冇就用 /done 完成建立問題。')

            elif content_type == 'text' and chat_type == 'group':
                if msg['text'].startswith('/start@' + botName):
                    print('invited into group')
                    poll_id = msg['text'].split(' ')[1]
                    self.get_invited(poll_id)
                    allPoll[poll_id].groupId = _chat_id
                elif msg['text'].startswith('/answer_'):
                    poll_id = msg['text'].split('_')[1].split('@')[0]
                    self.initiate_survey(poll_id,
                                         target_id=msg['from']['id'],
                                         display_name=msg['from']['first_name'] + ' ' + msg['from']['last_name'])
                elif msg['text'].encode(encoding='utf-8') == '開始回應':
                    orig_text = msg['reply_to_message']['text']
                    poll_id = orig_text.split('/answer_')[1].split(' ')[0]
                    self.initiate_survey(poll_id,
                                         target_id=msg['from']['id'],
                                         display_name=msg['from']['first_name'] + ' ' + msg['from']['last_name'])

            print('Poll:' + self._poll.__str__())
        else:
            raise telepot.BadFlavor(msg)

TOKEN = sys.argv[1]  # get token from command-line

bot = telepot.DelegatorBot(TOKEN, [
    (per_chat_id(), create_open(HKGathering, timeout=20)), ])
print('Listening ...')
bot.notifyOnMessage(run_forever=True)
<|endoftext|>


<commit_before># -*- cpy-indent-level: 4; indent-tabs-mode: nil -*-
# ex: set expandtab softtabstop=4 shiftwidth=4:
#
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014  Contributor
#
# 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.
"""Any work by the broker to write out (or read in?) templates lives here."""

import os
import logging

from aquilon.config import Config, lookup_file_path
from aquilon.exceptions_ import ArgumentError, ProcessException, InternalError
from aquilon.aqdb.model import (Host, Cluster, Fqdn, DnsRecord, HardwareEntity,
                                Machine, Sandbox, Domain)
from aquilon.worker.logger import CLIENT_INFO
from aquilon.notify.index import trigger_notifications
from aquilon.worker.processes import run_command
from aquilon.worker.locks import lock_queue, CompileKey

LOGGER = logging.getLogger(__name__)

def template_branch_basedir(config, dbbranch, dbauthor=None):
    if isinstance(dbbranch, Sandbox):
        if not dbauthor:
            raise InternalError("Missing required author to compile "
                                "{0:l}." % dbbranch)
        return os.path.join(config.get("broker", "templatesdir"),
                            dbauthor.name, dbbranch.name)
    else:
        return os.path.join(config.get("broker", "domainsdir"), dbbranch.name)

class TemplateDomain(object):

    def __init__(self, domain, author=None, logger=LOGGER):
        super(TemplateDomain, self).__init__()

        self.domain = domain
        self.author = author
        self.logger = logger

    def directories(self):
        """Return a list of directories required for compiling this domain"""
        config = Config()
        dirs = []

        if isinstance(self.domain, Domain):
            dirs.append(os.path.join(config.get("broker", "domainsdir"),
                                     self.domain.name))

        dirs.append(os.path.join(config.get("broker", "cfgdir"),
                                 "domains", self.domain.name))

        # This is a bit redundant. When creating the directories, the "clusters"
        # subdir would be enough; when removing them, the base dir would be
        # enough. Having both does not hurt and does not need such extra logic.
        dirs.append(os.path.join(config.get("broker", "quattordir"),
                                 "build", self.domain.name))
        dirs.append(os.path.join(config.get("broker", "quattordir"),
                                 "build", self.domain.name, "clusters"))

        return dirs

    def compile(self, session, only=None, locked=False,
                panc_debug_include=None, panc_debug_exclude=None,
                cleandeps=False):
        """The build directories are checked and constructed
        if necessary, so no prior setup is required.  The compile may
        take some time (current rate is 10 hosts per second, with a
        couple of seconds of constant overhead), and the possibility
        of blocking on the compile lock.

        If the 'only' parameter is provided, then it should be a
        list or set containing the profiles that need to be compiled.

        May raise ArgumentError exception, else returns the standard
        output (as a string) of the compile
        """

        config = Config()

        templatedir = template_branch_basedir(config, self.domain, self.author)
        if not os.path.exists(templatedir):
            raise ArgumentError("Template directory '%s' does not exist." %
                                templatedir)

        self.logger.info("preparing domain %s for compile" % self.domain.name)

        # Ensure that the compile directory is in a good state.
        outputdir = config.get("broker", "profilesdir")

        for d in self.directories() + [config.get("broker", "profilesdir")]:
            if not os.path.exists(d):
                try:
                    self.logger.info("creating %s" % d)
                    os.makedirs(d)
                except OSError, e:
                    raise ArgumentError("Failed to mkdir %s: %s" % (d, e))

        nothing_to_do = True
        if only:
            nothing_to_do = False
        else:
            hostnames = session.query(Fqdn)
            hostnames = hostnames.join(DnsRecord, HardwareEntity, Machine, Host)
            hostnames = hostnames.filter_by(branch=self.domain,
                                            sandbox_author=self.author)

            clusternames = session.query(Cluster.name)
            clusternames = clusternames.filter_by(branch=self.domain,
                                                  sandbox_author=self.author)
            if self.author:
                # Need to restrict to the subset of the sandbox managed
                # by this author.
                only = [str(fqdn) for fqdn in hostnames]
                only.extend(["cluster/%s" % c.name for c in clusternames])
                nothing_to_do = not bool(only)
            else:
                nothing_to_do = not hostnames.count() and not clusternames.count()

        if nothing_to_do:
            self.logger.client_info('No object profiles: nothing to do.')
            return

        # The ant wrapper is silly and it may pick up the wrong set of .jars if
        # ANT_HOME is not set
        panc_env = {"PATH": "%s/bin:%s" % (config.get("broker", "java_home"),
                                           os.environ.get("PATH", "")),
                    "ANT_HOME": config.get("broker", "ant_home"),
                    "JAVA_HOME": config.get("broker", "java_home")}
        if config.has_option("broker", "ant_options"):
            panc_env["ANT_OPTS"] = config.get("broker", "ant_options")

        if config.getboolean('panc', 'gzip_output'):
            compress_suffix = ".gz"
        else:
            compress_suffix = ""

        formats = []
        suffixes = []
        if config.getboolean('panc', 'xml_profiles'):
            formats.append("pan" + compress_suffix)
            suffixes.append(".xml" + compress_suffix)
        if config.getboolean('panc', 'json_profiles'):
            formats.append("json" + compress_suffix)
            suffixes.append(".json" + compress_suffix)

        formats.append("dep")

        args = [config.get("broker", "ant")]
        args.append("--noconfig")
        args.append("-f")
        args.append(lookup_file_path("build.xml"))
        args.append("-Dbasedir=%s" % config.get("broker", "quattordir"))
        args.append("-Dpanc.jar=%s" % self.domain.compiler)
        args.append("-Dpanc.formats=%s" % ",".join(formats))
        args.append("-Dprofile.suffixes=%s" % ",".join(suffixes))
        args.append("-Dpanc.template_extension=%s" %
                    config.get("panc", "template_extension"))
        args.append("-Ddomain=%s" % self.domain.name)
        args.append("-Ddistributed.profiles=%s" % outputdir)
        args.append("-Dpanc.batch.size=%s" %
                    config.get("panc", "batch_size"))
        args.append("-Dant-contrib.jar=%s" %
                    config.get("broker", "ant_contrib_jar"))
        if isinstance(self.domain, Sandbox):
            args.append("-Ddomain.templates=%s" % templatedir)
        if only:
            # Use -Dforce.build=true?
            # TODO: pass the list in a temp file
            args.append("-Dobject.profile=%s" % " ".join(only))
            args.append("compile.object.profile")
        else:
            # Technically this is the default, but being explicit
            # doesn't hurt.
            args.append("compile.domain.profiles")
        if panc_debug_include is not None:
            args.append("-Dpanc.debug.include=%s" % panc_debug_include)
        if panc_debug_exclude is not None:
            args.append("-Dpanc.debug.exclude=%s" % panc_debug_exclude)
        if cleandeps:
            # Cannot send a false value - the test in build.xml is for
            # whether or not the property is defined at all.
            args.append("-Dclean.dep.files=%s" % cleandeps)

        try:
            if not locked:
                if only and len(only) == 1:
                    key = CompileKey(domain=self.domain.name,
                                     profile=list(only)[0],
                                     logger=self.logger)
                else:
                    key = CompileKey(domain=self.domain.name,
                                     logger=self.logger)
                lock_queue.acquire(key)
            self.logger.info("starting compile")
            try:
                run_command(args, env=panc_env, logger=self.logger,
                            path=config.get("broker", "quattordir"),
                            loglevel=CLIENT_INFO)
            except ProcessException:
                raise ArgumentError("Compilation failed, see the compiler "
                                    "messages for details.")
        finally:
            if not locked:
                lock_queue.release(key)

        trigger_notifications(config, self.logger, CLIENT_INFO)
<commit_msg>Work around Java timestamp granularity issue<commit_after># -*- cpy-indent-level: 4; indent-tabs-mode: nil -*-
# ex: set expandtab softtabstop=4 shiftwidth=4:
#
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014  Contributor
#
# 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.
"""Any work by the broker to write out (or read in?) templates lives here."""

import os
import logging
import time

from aquilon.config import Config, lookup_file_path
from aquilon.exceptions_ import ArgumentError, ProcessException, InternalError
from aquilon.aqdb.model import (Host, Cluster, Fqdn, DnsRecord, HardwareEntity,
                                Machine, Sandbox, Domain)
from aquilon.worker.logger import CLIENT_INFO
from aquilon.notify.index import trigger_notifications
from aquilon.worker.processes import run_command
from aquilon.worker.locks import lock_queue, CompileKey

LOGGER = logging.getLogger(__name__)

def template_branch_basedir(config, dbbranch, dbauthor=None):
    if isinstance(dbbranch, Sandbox):
        if not dbauthor:
            raise InternalError("Missing required author to compile "
                                "{0:l}." % dbbranch)
        return os.path.join(config.get("broker", "templatesdir"),
                            dbauthor.name, dbbranch.name)
    else:
        return os.path.join(config.get("broker", "domainsdir"), dbbranch.name)

class TemplateDomain(object):

    def __init__(self, domain, author=None, logger=LOGGER):
        super(TemplateDomain, self).__init__()

        self.domain = domain
        self.author = author
        self.logger = logger

    def directories(self):
        """Return a list of directories required for compiling this domain"""
        config = Config()
        dirs = []

        if isinstance(self.domain, Domain):
            dirs.append(os.path.join(config.get("broker", "domainsdir"),
                                     self.domain.name))

        dirs.append(os.path.join(config.get("broker", "cfgdir"),
                                 "domains", self.domain.name))

        # This is a bit redundant. When creating the directories, the "clusters"
        # subdir would be enough; when removing them, the base dir would be
        # enough. Having both does not hurt and does not need such extra logic.
        dirs.append(os.path.join(config.get("broker", "quattordir"),
                                 "build", self.domain.name))
        dirs.append(os.path.join(config.get("broker", "quattordir"),
                                 "build", self.domain.name, "clusters"))

        return dirs

    def compile(self, session, only=None, locked=False,
                panc_debug_include=None, panc_debug_exclude=None,
                cleandeps=False):
        """The build directories are checked and constructed
        if necessary, so no prior setup is required.  The compile may
        take some time (current rate is 10 hosts per second, with a
        couple of seconds of constant overhead), and the possibility
        of blocking on the compile lock.

        If the 'only' parameter is provided, then it should be a
        list or set containing the profiles that need to be compiled.

        May raise ArgumentError exception, else returns the standard
        output (as a string) of the compile
        """

        config = Config()

        templatedir = template_branch_basedir(config, self.domain, self.author)
        if not os.path.exists(templatedir):
            raise ArgumentError("Template directory '%s' does not exist." %
                                templatedir)

        self.logger.info("preparing domain %s for compile" % self.domain.name)

        # Ensure that the compile directory is in a good state.
        outputdir = config.get("broker", "profilesdir")

        for d in self.directories() + [config.get("broker", "profilesdir")]:
            if not os.path.exists(d):
                try:
                    self.logger.info("creating %s" % d)
                    os.makedirs(d)
                except OSError, e:
                    raise ArgumentError("Failed to mkdir %s: %s" % (d, e))

        nothing_to_do = True
        if only:
            nothing_to_do = False
        else:
            hostnames = session.query(Fqdn)
            hostnames = hostnames.join(DnsRecord, HardwareEntity, Machine, Host)
            hostnames = hostnames.filter_by(branch=self.domain,
                                            sandbox_author=self.author)

            clusternames = session.query(Cluster.name)
            clusternames = clusternames.filter_by(branch=self.domain,
                                                  sandbox_author=self.author)
            if self.author:
                # Need to restrict to the subset of the sandbox managed
                # by this author.
                only = [str(fqdn) for fqdn in hostnames]
                only.extend(["cluster/%s" % c.name for c in clusternames])
                nothing_to_do = not bool(only)
            else:
                nothing_to_do = not hostnames.count() and not clusternames.count()

        if nothing_to_do:
            self.logger.client_info('No object profiles: nothing to do.')
            return

        # The ant wrapper is silly and it may pick up the wrong set of .jars if
        # ANT_HOME is not set
        panc_env = {"PATH": "%s/bin:%s" % (config.get("broker", "java_home"),
                                           os.environ.get("PATH", "")),
                    "ANT_HOME": config.get("broker", "ant_home"),
                    "JAVA_HOME": config.get("broker", "java_home")}
        if config.has_option("broker", "ant_options"):
            panc_env["ANT_OPTS"] = config.get("broker", "ant_options")

        if config.getboolean('panc', 'gzip_output'):
            compress_suffix = ".gz"
        else:
            compress_suffix = ""

        formats = []
        suffixes = []
        if config.getboolean('panc', 'xml_profiles'):
            formats.append("pan" + compress_suffix)
            suffixes.append(".xml" + compress_suffix)
        if config.getboolean('panc', 'json_profiles'):
            formats.append("json" + compress_suffix)
            suffixes.append(".json" + compress_suffix)

        formats.append("dep")

        args = [config.get("broker", "ant")]
        args.append("--noconfig")
        args.append("-f")
        args.append(lookup_file_path("build.xml"))
        args.append("-Dbasedir=%s" % config.get("broker", "quattordir"))
        args.append("-Dpanc.jar=%s" % self.domain.compiler)
        args.append("-Dpanc.formats=%s" % ",".join(formats))
        args.append("-Dprofile.suffixes=%s" % ",".join(suffixes))
        args.append("-Dpanc.template_extension=%s" %
                    config.get("panc", "template_extension"))
        args.append("-Ddomain=%s" % self.domain.name)
        args.append("-Ddistributed.profiles=%s" % outputdir)
        args.append("-Dpanc.batch.size=%s" %
                    config.get("panc", "batch_size"))
        args.append("-Dant-contrib.jar=%s" %
                    config.get("broker", "ant_contrib_jar"))
        if isinstance(self.domain, Sandbox):
            args.append("-Ddomain.templates=%s" % templatedir)
        if only:
            # Use -Dforce.build=true?
            # TODO: pass the list in a temp file
            args.append("-Dobject.profile=%s" % " ".join(only))
            args.append("compile.object.profile")
        else:
            # Technically this is the default, but being explicit
            # doesn't hurt.
            args.append("compile.domain.profiles")
        if panc_debug_include is not None:
            args.append("-Dpanc.debug.include=%s" % panc_debug_include)
        if panc_debug_exclude is not None:
            args.append("-Dpanc.debug.exclude=%s" % panc_debug_exclude)
        if cleandeps:
            # Cannot send a false value - the test in build.xml is for
            # whether or not the property is defined at all.
            args.append("-Dclean.dep.files=%s" % cleandeps)

        try:
            if not locked:
                if only and len(only) == 1:
                    key = CompileKey(domain=self.domain.name,
                                     profile=list(only)[0],
                                     logger=self.logger)
                else:
                    key = CompileKey(domain=self.domain.name,
                                     logger=self.logger)
                lock_queue.acquire(key)
            self.logger.info("starting compile")
            try:
                start_time = time.time()
                run_command(args, env=panc_env, logger=self.logger,
                            path=config.get("broker", "quattordir"),
                            loglevel=CLIENT_INFO)
                end_time = time.time()
            except ProcessException:
                raise ArgumentError("Compilation failed, see the compiler "
                                    "messages for details.")

            # Ugly hack. The File.lastModified() method is supposed to have
            # millisecond granularity, but the actual implementation in Java 7
            # has 1 second granularity only. So if the compilation finishes in
            # less than a second, and something modifies the data within that
            # second, the panc dependency tracker will be unable to notice that
            # the object is out of date and needs to be recompiled. Sleeping a
            # bit works around the issue by making sure further modifications
            # to the source templates will have a different second value than
            # anything this compilation used.
            if long(start_time) == long(end_time):
                time.sleep(1)
        finally:
            if not locked:
                lock_queue.release(key)

        trigger_notifications(config, self.logger, CLIENT_INFO)
<|endoftext|>