<commit_before># gender of subject
#   0 - male
#   1 - female
gender = 0

# age of subject
#   integer
age = 40

# Status of subject
#   0 - Single
#   1 - In a relationship
#   2 - In an open relationship
#   3 - It's complicated
#   4 - I'm a pizza
#   5 - Depends who's asking
status = 5

# how ignorant is the subject
# 0 - 100  percents
#   integer
ignorance = 10

# how much money does the subject have
#   float
money_have = 14662.00

# how much money does the subject want to have
#   float
money_wants = 20309.00

# how much money the subject spent
#   float
money_spent = 10991.00

# how popular is the subject online (cloudscore)
#   integer
popularity_online = 19

# number of subjects real life friends
#   integer
rl_friends = 7

# returns a sum of all variables... stupid as hell, but a placeholder for later
def sum_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends):
    return gender + age + status + ignorance + money_have + money_wants + money_spent + popularity_online + rl_friends

# returns a weighted sum... better, but still not perfect
def better_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends):
    weighted_sum = 0

    # if gender = male, 5 points more complicated
    if gender == 0:
        weighted_sum += 5

    # age weights
    if age < 10:
        weighted_sum += 0
    elif age < 20:
        weighted_sum += 4
    elif age < 35:
        weighted_sum += 2
    elif age < 50:
        weighted_sum += 4
    else:
        weighted_sum += 0

    # status weights
    status_weights = [0, 5, 9, 21, 3, 13]
    if weighted_sum >= 0 and weighted_sum < 6:
        weighted_sum += status_weights[status]
    else:
        # unknown status, adding a (random) default value
        weighted_sum += 7

    # calculate ignorance or something
    if ignorance >= 0 and ignorance <= 100:
        weighted_sum += (100 - ignorance) * 0.15
    else:
        # ignorance out of bounds, adding a (random) default value
        weighted_sum += 7

    # TODO: Add money calculation

    # online life complicates stuff
    weighted_sum += popularity_online / 3

    # more friends, ... not sure what
    if rl_friends > 15: # really? get real
        weighted_sum += 10 + rl_friends * 2
    if rl_friends > 8:
        weighted_sum += rl_friends - 8
    else:
        weighted_sum += 8 - rl_friends

    return weighted_sum

print "Simple (wrong) approaches:"
print "Sum of all values: ", sum_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends)
print "A better approach (weighted): ", better_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends)
<commit_msg>python is kinda nice ;)<commit_after># gender of subject
#   0 - male
#   1 - female
gender = 0

# age of subject
#   integer
age = 40

# Status of subject
#   0 - Single
#   1 - In a relationship
#   2 - In an open relationship
#   3 - It's complicated
#   4 - I'm a pizza
#   5 - Depends who's asking
status = 5

# how ignorant is the subject
# 0 - 100  percents
#   integer
ignorance = 10

# how much money does the subject have
#   float
money_have = 14662.00

# how much money does the subject want to have
#   float
money_wants = 20309.00

# how much money the subject spent
#   float
money_spent = 10991.00

# how popular is the subject online (cloudscore)
#   integer
popularity_online = 19

# number of subjects real life friends
#   integer
rl_friends = 7

# returns a sum of all variables... stupid as hell, but a placeholder for later
def sum_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends):
    return sum(locals())

# returns a weighted sum... better, but still not perfect
def better_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends):
    weighted_sum = 0

    # if gender = male, 5 points more complicated
    if gender == 0:
        weighted_sum += 5

    # age weights
    if age < 10:
        weighted_sum += 0
    elif age < 20:
        weighted_sum += 4
    elif age < 35:
        weighted_sum += 2
    elif age < 50:
        weighted_sum += 4
    else:
        weighted_sum += 0

    # status weights
    status_weights = [0, 5, 9, 21, 3, 13]
    if weighted_sum >= 0 and weighted_sum < 6:
        weighted_sum += status_weights[status]
    else:
        # unknown status, adding a (random) default value
        weighted_sum += 7

    # calculate ignorance or something
    if ignorance >= 0 and ignorance <= 100:
        weighted_sum += (100 - ignorance) * 0.15
    else:
        # ignorance out of bounds, adding a (random) default value
        weighted_sum += 7

    # TODO: Add money calculation

    # online life complicates stuff
    weighted_sum += popularity_online / 3

    # more friends, ... not sure what
    if rl_friends > 15: # really? get real
        weighted_sum += 10 + rl_friends * 2
    if rl_friends > 8:
        weighted_sum += rl_friends - 8
    else:
        weighted_sum += 8 - rl_friends

    return weighted_sum

print "Simple (wrong) approaches:"
print "Sum of all values: ", sum_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends)
print "A better approach (weighted): ", better_approach(gender, age, status, ignorance, money_have, money_wants, money_spent, popularity_online, rl_friends)
<|endoftext|>


<commit_before># Copyright (c) 2007-2008 The PyAMF Project.
# See LICENSE for details.

"""
Remote Object Tests.

@author: U{Nick Joyce<mailto:nick@boxdesign.co.uk>}
@since: 0.1
"""

import unittest

import pyamf
from pyamf import remoting
from pyamf.remoting import amf3, gateway
from pyamf.flex import messaging

class RandomIdGeneratorTestCase(unittest.TestCase):
    def test_generate(self):
        x = []

        for i in range(5):
            id_ = amf3.generate_random_id()

            self.assertTrue(id_ not in x)
            x.append(id_)

class AcknowlegdementGeneratorTestCase(unittest.TestCase):
    def test_generate(self):
        ack = amf3.generate_acknowledgement()

        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertTrue(ack.messageId is not None)
        self.assertTrue(ack.clientId is not None)
        self.assertTrue(ack.timestamp is not None)

    def test_request(self):
        ack = amf3.generate_acknowledgement(pyamf.Bag({'messageId': '123123'}))

        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertTrue(ack.messageId is not None)
        self.assertTrue(ack.clientId is not None)
        self.assertTrue(ack.timestamp is not None)

        self.assertEquals(ack.correlationId, '123123')

class RequestProcessorTestCase(unittest.TestCase):
    def test_create(self):
        rp = amf3.RequestProcessor('xyz')
        self.assertEquals(rp.gateway, 'xyz')

    def test_ping(self):
        message = messaging.CommandMessage(operation=5)
        rp = amf3.RequestProcessor(None)
        request = remoting.Request('null', body=[message])

        response = rp(request)
        ack = response.body

        self.assertTrue(isinstance(response, remoting.Response))
        self.assertEquals(response.status, remoting.STATUS_OK)
        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertEquals(ack.body, True)

    def test_request(self):
        def echo(x):
            return x

        gw = gateway.BaseGateway({'echo': echo})
        rp = amf3.RequestProcessor(gw)
        message = messaging.RemotingMessage(body=['foo.bar'], operation='echo')
        request = remoting.Request('null', body=[message])

        response = rp(request)
        ack = response.body

        self.assertTrue(isinstance(response, remoting.Response))
        self.assertEquals(response.status, remoting.STATUS_OK)
        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertEquals(ack.body, 'foo.bar')

def suite():
    suite = unittest.TestSuite()

    suite.addTest(unittest.makeSuite(RandomIdGeneratorTestCase))
    suite.addTest(unittest.makeSuite(AcknowlegdementGeneratorTestCase))
    suite.addTest(unittest.makeSuite(RequestProcessorTestCase))

    return suite

if __name__ == '__main__':
    unittest.main(defaultTest='suite')
<commit_msg>version nr typo<commit_after># Copyright (c) 2007-2008 The PyAMF Project.
# See LICENSE for details.

"""
Remote Object Tests.

@author: U{Nick Joyce<mailto:nick@boxdesign.co.uk>}

@since: 0.1.0
"""

import unittest

import pyamf
from pyamf import remoting
from pyamf.remoting import amf3, gateway
from pyamf.flex import messaging

class RandomIdGeneratorTestCase(unittest.TestCase):
    def test_generate(self):
        x = []

        for i in range(5):
            id_ = amf3.generate_random_id()

            self.assertTrue(id_ not in x)
            x.append(id_)

class AcknowlegdementGeneratorTestCase(unittest.TestCase):
    def test_generate(self):
        ack = amf3.generate_acknowledgement()

        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertTrue(ack.messageId is not None)
        self.assertTrue(ack.clientId is not None)
        self.assertTrue(ack.timestamp is not None)

    def test_request(self):
        ack = amf3.generate_acknowledgement(pyamf.Bag({'messageId': '123123'}))

        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertTrue(ack.messageId is not None)
        self.assertTrue(ack.clientId is not None)
        self.assertTrue(ack.timestamp is not None)

        self.assertEquals(ack.correlationId, '123123')

class RequestProcessorTestCase(unittest.TestCase):
    def test_create(self):
        rp = amf3.RequestProcessor('xyz')
        self.assertEquals(rp.gateway, 'xyz')

    def test_ping(self):
        message = messaging.CommandMessage(operation=5)
        rp = amf3.RequestProcessor(None)
        request = remoting.Request('null', body=[message])

        response = rp(request)
        ack = response.body

        self.assertTrue(isinstance(response, remoting.Response))
        self.assertEquals(response.status, remoting.STATUS_OK)
        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertEquals(ack.body, True)

    def test_request(self):
        def echo(x):
            return x

        gw = gateway.BaseGateway({'echo': echo})
        rp = amf3.RequestProcessor(gw)
        message = messaging.RemotingMessage(body=['foo.bar'], operation='echo')
        request = remoting.Request('null', body=[message])

        response = rp(request)
        ack = response.body

        self.assertTrue(isinstance(response, remoting.Response))
        self.assertEquals(response.status, remoting.STATUS_OK)
        self.assertTrue(isinstance(ack, messaging.AcknowledgeMessage))
        self.assertEquals(ack.body, 'foo.bar')

def suite():
    suite = unittest.TestSuite()

    suite.addTest(unittest.makeSuite(RandomIdGeneratorTestCase))
    suite.addTest(unittest.makeSuite(AcknowlegdementGeneratorTestCase))
    suite.addTest(unittest.makeSuite(RequestProcessorTestCase))

    return suite

if __name__ == '__main__':
    unittest.main(defaultTest='suite')
<|endoftext|>


<commit_before>#!/usr/bin/env python2.5
#
# Copyright 2011 the Melange authors.
#
# 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.

"""Module for the GSoC participant dashboard.
"""

__authors__ = [
  '"Lennard de Rijk" <ljvderijk@gmail.com>',
  ]

from google.appengine.api import users

from django.conf.urls.defaults import url

from soc.logic.helper import timeline as timeline_helper
from soc.logic.lists import Lists
from soc.views import out_of_band
from soc.views.helper import lists
from soc.views.template import Template

from soc.modules.gsoc.logic.models.org_app_survey import logic as \
    org_app_logic
from soc.modules.gsoc.logic.models.student_project import logic as \
    project_logic
from soc.modules.gsoc.views.base import RequestHandler
from soc.modules.gsoc.views.helper import url_patterns
from soc.modules.gsoc.views.models.organization import view as \
    org_view
from soc.modules.gsoc.views.models.student_proposal import view as \
    proposal_view
from soc.modules.gsoc.views.models.student_project import view as \
    project_view
from soc.modules.gsoc.views.models.org_app_survey import view as \
    org_app_view
from soc.modules.gsoc.views.models.project_survey import view as \
    project_survey_view

class Dashboard(RequestHandler):
  """View for the participant dashboard.
  """

  def djangoURLPatterns(self):
    """The URL pattern for the dashboard.
    """
    return [
        url(r'^gsoc/dashboard/%s$' %url_patterns.PROGRAM, self,
            name='gsoc_dashboard')]

  def checkAccess(self):
    """Denies access if you don't have a role in the current program.
    """
    # TODO(ljvderijk): Would be nice if it would directly redirect you to login
    # if you are not logged in.
    # TODO(ljvderijk): You need a "profile" to get access but that needs to be
    # implemented.
    pass

  def templatePath(self):
    """Returns the path to the template.
    """
    return 'v2/modules/gsoc/dashboard/base.html'

  def get(self):
    """Handler for the GET request.
    """
    if lists.isDataRequest(self.request):
      components = self._getActiveComponents()

      list_data = None
      for component in components:
        list_data = component.getListData()
        if list_data:
          break

      if not list_data:
        raise out_of_band.AccessViolation(
            'You do not have access to this data')
      self.response = lists.getResponse(self.request, list_data)
    else:
      super(Dashboard, self).get()

  def context(self):
    """Handler for default HTTP GET request.
    """
    components = self._getActiveComponents()
    encoded_path = self.data.request.path.encode('utf-8')

    context = {}
    context['page_name'] = self.data.program.name
    context['user'] = self.data.user
    context['logout_link'] = users.create_logout_url(encoded_path)
    # TODO(ljvderijk): Implement code for setting dashboard messages.
    #context['alert_msg'] = 'Default alert goes here'
    context['components'] = components

    return context

  def _getActiveComponents(self):
    """Returns the components that are active on the page.
    """
    if self.data.student:
      return self._getStudentComponents()
    elif self.data.mentor or self.data.org_admin:
      return self._getOrgMemberComponents()
    else:
      return self._getLoneUserCompontents()

  def _getStudentComponents(self):
    """Get the dashboard components for a student.
    """
    # Add all the proposals of this current user
    components = [MyProposalsComponent(self.request, self.data)]

    fields = {'student': self.data.student}
    project = project_logic.getForFields(fields, unique=True)
    if project:
      # Add a component to show all the projects
      components.append(MyProjectsComponent(self.request, self.data))
      # Add a component to show the evaluations
      # TODO(ljvderijk): Enable after the right information can be displayed
      #components.append(MyEvaluationsComponent(self.request, self.data))

    return components

  def _getOrgMemberComponents(self):
    """Get the dashboard components for Organization members.
    """
    components = []

    if self.data.mentor:
      if timeline_helper.isAfterEvent(
          self.data.program_timeline, 'accepted_students_announced_deadline'):
        # add a component to show all projects a user is mentoring
        components.append(
            ProjectsIMentorComponent(self.request, self.data))

    if self.data.org_admin:
      # add a component for all organization that this user administers
      components.append(OrganizationsIAdminComponent(self.request, self.data))

    if timeline_helper.isBeforeEvent(
      self.data.program_timeline, 'student_signup_start'):
      # Add the submitted proposals component
      #components.append(
      #    SubmittedProposalsComponent(self.request, self.data))
      pass

    return components

  def _getLoneUserComponents(self):
    """Get the dashboard components for users without any role.
    """
    components = []

    org_app_survey = org_app_logic.getForProgram(self.data.program)

    fields = {'survey': org_app_survey}
    org_app_record = org_app_logic.getRecordLogic().getForFields(fields, unique=True)

    if org_app_record:
      # add a component showing the organization application of the user
      components.append(MyOrgApplicationsComponent(self.request, self.data,
                                                   org_app_survey))

    return components

class Component(Template):
  """Base component for the dashboard.
  """

  def __init__(self, request, data):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
    """
    self.request = request
    self.data = data

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    # by default no list is present
    return None

class MyOrgApplicationsComponent(Component):
  """Component for listing the Organization Applications of the current user.
  """

  def __init__(self, request, data, org_app_survey):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
      org_app_survey: the OrgApplicationSurvey entity
    """
    # passed in so we don't have to do double queries
    self.org_app_survey = org_app_survey
    super(MyOrgApplicationsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    # TODO(ljvderijk): List redirects
    list_params = org_app_view.getParams()['record_list_params']
    list_params['list_description'] = 'List of your Organization Applications'
    list_config = lists.getListGenerator(self.request, list_params,
                                         visibility='self', idx=0)
    return {
        'name': 'org_applications',
        'title': 'MY ORGANIZATION APPLICATIONS',
        'lists': Lists([list_config]),
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 0:
      list_data = lists.getListData(
          self.request, org_app_view.getParams()['record_list_params'],
          {'survey': self.org_app_survey, 'main_admin': self.data.user},
          visibility='self')
      return list_data
    else:
      return None

class MyProposalsComponent(Component):
  """Component for listing all the proposals of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(self.request,
                                         proposal_view.getParams(), idx=1)
    return {
        'name': 'proposals',
        'title': 'PROPOSALS',
        'lists': Lists([list_config]),
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 1:
      list_data = lists.getListData(self.request, proposal_view.getParams(),
                                   {'program': self.data.program,
                                    'scope': self.data.student})
      return list_data
    else:
      return None

class MyProjectsComponent(Component):
  """Component for listing all the projects of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 2:
      list_data = lists.getListData(self.request, project_view.getParams(),
                                   {'program': self.data.program,
                                    'student': self.data.student})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(self.request,
                                         project_view.getParams(), idx=2)
    return {
        'name': 'projects',
        'title': 'PROJECTS',
        'lists': Lists([list_config]),
    }

class MyEvaluationsComponent(Component):
  """Component for listing all the Evaluations of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 3:
      list_data = lists.getListData(self.request, project_survey_view.getParams(),
                                    {'scope': self.data.program})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, project_survey_view.getParams(), idx=3)

    return {
        'name': 'evaluations',
        'title': 'EVALUATIONS',
        'lists': Lists([list_config]),
    }

class SubmittedProposalsComponent(Component):
  """Component for listing all the Evaluations of the current Student.
  """
  # TODO(ljvderijk): Implement
  pass

class ProjectsIMentorComponent(Component):
  """Component for listing all the Projects mentored by the current user.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 4:
      list_data = lists.getListData(self.request, project_view.getParams(),
                                    {'program': self.data.program,
                                     'mentor': self.data.mentor})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, project_view.getParams(), idx=4)

    return {
        'name': 'mentoring_projects',
        'title': 'PROJECTS I AM A MENTOR FOR',
        'lists': Lists([list_config]),
    }

class OrganizationsIAdminComponent(Component):
  """Component for listing all the Organizations controlled by the current
  user.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 5:
      # TODO(ljvderijk): Feels weird that if you have access to all the keys
      # already that you need to use the list code in this way. The rewrite
      # should probably allow the caller to control the entities to put in?
      list_data = lists.getListData(
          self.request, org_view.getParams(),
          {'scope': self.data.program,
           'link_id': [org_admin.scope.link_id
                       for org_admin in self.data.org_admin]})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, org_view.getParams(), idx=5)

    return {
        'name': 'adminning_organizations',
        'title': 'ORGANIZATIONS THAT I AM AN ADMIN FOR',
        'lists': Lists([list_config]),
    }
<commit_msg>Fix tyop in dashboard.py<commit_after>#!/usr/bin/env python2.5
#
# Copyright 2011 the Melange authors.
#
# 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.

"""Module for the GSoC participant dashboard.
"""

__authors__ = [
  '"Lennard de Rijk" <ljvderijk@gmail.com>',
  ]

from google.appengine.api import users

from django.conf.urls.defaults import url

from soc.logic.helper import timeline as timeline_helper
from soc.logic.lists import Lists
from soc.views import out_of_band
from soc.views.helper import lists
from soc.views.template import Template

from soc.modules.gsoc.logic.models.org_app_survey import logic as \
    org_app_logic
from soc.modules.gsoc.logic.models.student_project import logic as \
    project_logic
from soc.modules.gsoc.views.base import RequestHandler
from soc.modules.gsoc.views.helper import url_patterns
from soc.modules.gsoc.views.models.organization import view as \
    org_view
from soc.modules.gsoc.views.models.student_proposal import view as \
    proposal_view
from soc.modules.gsoc.views.models.student_project import view as \
    project_view
from soc.modules.gsoc.views.models.org_app_survey import view as \
    org_app_view
from soc.modules.gsoc.views.models.project_survey import view as \
    project_survey_view

class Dashboard(RequestHandler):
  """View for the participant dashboard.
  """

  def djangoURLPatterns(self):
    """The URL pattern for the dashboard.
    """
    return [
        url(r'^gsoc/dashboard/%s$' %url_patterns.PROGRAM, self,
            name='gsoc_dashboard')]

  def checkAccess(self):
    """Denies access if you don't have a role in the current program.
    """
    # TODO(ljvderijk): Would be nice if it would directly redirect you to login
    # if you are not logged in.
    # TODO(ljvderijk): You need a "profile" to get access but that needs to be
    # implemented.
    pass

  def templatePath(self):
    """Returns the path to the template.
    """
    return 'v2/modules/gsoc/dashboard/base.html'

  def get(self):
    """Handler for the GET request.
    """
    if lists.isDataRequest(self.request):
      components = self._getActiveComponents()

      list_data = None
      for component in components:
        list_data = component.getListData()
        if list_data:
          break

      if not list_data:
        raise out_of_band.AccessViolation(
            'You do not have access to this data')
      self.response = lists.getResponse(self.request, list_data)
    else:
      super(Dashboard, self).get()

  def context(self):
    """Handler for default HTTP GET request.
    """
    components = self._getActiveComponents()
    encoded_path = self.data.request.path.encode('utf-8')

    context = {}
    context['page_name'] = self.data.program.name
    context['user'] = self.data.user
    context['logout_link'] = users.create_logout_url(encoded_path)
    # TODO(ljvderijk): Implement code for setting dashboard messages.
    #context['alert_msg'] = 'Default alert goes here'
    context['components'] = components

    return context

  def _getActiveComponents(self):
    """Returns the components that are active on the page.
    """
    if self.data.student:
      return self._getStudentComponents()
    elif self.data.mentor or self.data.org_admin:
      return self._getOrgMemberComponents()
    else:
      return self._getLoneUserComponents()

  def _getStudentComponents(self):
    """Get the dashboard components for a student.
    """
    # Add all the proposals of this current user
    components = [MyProposalsComponent(self.request, self.data)]

    fields = {'student': self.data.student}
    project = project_logic.getForFields(fields, unique=True)
    if project:
      # Add a component to show all the projects
      components.append(MyProjectsComponent(self.request, self.data))
      # Add a component to show the evaluations
      # TODO(ljvderijk): Enable after the right information can be displayed
      #components.append(MyEvaluationsComponent(self.request, self.data))

    return components

  def _getOrgMemberComponents(self):
    """Get the dashboard components for Organization members.
    """
    components = []

    if self.data.mentor:
      if timeline_helper.isAfterEvent(
          self.data.program_timeline, 'accepted_students_announced_deadline'):
        # add a component to show all projects a user is mentoring
        components.append(
            ProjectsIMentorComponent(self.request, self.data))

    if self.data.org_admin:
      # add a component for all organization that this user administers
      components.append(OrganizationsIAdminComponent(self.request, self.data))

    if timeline_helper.isBeforeEvent(
      self.data.program_timeline, 'student_signup_start'):
      # Add the submitted proposals component
      #components.append(
      #    SubmittedProposalsComponent(self.request, self.data))
      pass

    return components

  def _getLoneUserComponents(self):
    """Get the dashboard components for users without any role.
    """
    components = []

    org_app_survey = org_app_logic.getForProgram(self.data.program)

    fields = {'survey': org_app_survey}
    org_app_record = org_app_logic.getRecordLogic().getForFields(fields, unique=True)

    if org_app_record:
      # add a component showing the organization application of the user
      components.append(MyOrgApplicationsComponent(self.request, self.data,
                                                   org_app_survey))

    return components

class Component(Template):
  """Base component for the dashboard.
  """

  def __init__(self, request, data):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
    """
    self.request = request
    self.data = data

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    # by default no list is present
    return None

class MyOrgApplicationsComponent(Component):
  """Component for listing the Organization Applications of the current user.
  """

  def __init__(self, request, data, org_app_survey):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
      org_app_survey: the OrgApplicationSurvey entity
    """
    # passed in so we don't have to do double queries
    self.org_app_survey = org_app_survey
    super(MyOrgApplicationsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    # TODO(ljvderijk): List redirects
    list_params = org_app_view.getParams()['record_list_params']
    list_params['list_description'] = 'List of your Organization Applications'
    list_config = lists.getListGenerator(self.request, list_params,
                                         visibility='self', idx=0)
    return {
        'name': 'org_applications',
        'title': 'MY ORGANIZATION APPLICATIONS',
        'lists': Lists([list_config]),
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 0:
      list_data = lists.getListData(
          self.request, org_app_view.getParams()['record_list_params'],
          {'survey': self.org_app_survey, 'main_admin': self.data.user},
          visibility='self')
      return list_data
    else:
      return None

class MyProposalsComponent(Component):
  """Component for listing all the proposals of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(self.request,
                                         proposal_view.getParams(), idx=1)
    return {
        'name': 'proposals',
        'title': 'PROPOSALS',
        'lists': Lists([list_config]),
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 1:
      list_data = lists.getListData(self.request, proposal_view.getParams(),
                                   {'program': self.data.program,
                                    'scope': self.data.student})
      return list_data
    else:
      return None

class MyProjectsComponent(Component):
  """Component for listing all the projects of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 2:
      list_data = lists.getListData(self.request, project_view.getParams(),
                                   {'program': self.data.program,
                                    'student': self.data.student})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(self.request,
                                         project_view.getParams(), idx=2)
    return {
        'name': 'projects',
        'title': 'PROJECTS',
        'lists': Lists([list_config]),
    }

class MyEvaluationsComponent(Component):
  """Component for listing all the Evaluations of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 3:
      list_data = lists.getListData(self.request, project_survey_view.getParams(),
                                    {'scope': self.data.program})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, project_survey_view.getParams(), idx=3)

    return {
        'name': 'evaluations',
        'title': 'EVALUATIONS',
        'lists': Lists([list_config]),
    }

class SubmittedProposalsComponent(Component):
  """Component for listing all the Evaluations of the current Student.
  """
  # TODO(ljvderijk): Implement
  pass

class ProjectsIMentorComponent(Component):
  """Component for listing all the Projects mentored by the current user.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 4:
      list_data = lists.getListData(self.request, project_view.getParams(),
                                    {'program': self.data.program,
                                     'mentor': self.data.mentor})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, project_view.getParams(), idx=4)

    return {
        'name': 'mentoring_projects',
        'title': 'PROJECTS I AM A MENTOR FOR',
        'lists': Lists([list_config]),
    }

class OrganizationsIAdminComponent(Component):
  """Component for listing all the Organizations controlled by the current
  user.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 5:
      # TODO(ljvderijk): Feels weird that if you have access to all the keys
      # already that you need to use the list code in this way. The rewrite
      # should probably allow the caller to control the entities to put in?
      list_data = lists.getListData(
          self.request, org_view.getParams(),
          {'scope': self.data.program,
           'link_id': [org_admin.scope.link_id
                       for org_admin in self.data.org_admin]})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, org_view.getParams(), idx=5)

    return {
        'name': 'adminning_organizations',
        'title': 'ORGANIZATIONS THAT I AM AN ADMIN FOR',
        'lists': Lists([list_config]),
    }
<|endoftext|>


<commit_before>import hoomd
import pytest
import numpy as np
from itertools import combinations
from copy import deepcopy

np.random.seed(0)

def assert_equivalent_type_params(type_param1, type_param2):
    for pair in type_param1:
        if isinstance(type_param1[pair], dict):
            for key in type_param1[pair]:
                assert type_param1[pair][key] == type_param2[pair][key]
        else:
            assert type_param1[pair] == type_param2[pair]

def assert_equivalent_parameter_dicts(param_dict1, param_dict2):
    for key in param_dict1:
        assert param_dict1[key] == param_dict2[key]

def _lj_params(particle_types):
    combos = list(combinations(particle_types, 2))
    idx = np.random.choice(len(combos), size=100, replace=True)
    combos = np.array_split([combos[i] for i in idx], 10)
    sample_range = np.linspace(0.5, 1.5, 100)
    samples = np.array_split(np.random.choice(sample_range,
                                              size=100 * 3,
                                              replace=True), 3)
    pair_potential_dicts = []
    r_cut_dicts = []
    r_on_dicts = []
    count = 0
    for combo_list in combos:
        combo_pair_potentials = {}
        combo_rcuts = {}
        combo_rons = {}
        for combo in combo_list:
            combo_pair_potentials[tuple(combo)] = {'sigma': samples[0][count],
                                                   'epsilon': samples[1][count]}
            combo_rcuts[tuple(combo)] = 2.5 * samples[0][count]
            combo_rons[tuple(combo)] = 2.5 * samples[0][count] * samples[2][count]
            count += 1
        pair_potential_dicts.append(combo_pair_potentials)
        r_cut_dicts.append(combo_rcuts)
        r_on_dicts.append(combo_rons)

    pair_potential = [hoomd.md.pair.LJ] * len(combos)
    modes = np.random.choice(['none', 'shifted', 'xplor'], size=len(combos))

    return zip(pair_potential,
               pair_potential_dicts,
               r_cut_dicts,
               r_on_dicts,
               modes)

@pytest.fixture(scope="function", params=_lj_params(['A', 'B', 'C', 'D']))
def valid_params(request):
    return deepcopy(request.param)

def test_valid_params(valid_params):
    pair_potential, pair_potential_dict, r_cut, r_on, mode = valid_params
    cell = hoomd.md.nlist.Cell()
    pot = pair_potential(nlist=cell, mode=mode)
    for pair in pair_potential_dict:
        pot.params[pair] = pair_potential_dict[pair]
        pot.r_cut[pair] = r_cut[pair]
        pot.r_on[pair] = r_on[pair]

    assert_equivalent_type_params(pot.params.to_dict(), pair_potential_dict)
    assert_equivalent_type_params(pot.r_cut.to_dict(), r_cut)
    assert_equivalent_type_params(pot.r_on.to_dict(), r_on)
    assert_equivalent_parameter_dicts(pot.nlist._param_dict, cell._param_dict)
<commit_msg>Test params after attaching<commit_after>import hoomd
import pytest
import numpy as np
import itertools
from copy import deepcopy

np.random.seed(0)

def assert_equivalent_type_params(type_param1, type_param2):
    for pair in type_param1:
        if isinstance(type_param1[pair], dict):
            for key in type_param1[pair]:
                np.testing.assert_allclose(type_param1[pair][key],
                                           type_param2[pair][key])
        else:
            assert type_param1[pair] == type_param2[pair]

def assert_equivalent_parameter_dicts(param_dict1, param_dict2):
    for key in param_dict1:
        assert param_dict1[key] == param_dict2[key]

def _lj_params(particle_types):
    combos = list(itertools.combinations_with_replacement(particle_types, 2))
    N = len(combos)
    combos = [combos for i in range(1)]
    sample_range = np.linspace(0.5, 1.5, 100)
    samples = np.array_split(np.random.choice(sample_range,
                                              size=N * len(combos) * 3,
                                              replace=True), 3)
    pair_potential_dicts = []
    r_cut_dicts = []
    r_on_dicts = []
    count = 0
    for combo_list in combos:
        combo_pair_potentials = {}
        combo_rcuts = {}
        combo_rons = {}
        for combo in combo_list:
            combo_pair_potentials[tuple(combo)] = {'sigma': samples[0][count],
                                                   'epsilon': samples[1][count]}
            combo_rcuts[tuple(combo)] = 2.5 * samples[0][count]
            combo_rons[tuple(combo)] = 2.5 * samples[0][count] * samples[2][count]
            count += 1
        pair_potential_dicts.append(combo_pair_potentials)
        r_cut_dicts.append(combo_rcuts)
        r_on_dicts.append(combo_rons)

    pair_potential = [hoomd.md.pair.LJ] * len(combos)
    modes = np.random.choice(['none', 'shifted', 'xplor'], size=len(combos))

    return zip(pair_potential,
               pair_potential_dicts,
               r_cut_dicts,
               r_on_dicts,
               modes)

@pytest.fixture(scope="function", params=_lj_params(['A', 'B', 'C', 'D']))
def valid_params(request):
    return deepcopy(request.param)

def test_valid_params(valid_params):
    pair_potential, pair_potential_dict, r_cut, r_on, mode = valid_params
    cell = hoomd.md.nlist.Cell()
    pot = pair_potential(nlist=cell, mode=mode)
    for pair in pair_potential_dict:
        pot.params[pair] = pair_potential_dict[pair]
        pot.r_cut[pair] = r_cut[pair]
        pot.r_on[pair] = r_on[pair]

    assert_equivalent_type_params(pot.params.to_dict(), pair_potential_dict)
    assert_equivalent_type_params(pot.r_cut.to_dict(), r_cut)
    assert_equivalent_type_params(pot.r_on.to_dict(), r_on)
    assert_equivalent_parameter_dicts(pot.nlist._param_dict, cell._param_dict)

def test_attached_params(simulation_factory, two_particle_snapshot_factory,
                         valid_params, lattice_snapshot_factory):
    pair_potential, pair_potential_dict, r_cut, r_on, mode = valid_params
    particle_types = ['A', 'B', 'C', 'D']
    cell = hoomd.md.nlist.Cell()
    pot = pair_potential(nlist=cell, r_cut=2.5)

    for pair in pair_potential_dict:
        pot.params[pair] = pair_potential_dict[pair]
        pot.r_cut[pair] = r_cut[pair]
        pot.r_on[pair] = r_on[pair]

    snap = lattice_snapshot_factory(particle_types=particle_types,
                                    n=100, a=0.5, r=0.01)
    snap.particles.typeid[:] = np.random.randint(0, len(snap.particles.types),
                                                 snap.particles.N)
    sim = simulation_factory(snap)
    sim.operations.integrator = hoomd.md.Integrator(dt=0.005)
    sim.operations.integrator.forces.append(pot)
    sim.operations.schedule()
    attached_pot = sim.operations.integrator.forces[0]
    assert_equivalent_type_params(attached_pot.params.to_dict(),
                                  pair_potential_dict)
    assert_equivalent_type_params(attached_pot.r_cut.to_dict(), r_cut)
    assert_equivalent_type_params(attached_pot.r_on.to_dict(), r_on)
    assert_equivalent_parameter_dicts(attached_pot.nlist._param_dict,
                                      cell._param_dict)
<|endoftext|>


<commit_before>from itertools import permutations
from math import factorial
from scipy.spatial.distance import squareform
import numpy as np

def test(strings, meaning_distances, perms):

  # Compute meaning distance residuals
  meaning_residuals = residualize(meaning_distances)

  # Determine category labels and the edit-distances between them
  category_labels = list(set(strings))
  label_distances = squareform(pairwise_string_distances(category_labels))

  # Number of strings, number of categories, and number of possible category permutations
  m = len(strings)
  n = len(category_labels)
  p = factorial(n)

  # Deterministic test - measure every possible category-meaning mapping
  if p <= perms:

    # Create an empty array to store the covarience for each permutation
    covariences = np.zeros(p, dtype=float)

    # Iterate over an enumeration of all permutations of category label orders
    for i, category_labels in enumerate(permutations(category_labels)):

      # Map each string to its index in the permuted category_labels
      string_remapping = [category_labels.index(string) for string in strings]

      # Compile the string distances from the pre-computed label_distances matrix
      string_distances = [label_distances[string_remapping[j], string_remapping[k]] for j in range(0, m) for k in range(j+1, m)]

      # Residualize the string distances
      string_residuals = residualize(string_distances)

      # Store the covarience between meaning distances and string distances
      covariences[i] = (meaning_residuals * string_residuals).sum()

  # Stochasitc test - randomly sample the space of category-meaning mappings
  else:

    # Create an empty array to store the covariences
    covariences = np.zeros(perms, dtype=float)

    # Compute the veridical covarience and store it in first position
    string_residuals = residualize(pairwise_string_distances(strings))
    covariences[0] = (meaning_residuals * string_residuals).sum()

    # For each permutation...
    for i in range(1, perms):

      # Shuffle the order of category labels
      np.random.shuffle(category_labels)

      # Map each string to its index in the permuted category_labels
      string_remapping = [category_labels.index(string) for string in strings]

      # Compile the string distances from the pre-computed label_distances matrix
      string_distances = [label_distances[string_remapping[j], string_remapping[k]] for j in range(0, m) for k in range(j+1, m)]

      # Residualize the string distances
      string_residuals = residualize(string_distances)

      # Store the covarience between meaning distances and string distances
      covariences[i] = (meaning_residuals * string_residuals).sum()

  # Return standard score (z-score)
  return (covariences[0] - covariences.mean()) / covariences.std()

# Return the residuals of an array
def residualize(distances):
  distances = np.asarray(distances, dtype=float)
  return distances - distances.mean()

# Take a list of strings and compute the pairwise edit-distances
def pairwise_string_distances(strings):
  distances = []
  for i in range(0, len(strings)):
    for j in range(i+1, len(strings)):
      distances.append(norm_Levenshtein_distance(strings[i], strings[j]))
  return np.array(distances, dtype=float)

# Calculate the normalized Levenshtein distance between two strings
def norm_Levenshtein_distance(string1, string2):
  if len(string1) > len(string2):
    string1, string2 = string2, string1
  distances = range(len(string1) + 1)
  for index2, char2 in enumerate(string2):
    newDistances = [index2 + 1]
    for index1, char1 in enumerate(string1):
      if char1 == char2:
        newDistances.append(distances[index1])
      else:
        newDistances.append(1 + min((distances[index1], distances[index1+1], newDistances[-1])))
    distances = newDistances
  return float(distances[-1]) / max(len(string1), len(string2))
<commit_msg>Tucked residualization away<commit_after>from itertools import permutations
from math import factorial
from scipy.spatial.distance import squareform
import numpy as np

def test(strings, meaning_distances, perms):

  # Compute meaning distance residuals
  meaning_residuals = residualize(meaning_distances)

  # Determine category labels and the edit-distances between them
  category_labels = list(set(strings))
  label_distances = squareform(pairwise_string_distances(category_labels))

  # Number of strings, number of categories, and number of possible category permutations
  m = len(strings)
  n = len(category_labels)
  p = factorial(n)

  # Deterministic test - measure every possible category-meaning mapping
  if p <= perms:

    # Create an empty array to store the covarience for each permutation
    covariences = np.zeros(p, dtype=float)

    # Iterate over an enumeration of all permutations of category label orders
    for i, category_labels in enumerate(permutations(category_labels)):

      # Map each string to its index in the permuted category_labels
      string_remapping = [category_labels.index(string) for string in strings]

      # Compile the string distances from the pre-computed label_distances matrix
      string_distances = [label_distances[string_remapping[j], string_remapping[k]] for j in range(0, m) for k in range(j+1, m)]

      # Store the covarience between meaning distances and string distances
      covariences[i] = (meaning_residuals * residualize(string_distances)).sum()

  # Stochasitc test - randomly sample the space of category-meaning mappings
  else:

    # Create an empty array to store the covariences
    covariences = np.zeros(perms, dtype=float)

    # Compute the veridical covarience and store it in first position
    covariences[0] = (meaning_residuals * residualize(pairwise_string_distances(strings))).sum()

    # For each permutation...
    for i in range(1, perms):

      # Shuffle the order of category labels
      np.random.shuffle(category_labels)

      # Map each string to its index in the permuted category_labels
      string_remapping = [category_labels.index(string) for string in strings]

      # Compile the string distances from the pre-computed label_distances matrix
      string_distances = [label_distances[string_remapping[j], string_remapping[k]] for j in range(0, m) for k in range(j+1, m)]

      # Store the covarience between meaning distances and string distances
      covariences[i] = (meaning_residuals * residualize(string_distances)).sum()

  # Return standard score (z-score)
  return (covariences[0] - covariences.mean()) / covariences.std()

# Return the residuals of an array
def residualize(distances):
  distances = np.asarray(distances, dtype=float)
  return distances - distances.mean()

# Take a list of strings and compute the pairwise edit-distances
def pairwise_string_distances(strings):
  distances = []
  for i in range(0, len(strings)):
    for j in range(i+1, len(strings)):
      distances.append(norm_Levenshtein_distance(strings[i], strings[j]))
  return np.array(distances, dtype=float)

# Calculate the normalized Levenshtein distance between two strings
def norm_Levenshtein_distance(string1, string2):
  if len(string1) > len(string2):
    string1, string2 = string2, string1
  distances = range(len(string1) + 1)
  for index2, char2 in enumerate(string2):
    newDistances = [index2 + 1]
    for index1, char1 in enumerate(string1):
      if char1 == char2:
        newDistances.append(distances[index1])
      else:
        newDistances.append(1 + min((distances[index1], distances[index1+1], newDistances[-1])))
    distances = newDistances
  return float(distances[-1]) / max(len(string1), len(string2))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
spdypy.frame
~~~~~~~~~~~~

Defines SPDYPy's internal representation of a SPDY frame.
"""
import struct
from collections import namedtuple

# Define our control frame types.
SYN_STREAM = 1
SYN_REPLY = 2
RST_STREAM = 3
SETTINGS = 4
PING = 6
GOAWAY = 7
HEADERS = 8
WINDOW_UPDATE = 9

# Define the flags we know about.
FLAG_FIN = 'FLAG_FIN'
FLAG_UNIDIRECTIONAL = 'FLAG_UNIDIRECTIONAL'
FLAG_CLEAR_SETTINGS = 'FLAG_CLEAR_SETTINGS'
FLAG_SETTINGS_PERSIST_VALUE = 'FLAG_SETTINGS_PERSIST_VALUE'
FLAG_SETTINGS_PERSISTED = 'FLAG_SETTINGS_PERSISTED'

# Define the settings IDs.
SETTINGS_UPLOAD_BANDWIDTH = 1
SETTINGS_DOWNLOAD_BANDWIDTH = 2
SETTINGS_ROUND_TRIP_TIME = 3
SETTINGS_MAX_CONCURRENT_STREAMS = 4
SETTINGS_CURRENT_CWND = 5
SETTINGS_DOWNLOAD_RETRANS_RATE = 6
SETTINGS_INITIAL_WINDOW_SIZE = 7
SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8

# Define our NamedTuple for containing frame settings.
Settings = namedtuple('Settings', ['id', 'value', 'flags'])

def parse_flags(byte, frame_type=None):
    """
    Given the flag byte and the frame type, return the flags that have been
    set. If the frame type is not set, assumes a data frame.

    :param byte: The flag byte.
    :param frame_type: The control frame type, or None if the frame is a data
                       frame.
    """
    flags = set()

    if frame_type in (None, SYN_REPLY, HEADERS):
        if byte & 0x01:
            flags.add(FLAG_FIN)

    elif frame_type == SYN_STREAM:
        if byte & 0x01:
            flags.add(FLAG_FIN)
        if byte & 0x02:
            flags.add(FLAG_UNIDIRECTIONAL)

    elif frame_type == SETTINGS:
        if byte & 0x01:
            flags.add(FLAG_CLEAR_SETTINGS)

    return flags

def from_bytes(buffer):
    """
    Build a Frame object from the buffer. Returns the correct Frame and the
    number of bytes consumed from the buffer.

    :param buffer: The byte buffer that represents the frame.
    """
    control = buffer[0] & 0x80

    # Build the fields from the first 4 bytes, then pass the remainder off to
    # the relevant class.
    if control:
        fields = struct.unpack("!HH", buffer[0:4])
        version = fields[0] & 0x7FFF
        frame_type = fields[1]

        frame = frame_from_type.get(frame_type, Frame)()

        # Assign the fields we've already parsed.
        frame.control = True
        frame.version = version
    else:
        stream_id = struct.unpack("!L", buffer[0:4])[0] & 0x7FFFFFFF

        frame = Frame()
        frame.stream_id = stream_id

    # Let the frame build its flags up.
    frame.build_flags(buffer[4])

    # Get the length.
    length = struct.unpack("!L", buffer[4:8])[0] & 0x00FFFFFF

    # Then pass the remaining data to the data builder.
    frame.build_data(buffer[8:8 + length])

    return (frame, 8 + length)

class Frame(object):
    """
    A single SPDY frame. This is effectively an abstract base class for the
    various SPDY frame classes.
    """
    def __init__(self):
        self.control = None
        self.version = None
        self.type = None
        self.flags = set()
        self.data = None
        self.stream_id = None

    def build_flags(self, flag_byte):
        """
        This method should take a flag byte, and then populate the flags set
        on the object.
        """
        raise NotImplementedError("This is an abstract base class.")

    def build_data(self, data_buffer):
        """
        This method builds the relevant instance variables from the data buffer
        that makes up the frame body.
        """
        raise NotImplementedError("This is an abtract base class.")

class SYNMixin(object):
    """
    This mixin is used to generate the SYNStreamFrame and SYNReplyFrame
    classes. These classes reflect frames that have identical structures, and
    so will have identical implementations for a number of their methods.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.

        :param flag_byte: The byte containing the flags.
        """
        if flag_byte & 0x01:
            self.flags.add(FLAG_FIN)
        if flag_byte & 0x02:
            self.flags.add(FLAG_UNIDIRECTIONAL)

    def build_data(self, data_buffer):
        """
        Build the SYN_STREAM body fields.
        """
        fields = struct.unpack("!LLL", data_buffer[0:12])
        self.stream_id = fields[0] & 0x7FFFFFFF
        self.assoc_stream_id = fields[1] & 0x7FFFFFFF
        self.priority = (fields[2] & 0xE0000000) >> 29

        self.name_value_block = data_buffer[12:]

class SYNStreamFrame(SYNMixin, Frame):
    """
    A single SYN_STREAM frame.
    """
    pass

class SYNReplyFrame(SYNMixin, Frame):
    """
    A single SYN_REPLY frame.
    """
    pass

class RSTStreamFrame(Frame):
    """
    A single RST_STREAM frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte != 0:
            raise ValueError("RST_STREAM never defines flags.")

    def build_data(self, data_buffer):
        """
        Build the RST_STREAM body fields.
        """
        fields = struct.unpack("!LL", data_buffer[0:8])

        self.stream_id = fields[0] & 0x7FFFFFFF

        # Check the status code field as well.
        if not 0 < fields[1] < 12:
            raise RuntimeError("Invalid status code.")

        self.status_code = fields[1]

        return

class SettingsFrame(Frame):
    """
    A single SETTINGS frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte & 0x01:
            self.flags.add(FLAG_CLEAR_SETTINGS)

    def build_data(self, data_buffer):
        """
        Build the SETTINGS body fields.
        """
        self.settings = []

        # The first 32 bits define the number of setting values to expect.
        fields = struct.unpack("!L", data_buffer[0:4])[0]
        field_len = fields * 8

        # Each of the ID/value pairs is 64 bits long. Expect that many of them.
        struct_str = '!' + ('LL' * fields)
        setting_pairs = struct.unpack(struct_str, data_buffer[4:4 + field_len])

        for i in range(fields):
            # Handle the flags first.
            field_flags = set()

            if setting_pairs[i * 2] & 0x01000000:
                field_flags.add(FLAG_SETTINGS_PERSIST_VALUE)
            if setting_pairs[i * 2] & 0x02000000:
                field_flags.add(FLAG_SETTINGS_PERSISTED)

            field_id = setting_pairs[i * 2] & 0x00FFFFFF
            field_value = setting_pairs[(i * 2) + 1]

            # Add the field.
            self.settings.append(Settings(field_id, field_value, field_flags))

        return

class PingFrame(Frame):
    """
    A single PING frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte != 0:
            raise ValueError("PING never defines flags.")

    def build_data(self, data_buffer):
        self.ping_id = struct.unpack("!L", data_buffer[0:4])[0]

        return

class GoAwayFrame(Frame):
    """
    A single GOAWAY frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte != 0:
            raise ValueError("GOAWAY never defines flags.")

# Map frame indicator bytes to frame objects.
frame_from_type = {
    SYN_STREAM: SYNStreamFrame,
    SYN_REPLY: SYNReplyFrame,
    RST_STREAM: RSTStreamFrame,
    SETTINGS: SettingsFrame,
    PING: PingFrame,
}
<commit_msg>Fixup docstring.<commit_after># -*- coding: utf-8 -*-
"""
spdypy.frame
~~~~~~~~~~~~

Defines SPDYPy's internal representation of a SPDY frame.
"""
import struct
from collections import namedtuple

# Define our control frame types.
SYN_STREAM = 1
SYN_REPLY = 2
RST_STREAM = 3
SETTINGS = 4
PING = 6
GOAWAY = 7
HEADERS = 8
WINDOW_UPDATE = 9

# Define the flags we know about.
FLAG_FIN = 'FLAG_FIN'
FLAG_UNIDIRECTIONAL = 'FLAG_UNIDIRECTIONAL'
FLAG_CLEAR_SETTINGS = 'FLAG_CLEAR_SETTINGS'
FLAG_SETTINGS_PERSIST_VALUE = 'FLAG_SETTINGS_PERSIST_VALUE'
FLAG_SETTINGS_PERSISTED = 'FLAG_SETTINGS_PERSISTED'

# Define the settings IDs.
SETTINGS_UPLOAD_BANDWIDTH = 1
SETTINGS_DOWNLOAD_BANDWIDTH = 2
SETTINGS_ROUND_TRIP_TIME = 3
SETTINGS_MAX_CONCURRENT_STREAMS = 4
SETTINGS_CURRENT_CWND = 5
SETTINGS_DOWNLOAD_RETRANS_RATE = 6
SETTINGS_INITIAL_WINDOW_SIZE = 7
SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE = 8

# Define our NamedTuple for containing frame settings.
Settings = namedtuple('Settings', ['id', 'value', 'flags'])

def parse_flags(byte, frame_type=None):
    """
    Given the flag byte and the frame type, return the flags that have been
    set. If the frame type is not set, assumes a data frame.

    :param byte: The flag byte.
    :param frame_type: The control frame type, or None if the frame is a data
                       frame.
    """
    flags = set()

    if frame_type in (None, SYN_REPLY, HEADERS):
        if byte & 0x01:
            flags.add(FLAG_FIN)

    elif frame_type == SYN_STREAM:
        if byte & 0x01:
            flags.add(FLAG_FIN)
        if byte & 0x02:
            flags.add(FLAG_UNIDIRECTIONAL)

    elif frame_type == SETTINGS:
        if byte & 0x01:
            flags.add(FLAG_CLEAR_SETTINGS)

    return flags

def from_bytes(buffer):
    """
    Build a Frame object from the buffer. Returns the correct Frame and the
    number of bytes consumed from the buffer.

    :param buffer: The byte buffer that represents the frame.
    """
    control = buffer[0] & 0x80

    # Build the fields from the first 4 bytes, then pass the remainder off to
    # the relevant class.
    if control:
        fields = struct.unpack("!HH", buffer[0:4])
        version = fields[0] & 0x7FFF
        frame_type = fields[1]

        frame = frame_from_type.get(frame_type, Frame)()

        # Assign the fields we've already parsed.
        frame.control = True
        frame.version = version
    else:
        stream_id = struct.unpack("!L", buffer[0:4])[0] & 0x7FFFFFFF

        frame = Frame()
        frame.stream_id = stream_id

    # Let the frame build its flags up.
    frame.build_flags(buffer[4])

    # Get the length.
    length = struct.unpack("!L", buffer[4:8])[0] & 0x00FFFFFF

    # Then pass the remaining data to the data builder.
    frame.build_data(buffer[8:8 + length])

    return (frame, 8 + length)

class Frame(object):
    """
    A single SPDY frame. This is effectively an abstract base class for the
    various SPDY frame classes.
    """
    def __init__(self):
        self.control = None
        self.version = None
        self.type = None
        self.flags = set()
        self.data = None
        self.stream_id = None

    def build_flags(self, flag_byte):
        """
        This method should take a flag byte, and then populate the flags set
        on the object.
        """
        raise NotImplementedError("This is an abstract base class.")

    def build_data(self, data_buffer):
        """
        This method builds the relevant instance variables from the data buffer
        that makes up the frame body.
        """
        raise NotImplementedError("This is an abtract base class.")

class SYNMixin(object):
    """
    This mixin is used to generate the SYNStreamFrame and SYNReplyFrame
    classes. These classes reflect frames that have identical structures, and
    so will have identical implementations for a number of their methods.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.

        :param flag_byte: The byte containing the flags.
        """
        if flag_byte & 0x01:
            self.flags.add(FLAG_FIN)
        if flag_byte & 0x02:
            self.flags.add(FLAG_UNIDIRECTIONAL)

    def build_data(self, data_buffer):
        """
        Build the SYN_STREAM body fields.
        """
        fields = struct.unpack("!LLL", data_buffer[0:12])
        self.stream_id = fields[0] & 0x7FFFFFFF
        self.assoc_stream_id = fields[1] & 0x7FFFFFFF
        self.priority = (fields[2] & 0xE0000000) >> 29

        self.name_value_block = data_buffer[12:]

class SYNStreamFrame(SYNMixin, Frame):
    """
    A single SYN_STREAM frame.
    """
    pass

class SYNReplyFrame(SYNMixin, Frame):
    """
    A single SYN_REPLY frame.
    """
    pass

class RSTStreamFrame(Frame):
    """
    A single RST_STREAM frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte != 0:
            raise ValueError("RST_STREAM never defines flags.")

    def build_data(self, data_buffer):
        """
        Build the RST_STREAM body fields.
        """
        fields = struct.unpack("!LL", data_buffer[0:8])

        self.stream_id = fields[0] & 0x7FFFFFFF

        # Check the status code field as well.
        if not 0 < fields[1] < 12:
            raise RuntimeError("Invalid status code.")

        self.status_code = fields[1]

        return

class SettingsFrame(Frame):
    """
    A single SETTINGS frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte & 0x01:
            self.flags.add(FLAG_CLEAR_SETTINGS)

    def build_data(self, data_buffer):
        """
        Build the SETTINGS body fields.
        """
        self.settings = []

        # The first 32 bits define the number of setting values to expect.
        fields = struct.unpack("!L", data_buffer[0:4])[0]
        field_len = fields * 8

        # Each of the ID/value pairs is 64 bits long. Expect that many of them.
        struct_str = '!' + ('LL' * fields)
        setting_pairs = struct.unpack(struct_str, data_buffer[4:4 + field_len])

        for i in range(fields):
            # Handle the flags first.
            field_flags = set()

            if setting_pairs[i * 2] & 0x01000000:
                field_flags.add(FLAG_SETTINGS_PERSIST_VALUE)
            if setting_pairs[i * 2] & 0x02000000:
                field_flags.add(FLAG_SETTINGS_PERSISTED)

            field_id = setting_pairs[i * 2] & 0x00FFFFFF
            field_value = setting_pairs[(i * 2) + 1]

            # Add the field.
            self.settings.append(Settings(field_id, field_value, field_flags))

        return

class PingFrame(Frame):
    """
    A single PING frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte != 0:
            raise ValueError("PING never defines flags.")

    def build_data(self, data_buffer):
        """
        Build the PING body fields.
        """
        self.ping_id = struct.unpack("!L", data_buffer[0:4])[0]

        return

class GoAwayFrame(Frame):
    """
    A single GOAWAY frame.
    """
    def build_flags(self, flag_byte):
        """
        Build the flags for this frame from the given byte.
        """
        if flag_byte != 0:
            raise ValueError("GOAWAY never defines flags.")

# Map frame indicator bytes to frame objects.
frame_from_type = {
    SYN_STREAM: SYNStreamFrame,
    SYN_REPLY: SYNReplyFrame,
    RST_STREAM: RSTStreamFrame,
    SETTINGS: SettingsFrame,
    PING: PingFrame,
}
<|endoftext|>


<commit_before>from __future__ import absolute_import
import os
import sys
import signal
import socket
import logging
from time import time
from uuid import uuid1
from datetime import datetime
from functools import wraps
from contextlib import contextmanager

from kuyruk import events, importer
from kuyruk.queue import Queue
from kuyruk.events import EventMixin
from kuyruk.exceptions import Timeout, InvalidTask, ObjectNotFound

logger = logging.getLogger(__name__)

def profile(f):
    """Logs the time spent while running the task."""
    @wraps(f)
    def inner(self, *args, **kwargs):
        start = time()
        result = f(self, *args, **kwargs)
        end = time()
        logger.info("%s finished in %i seconds." % (self.name, end - start))
        return result
    return inner

def object_to_id(f):
    """
    If the Task is a class task, converts the first parameter to the id.

    """
    @wraps(f)
    def inner(self, *args, **kwargs):
        cls = self.cls or self.arg_class
        if cls:
            try:
                obj = args[0]
            except IndexError:
                msg = "You must give an instance of %s as first argument." % cls
                raise TypeError(msg)

            if not isinstance(obj, cls):
                msg = "First argument must be an instance of %s." % cls
                raise TypeError(msg)

            args = list(args)
            args[0] = args[0].id
            assert isinstance(args[0], (int, long, basestring))
        return f(self, *args, **kwargs)
    return inner

def id_to_object(f):
    """
    If the Task is a class task, converts the first argument to an object
    by calling the get function of the class with the id.

    """
    @wraps(f)
    def inner(self, *args, **kwargs):
        cls = self.arg_class or self.cls
        if cls:
            if not args:
                raise InvalidTask

            obj_id = args[0]
            if not isinstance(obj_id, (int, long, basestring)):
                raise InvalidTask

            obj = cls.get(obj_id)
            if obj is None:
                raise ObjectNotFound

            if not isinstance(obj, cls):
                msg = "%s is not an instance of %s." % (obj, cls)
                raise ObjectNotFound(msg)

            args = list(args)
            args[0] = obj

        return f(self, *args, **kwargs)
    return inner

def send_client_signals(f):
    """Sends the presend and postsend signals."""
    @wraps(f)
    def inner(self, *args, **kwargs):
        self.send_signal(events.task_presend, args, kwargs, reverse=True)
        rv = f(self, *args, **kwargs)
        self.send_signal(events.task_postsend, args, kwargs)
        return rv
    return inner

class Task(EventMixin):

    def __init__(self, f, kuyruk, queue='kuyruk', local=False, eager=False,
                 retry=0, max_run_time=None, arg_class=None):
        self.f = f
        self.kuyruk = kuyruk
        self.queue_name = queue
        self.local = local
        self.eager = eager
        self.retry = retry
        self.max_run_time = max_run_time
        self.cls = None
        self.arg_class = arg_class
        self.setup()

    def setup(self):
        """Convenience function for extending classes
        that run after __init__."""
        pass

    def __repr__(self):
        return "<Task of %r>" % self.name

    @send_client_signals
    @object_to_id
    def __call__(self, *args, **kwargs):
        """When a fucntion is wrapped with a task decorator it will be
        converted to a Task object. By overriding __call__ method we are
        sending this task to queue instead of invoking the function
        without changing the client code.

        """
        logger.debug("Task.__call__ args=%r, kwargs=%r", args, kwargs)

        # These keyword argument allow the sender to override
        # the destination of the message.
        host = kwargs.pop('kuyruk_host', None)
        local = kwargs.pop('kuyruk_local', None)

        if self.eager or self.kuyruk.config.EAGER:
            # Run the task in process
            task_result = self._run(*args, **kwargs)
        else:
            # Send it to the queue
            task_result = TaskResult(self)
            task_result.id = self.send_to_queue(
                args, kwargs, host=host, local=local)

        return task_result

    def __get__(self, obj, objtype):
        """If the task is accessed from an instance via attribute syntax
        returns a bound task object that wraps the task itself, otherwise
        returns the task itself.

        This is done for allowing a method to be converted to task without
        modifying the client code. When a function decorated inside a class
        there is no way of accessing that class at that time because methods
        are bounded at run time when they are accessed. The trick here is that
        we set self.cls when the Task is accessed first time via attribute
        syntax.

        """
        self.cls = objtype
        if obj:
            # Class tasks needs to know what the object is so they can
            # inject that object in front of args.
            # We are returning a BoundTask instance here wrapping this task
            # that will do the injection.
            logger.debug("Creating bound task with obj=%r", obj)
            return BoundTask(self, obj)
        return self

    def send_to_queue(self, args, kwargs, host=None, local=None):
        """
        Sends this task to queue.

        :param args: Arguments that will be passed to task on execution.
        :param kwargs: Keyword arguments that will be passed to task
            on execution.
        :param host: Send this task to specific host. ``host`` will be
            appended to the queue name.
        :param local: Send this task to this host. Hostname of this host will
            be appended to the queue name.
        :return: :const:`None`

        """
        logger.debug("Task.send_to_queueue args=%r, kwargs=%r", args, kwargs)

        with self.queue(host=host, local=local) as queue:
            desc = self.get_task_description(args, kwargs, queue.name)
            queue.send(desc)

        # We are returning the unique identifier of the task sent to queue
        # so we can query the result backend for completion.
        # TODO no result backend is available yet
        return desc['id']

    @contextmanager
    def queue(self, host=None, local=None):
        queue_ = self.queue_name
        local_ = self.local

        if local is not None:
            local_ = local

        if host:
            queue_ = "%s.%s" % (self.queue_name, host)
            local_ = False

        yield Queue(queue_, self.kuyruk.channel(), local_)

    def get_task_description(self, args, kwargs, queue):
        """Return the dictionary to be sent to the queue."""
        return {
            'id': uuid1().hex,
            'queue': queue,
            'args': args,
            'kwargs': kwargs,
            'module': self.module_name,
            'function': self.f.__name__,
            'class': self.class_name,
            'retry': self.retry,
            'sender_timestamp': datetime.utcnow(),
            'sender_hostname': socket.gethostname(),
            'sender_pid': os.getpid(),
            'sender_cmd': ' '.join(sys.argv),
        }

    def send_signal(self, signal, args, kwargs, reverse=False, **extra):
        """
        Sends a signal for each sender.
        This allows the user to register for a specific sender.

        """
        senders = (self, self.__class__, self.kuyruk)
        if reverse:
            senders = reversed(senders)

        for sender in senders:
            signal.send(sender, task=self, args=args, kwargs=kwargs, **extra)

    @send_client_signals
    @object_to_id
    def apply(self, *args, **kwargs):
        logger.debug("Task.apply args=%r, kwargs=%r", args, kwargs)
        return self._run(*args, **kwargs)

    @profile
    @id_to_object
    def _run(self, *args, **kwargs):
        """Run the wrapped function and event handlers."""
        def send_signal(signal, reverse=False, **extra):
            self.send_signal(signal, args, kwargs, reverse, **extra)

        logger.debug("Task._apply args=%r, kwargs=%r", args, kwargs)

        result = TaskResult(self)

        limit = (self.max_run_time or
                 self.kuyruk.config.MAX_TASK_RUN_TIME or 0)

        logger.debug("Applying %r, args=%r, kwargs=%r", self, args, kwargs)
        try:
            send_signal(events.task_prerun, reverse=True)
            with time_limit(limit):
                return_value = self.run(*args, **kwargs)
        except Exception:
            send_signal(events.task_failure, exc_info=sys.exc_info())
            raise
        else:
            send_signal(events.task_success, return_value=return_value)
            result.result = return_value
        finally:
            send_signal(events.task_postrun)

        # We are returning a TaskResult here because __call__ returns a
        # TaskResult object too. Return value must be consistent whether
        # task is sent to queue or executed in process with apply().
        return result

    def run(self, *args, **kwargs):
        """
        Runs the wrapped function.
        This method is intended to be overriden from subclasses.

        """
        return self.f(*args, **kwargs)

    @property
    def name(self):
        """Location for the wrapped function.
        This value is by the worker to find the task.

        """
        if self.class_name:
            return "%s:%s.%s" % (
                self.module_name, self.class_name, self.f.__name__)
        else:
            return "%s:%s" % (self.module_name, self.f.__name__)

    @property
    def module_name(self):
        """Module name of the function wrapped."""
        name = self.f.__module__
        if name == '__main__':
            name = importer.get_main_module().name
        return name

    @property
    def class_name(self):
        """Name of the class if this is a class task,
        otherwise :const:`None`."""
        if self.cls:
            return self.cls.__name__

class BoundTask(Task):
    """
    This class wraps the Task and inject the bound object in front of args
    when it is called.

    """
    def __init__(self, task, obj):
        self.task = task
        self.obj = obj

    def __getattr__(self, item):
        """Delegates all attributes to real Task."""
        return getattr(self.task, item)

    @wraps(Task.__call__)
    def __call__(self, *args, **kwargs):
        logger.debug("BoundTask.__call__ args=%r, kwargs=%r", args, kwargs)
        # Insert the bound object as a first argument to __call__
        args = list(args)
        args.insert(0, self.obj)
        return super(BoundTask, self).__call__(*args, **kwargs)

    @wraps(Task.apply)
    def apply(self, *args, **kwargs):
        logger.debug("BoundTask.apply args=%r, kwargs=%r", args, kwargs)
        args = list(args)
        args.insert(0, self.obj)
        return super(BoundTask, self).apply(*args, **kwargs)

class TaskResult(object):
    """Insance of this class is returned after the task is sent to queue.
    Since Kuyruk does not support a result backend yet it will raise
    exception on any attribute or item access.

    """
    def __init__(self, task):
        self.task = task

    def __getattr__(self, name):
        raise NotImplementedError(name)

    def __setattr__(self, name, value):
        raise NotImplementedError(name)

    def __getitem__(self, key):
        raise NotImplementedError(key)

    def __setitem__(self, key, value):
        raise NotImplementedError(key)

    def __repr__(self):
        return "<TaskResult of %r>" % self.task.name

@contextmanager
def time_limit(seconds):
    def signal_handler(signum, frame):
        raise Timeout
    signal.signal(signal.SIGALRM, signal_handler)
    signal.alarm(seconds)
    try:
        yield
    finally:
        signal.alarm(0)
<commit_msg>raise notimplemented on setattr<commit_after>from __future__ import absolute_import
import os
import sys
import signal
import socket
import logging
from time import time
from uuid import uuid1
from datetime import datetime
from functools import wraps
from contextlib import contextmanager

from kuyruk import events, importer
from kuyruk.queue import Queue
from kuyruk.events import EventMixin
from kuyruk.exceptions import Timeout, InvalidTask, ObjectNotFound

logger = logging.getLogger(__name__)

def profile(f):
    """Logs the time spent while running the task."""
    @wraps(f)
    def inner(self, *args, **kwargs):
        start = time()
        result = f(self, *args, **kwargs)
        end = time()
        logger.info("%s finished in %i seconds." % (self.name, end - start))
        return result
    return inner

def object_to_id(f):
    """
    If the Task is a class task, converts the first parameter to the id.

    """
    @wraps(f)
    def inner(self, *args, **kwargs):
        cls = self.cls or self.arg_class
        if cls:
            try:
                obj = args[0]
            except IndexError:
                msg = "You must give an instance of %s as first argument." % cls
                raise TypeError(msg)

            if not isinstance(obj, cls):
                msg = "First argument must be an instance of %s." % cls
                raise TypeError(msg)

            args = list(args)
            args[0] = args[0].id
            assert isinstance(args[0], (int, long, basestring))
        return f(self, *args, **kwargs)
    return inner

def id_to_object(f):
    """
    If the Task is a class task, converts the first argument to an object
    by calling the get function of the class with the id.

    """
    @wraps(f)
    def inner(self, *args, **kwargs):
        cls = self.arg_class or self.cls
        if cls:
            if not args:
                raise InvalidTask

            obj_id = args[0]
            if not isinstance(obj_id, (int, long, basestring)):
                raise InvalidTask

            obj = cls.get(obj_id)
            if obj is None:
                raise ObjectNotFound

            if not isinstance(obj, cls):
                msg = "%s is not an instance of %s." % (obj, cls)
                raise ObjectNotFound(msg)

            args = list(args)
            args[0] = obj

        return f(self, *args, **kwargs)
    return inner

def send_client_signals(f):
    """Sends the presend and postsend signals."""
    @wraps(f)
    def inner(self, *args, **kwargs):
        self.send_signal(events.task_presend, args, kwargs, reverse=True)
        rv = f(self, *args, **kwargs)
        self.send_signal(events.task_postsend, args, kwargs)
        return rv
    return inner

class Task(EventMixin):

    def __init__(self, f, kuyruk, queue='kuyruk', local=False, eager=False,
                 retry=0, max_run_time=None, arg_class=None):
        self.f = f
        self.kuyruk = kuyruk
        self.queue_name = queue
        self.local = local
        self.eager = eager
        self.retry = retry
        self.max_run_time = max_run_time
        self.cls = None
        self.arg_class = arg_class
        self.setup()

    def setup(self):
        """Convenience function for extending classes
        that run after __init__."""
        pass

    def __repr__(self):
        return "<Task of %r>" % self.name

    @send_client_signals
    @object_to_id
    def __call__(self, *args, **kwargs):
        """When a fucntion is wrapped with a task decorator it will be
        converted to a Task object. By overriding __call__ method we are
        sending this task to queue instead of invoking the function
        without changing the client code.

        """
        logger.debug("Task.__call__ args=%r, kwargs=%r", args, kwargs)

        # These keyword argument allow the sender to override
        # the destination of the message.
        host = kwargs.pop('kuyruk_host', None)
        local = kwargs.pop('kuyruk_local', None)

        if self.eager or self.kuyruk.config.EAGER:
            # Run the task in process
            task_result = self._run(*args, **kwargs)
        else:
            # Send it to the queue
            task_result = TaskResult(self)
            task_result.id = self.send_to_queue(
                args, kwargs, host=host, local=local)

        return task_result

    def __get__(self, obj, objtype):
        """If the task is accessed from an instance via attribute syntax
        returns a bound task object that wraps the task itself, otherwise
        returns the task itself.

        This is done for allowing a method to be converted to task without
        modifying the client code. When a function decorated inside a class
        there is no way of accessing that class at that time because methods
        are bounded at run time when they are accessed. The trick here is that
        we set self.cls when the Task is accessed first time via attribute
        syntax.

        """
        self.cls = objtype
        if obj:
            # Class tasks needs to know what the object is so they can
            # inject that object in front of args.
            # We are returning a BoundTask instance here wrapping this task
            # that will do the injection.
            logger.debug("Creating bound task with obj=%r", obj)
            return BoundTask(self, obj)
        return self

    def send_to_queue(self, args, kwargs, host=None, local=None):
        """
        Sends this task to queue.

        :param args: Arguments that will be passed to task on execution.
        :param kwargs: Keyword arguments that will be passed to task
            on execution.
        :param host: Send this task to specific host. ``host`` will be
            appended to the queue name.
        :param local: Send this task to this host. Hostname of this host will
            be appended to the queue name.
        :return: :const:`None`

        """
        logger.debug("Task.send_to_queueue args=%r, kwargs=%r", args, kwargs)

        with self.queue(host=host, local=local) as queue:
            desc = self.get_task_description(args, kwargs, queue.name)
            queue.send(desc)

        # We are returning the unique identifier of the task sent to queue
        # so we can query the result backend for completion.
        # TODO no result backend is available yet
        return desc['id']

    @contextmanager
    def queue(self, host=None, local=None):
        queue_ = self.queue_name
        local_ = self.local

        if local is not None:
            local_ = local

        if host:
            queue_ = "%s.%s" % (self.queue_name, host)
            local_ = False

        yield Queue(queue_, self.kuyruk.channel(), local_)

    def get_task_description(self, args, kwargs, queue):
        """Return the dictionary to be sent to the queue."""
        return {
            'id': uuid1().hex,
            'queue': queue,
            'args': args,
            'kwargs': kwargs,
            'module': self.module_name,
            'function': self.f.__name__,
            'class': self.class_name,
            'retry': self.retry,
            'sender_timestamp': datetime.utcnow(),
            'sender_hostname': socket.gethostname(),
            'sender_pid': os.getpid(),
            'sender_cmd': ' '.join(sys.argv),
        }

    def send_signal(self, signal, args, kwargs, reverse=False, **extra):
        """
        Sends a signal for each sender.
        This allows the user to register for a specific sender.

        """
        senders = (self, self.__class__, self.kuyruk)
        if reverse:
            senders = reversed(senders)

        for sender in senders:
            signal.send(sender, task=self, args=args, kwargs=kwargs, **extra)

    @send_client_signals
    @object_to_id
    def apply(self, *args, **kwargs):
        logger.debug("Task.apply args=%r, kwargs=%r", args, kwargs)
        return self._run(*args, **kwargs)

    @profile
    @id_to_object
    def _run(self, *args, **kwargs):
        """Run the wrapped function and event handlers."""
        def send_signal(signal, reverse=False, **extra):
            self.send_signal(signal, args, kwargs, reverse, **extra)

        logger.debug("Task._apply args=%r, kwargs=%r", args, kwargs)

        result = TaskResult(self)

        limit = (self.max_run_time or
                 self.kuyruk.config.MAX_TASK_RUN_TIME or 0)

        logger.debug("Applying %r, args=%r, kwargs=%r", self, args, kwargs)
        try:
            send_signal(events.task_prerun, reverse=True)
            with time_limit(limit):
                return_value = self.run(*args, **kwargs)
        except Exception:
            send_signal(events.task_failure, exc_info=sys.exc_info())
            raise
        else:
            send_signal(events.task_success, return_value=return_value)
            result.result = return_value
        finally:
            send_signal(events.task_postrun)

        # We are returning a TaskResult here because __call__ returns a
        # TaskResult object too. Return value must be consistent whether
        # task is sent to queue or executed in process with apply().
        return result

    def run(self, *args, **kwargs):
        """
        Runs the wrapped function.
        This method is intended to be overriden from subclasses.

        """
        return self.f(*args, **kwargs)

    @property
    def name(self):
        """Location for the wrapped function.
        This value is by the worker to find the task.

        """
        if self.class_name:
            return "%s:%s.%s" % (
                self.module_name, self.class_name, self.f.__name__)
        else:
            return "%s:%s" % (self.module_name, self.f.__name__)

    @property
    def module_name(self):
        """Module name of the function wrapped."""
        name = self.f.__module__
        if name == '__main__':
            name = importer.get_main_module().name
        return name

    @property
    def class_name(self):
        """Name of the class if this is a class task,
        otherwise :const:`None`."""
        if self.cls:
            return self.cls.__name__

class BoundTask(Task):
    """
    This class wraps the Task and inject the bound object in front of args
    when it is called.

    """
    def __init__(self, task, obj):
        self.task = task
        self.obj = obj

    def __getattr__(self, item):
        """Delegates all attributes to real Task."""
        return getattr(self.task, item)

    @wraps(Task.__call__)
    def __call__(self, *args, **kwargs):
        logger.debug("BoundTask.__call__ args=%r, kwargs=%r", args, kwargs)
        # Insert the bound object as a first argument to __call__
        args = list(args)
        args.insert(0, self.obj)
        return super(BoundTask, self).__call__(*args, **kwargs)

    @wraps(Task.apply)
    def apply(self, *args, **kwargs):
        logger.debug("BoundTask.apply args=%r, kwargs=%r", args, kwargs)
        args = list(args)
        args.insert(0, self.obj)
        return super(BoundTask, self).apply(*args, **kwargs)

class TaskResult(object):
    """Insance of this class is returned after the task is sent to queue.
    Since Kuyruk does not support a result backend yet it will raise
    exception on any attribute or item access.

    """
    def __init__(self, task):
        self.task = task

    def __getattr__(self, name):
        raise NotImplementedError(name)

    def __setattr__(self, name, value):
        if name not in ('task', 'id', 'result'):
            raise NotImplementedError(name)
        super(TaskResult, self).__setattr__(name, value)

    def __getitem__(self, key):
        raise NotImplementedError(key)

    def __setitem__(self, key, value):
        raise NotImplementedError(key)

    def __repr__(self):
        return "<TaskResult of %r>" % self.task.name

@contextmanager
def time_limit(seconds):
    def signal_handler(signum, frame):
        raise Timeout
    signal.signal(signal.SIGALRM, signal_handler)
    signal.alarm(seconds)
    try:
        yield
    finally:
        signal.alarm(0)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright 2016 Taŭga Tecnologia
#    Aristides Caldeira <aristides.caldeira@tauga.com.br>
# License AGPL-3 or later (http://www.gnu.org/licenses/agpl)
#

{
    'name': u'SPED',
    'category': 'Fiscal',
    'version': '10.0.1.0.0',
    'author': u'Odoo Community Association (OCA), Ari Caldeira',
    'category': u'Base',
    'license': 'AGPL-3',
    'depends': [
        'l10n_br_base',
        'sped_imposto',
        'document',
        'product',
    ],
    'installable': True,
    'application': True,
    'data': [
        'report/sped_documento_report.xml',
        #
        # Menus
        #
        'views/sped_view.xml',

        #
        # Fiscal
        #
        'views/sped_veiculo_view.xml',

        'views/inherited_sped_operacao_base_view.xml',

        'views/sped_documento_item_declaracao_importacao_view.xml',
        'views/sped_documento_item_rastreabilidade_view.xml',
        'views/sped_documento_item_base_view.xml',
        'views/sped_documento_item_emissao_view.xml',

        'views/sped_documento_referenciado_view.xml',
        'views/sped_documento_pagamento_view.xml',

        'views/sped_documento_subsequente_view.xml',

        'views/sped_documento_base_view.xml',

        'views/sped_documento_emissao_nfe_view.xml',
        'views/sped_documento_emissao_nfce_view.xml',
        'views/sped_documento_emissao_nfse_view.xml',

        'views/sped_documento_item_emissao_servico_view.xml',
        'views/sped_documento_recebimento_nfe_view.xml',

        #
        # Grupos e permissões
        #
        'security/sped_documento_ir_rule.xml',
        'security/ir.model.access.csv',

        #
        # Dados de base
        #
        'demo/sped_participante_demo.xml',
    ],
    'external_dependencies': {
        'python': [
            'pybrasil',
            'email_validator',
        ],
    }
}
<commit_msg>[FIX]Correção no dict<commit_after># -*- coding: utf-8 -*-
#
# Copyright 2016 Taŭga Tecnologia
#    Aristides Caldeira <aristides.caldeira@tauga.com.br>
# License AGPL-3 or later (http://www.gnu.org/licenses/agpl)
#

{
    'name': u'SPED',
    'category': 'Fiscal',
    'version': '10.0.1.0.0',
    'author': u'Odoo Community Association (OCA), Ari Caldeira',
    'category': u'Base',
    'license': 'AGPL-3',
    'depends': [
        'l10n_br_base',
        'sped_imposto',
        'document',
        'product',
    ],
    'installable': True,
    'application': True,
    'data': [
        'report/sped_documento_report.xml',
        #
        # Menus
        #
        'views/sped_view.xml',

        #
        # Fiscal
        #
        'views/sped_veiculo_view.xml',

        'views/inherited_sped_operacao_base_view.xml',

        'views/sped_documento_item_declaracao_importacao_view.xml',
        'views/sped_documento_item_rastreabilidade_view.xml',
        'views/sped_documento_item_base_view.xml',
        'views/sped_documento_item_emissao_view.xml',

        'views/sped_documento_referenciado_view.xml',
        'views/sped_documento_pagamento_view.xml',

        'views/sped_documento_subsequente_view.xml',

        'views/sped_documento_base_view.xml',

        'views/sped_documento_emissao_nfe_view.xml',
        'views/sped_documento_emissao_nfce_view.xml',
        'views/sped_documento_emissao_nfse_view.xml',

        'views/sped_documento_item_emissao_servico_view.xml',
        'views/sped_documento_recebimento_nfe_view.xml',

        #
        # Grupos e permissões
        #
        'security/sped_documento_ir_rule.xml',
        'security/ir.model.access.csv',

    ],
    'demo': [
        'demo/sped_participante_demo.xml',
    ],
    'external_dependencies': {
        'python': [
            'pybrasil',
            'email_validator',
        ],
    }
}
<|endoftext|>