<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2010 British Broadcasting Corporation and Kamaelia Contributors(1)
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://www.kamaelia.org/AUTHORS - please extend this file,
#     not this notice.
#
# 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.
# -------------------------------------------------------------------------

"""\
==================
General Interactor
==================

This component implements the basic functionality of an Interactor. An
Interactor listens to events of another component and tranlates them
into movement which is applied to the target component. It provides
methods to be overridden for adding functionality.

Example Usage
-------------
A very simple Interactor could look like this::

    class VerySimpleInteractor(Interactor):
        def makeInteractorLinkages(self):
            self.link( (self,"outbox"), (self.target, "rel_rotation") )

        def setup(self):
            self.addListenEvents([pygame.MOUSEBUTTONDOWN])

        def handleEvents(self):
            while self.dataReady("events"):
                event = self.recv("events")
                if self.identifier in event.hitobjects:
                    self.send((0,90,0))

For examples of how to create Interactors have a look at the files
XXXInteractor.py.

A MatchedInteractor and a RotationInteractor each interacting with a
SimpleCube::

    CUBE1 = SimpleCube(size=(1,1,1), position=(1,0,0)).activate()
    CUBE2 = SimpleCube(size=(1,1,1), position=(-1,0,0)).activate()
    INTERACTOR1 = MatchedTranslationInteractor(target=CUBE1).activate()
    INTERACTOR2 = SimpleRotationInteractor(target=CUBE2).activate()

    Axon.Scheduler.scheduler.run.runThreads()

How does it work?
-----------------
Interactor provides functionality for interaction with the OpenGL
display service and OpenGL components. It is designed to be subclassed.
The following methods are provided to be overridden:

- makeInteractorLinkages() -- make linkages to and from targets needed
- setup()                  -- set up the component
- handleEvents()           -- handle input events ("events" inbox)
- frame()                  -- called every frame, to add additional functionality

Stubs method are provided, so missing these out does not result in
broken code. The methods get called from the main method, the following
code shows in which order::

    def main(self):
        # create and send eventspy request
        ...
        # setup function from derived objects
        self.setup()
        ...
        while 1:
            yield 1
            # handle events function from derived objects
            self.handleEvents()
            # frame function from derived objects
            self.frame()

If you need to override the __init__() method, e.g. to get
initialisation parameters, make sure to pass on all keyword arguments to
__init__(...) of the superclass, e.g.::

    def __init__(self, **argd):
        super(ClassName, self).__init__(**argd)
        # get an initialisation parameter
        myparam = argd.get("myparam", defaultvalue)

The following methods are provided to be used by inherited objects:

- addListenEvents(list of events) -- Request reception of a list of events
- removeListenEvents(list of events) -- Stop reveiving events

The are inteded to simplify component handling. For their functionality
see their description.

The event identifier of the target component gets saved in
self.identifier. Use this variable in event handling to determine if the
target component has been hit.

Interactor components terminate if a producerFinished or
shutdownMicroprocess message is received on their "control" inbox. The
received message is also forwarded to the "signal" outbox. Upon
termination, this component does *not* unbind itself from the
OpenGLDisplay service and does not free any requested resources.

"""

import pygame
from pygame.locals import *
from OpenGLDisplay import *

import Axon

class Interactor(Axon.AdaptiveCommsComponent.AdaptiveCommsComponent):
    """\
    Interactor(...) -> A new Interactor object (not very useful, designed to be subclassed)

    This component implements the basic functionality of an Interactor. An
    Interactor listens to events of another component and tranlates them
    into movement which is applied to the target component. It provides
    methods to be overridden for adding functionality.

    Keyword arguments:

    - target    -- OpenGL component to interact with
    - nolink    -- if True, no linkages are made (default=False)
    """

    Inboxes = {
        "inbox"      : "not used",
        "control"    : "For shutdown messages",
        "events"     : "Input events",
        "callback"   : "for the response after a displayrequest",
    }

    Outboxes = {
        "outbox"        : "used for sending relative tranlational movement",
        "signal"        : "For shutdown messages",
        "display_signal": "Outbox used for communicating to the display surface",
    }

    def __init__(self, **argd):
        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
        super(Interactor, self).__init__()

        # get display service
        displayservice = OpenGLDisplay.getDisplayService()
        # link display_signal to displayservice
        self.link((self,"display_signal"), displayservice)

        self.target = argd.get("target")

        self.nolink = argd.get("nolink", False)

    def main(self):
        # create eventspy request
        self.eventspyrequest = { "EVENTSPYREQUEST" : True,
                                                   "objectid" : id(self),
                                                   "target": id(self.target),
                                                   "callback" : (self,"callback"),
                                                   "events" : (self, "events")  }

        # send display request
        self.send(self.eventspyrequest, "display_signal")

        # setup function from derived objects
        self.setup()

        # wait for response on displayrequest
        while not self.dataReady("callback"): yield 1
        self.identifier = self.recv("callback")

        while 1:
            yield 1

            while self.dataReady("control"):
                cmsg = self.recv("control")
                if isinstance(cmsg, producerFinished) or isinstance(cmsg, shutdownMicroprocess):
                    self.send(cmsg, "signal")
                    return

            # handle events function from derived objects
            self.handleEvents()
            # frame function from derived objects
            self.frame()

    ##
    # Methods to be used by derived objects
    ##

    def addListenEvents(self, events):
        """\
        Sends listening request for pygame events to the display service.
        The events parameter is expected to be a list of pygame event constants.
        """
        for event in events:
            self.send({"ADDLISTENEVENT":event, "objectid":id(self)}, "display_signal")

    def removeListenEvents(self, events):
        """\
        Sends stop listening request for pygame events to the display service.
        The events parameter is expected to be a list of pygame event constants.
        """
        for event in events:
            self.send({"REMOVELISTENEVENT":event, "objectid":id(self)}, "display_signal")

    ##
    # Method stubs to be overridden by derived objects
    ##
    def makeInteractorLinkages(self):
        """ Method stub """
        pass

    def handleEvents(self):
        """
        Method stub

        Override this method to do event handling inside.
        Should look like this::

            while self.dataReady("events"):
                event = self.recv("events")
                # handle event ...

        """
        pass

    def setup(self):
        """
        Method stub

        Override this method for component setup.
        It will be called on the first scheduling of the component.
        """
        pass

    def frame(self):
        """
        Method stub

        Override this method for operations you want to do every frame.
        It will be called every time the component is scheduled. Do not
        include infinite loops, the method has to return every time it
        gets called.
        """
        pass

__kamaelia_components__ = ( Interactor, )

# Licensed to the BBC under a Contributor Agreement: THF
<commit_msg>Changed to reduce CPU usage<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2010 British Broadcasting Corporation and Kamaelia Contributors(1)
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://www.kamaelia.org/AUTHORS - please extend this file,
#     not this notice.
#
# 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.
# -------------------------------------------------------------------------

"""\
==================
General Interactor
==================

This component implements the basic functionality of an Interactor. An
Interactor listens to events of another component and tranlates them
into movement which is applied to the target component. It provides
methods to be overridden for adding functionality.

Example Usage
-------------
A very simple Interactor could look like this::

    class VerySimpleInteractor(Interactor):
        def makeInteractorLinkages(self):
            self.link( (self,"outbox"), (self.target, "rel_rotation") )

        def setup(self):
            self.addListenEvents([pygame.MOUSEBUTTONDOWN])

        def handleEvents(self):
            while self.dataReady("events"):
                event = self.recv("events")
                if self.identifier in event.hitobjects:
                    self.send((0,90,0))

For examples of how to create Interactors have a look at the files
XXXInteractor.py.

A MatchedInteractor and a RotationInteractor each interacting with a
SimpleCube::

    CUBE1 = SimpleCube(size=(1,1,1), position=(1,0,0)).activate()
    CUBE2 = SimpleCube(size=(1,1,1), position=(-1,0,0)).activate()
    INTERACTOR1 = MatchedTranslationInteractor(target=CUBE1).activate()
    INTERACTOR2 = SimpleRotationInteractor(target=CUBE2).activate()

    Axon.Scheduler.scheduler.run.runThreads()

How does it work?
-----------------
Interactor provides functionality for interaction with the OpenGL
display service and OpenGL components. It is designed to be subclassed.
The following methods are provided to be overridden:

- makeInteractorLinkages() -- make linkages to and from targets needed
- setup()                  -- set up the component
- handleEvents()           -- handle input events ("events" inbox)
- frame()                  -- called every frame, to add additional functionality

Stubs method are provided, so missing these out does not result in
broken code. The methods get called from the main method, the following
code shows in which order::

    def main(self):
        # create and send eventspy request
        ...
        # setup function from derived objects
        self.setup()
        ...
        while 1:
            yield 1
            # handle events function from derived objects
            self.handleEvents()
            # frame function from derived objects
            self.frame()

If you need to override the __init__() method, e.g. to get
initialisation parameters, make sure to pass on all keyword arguments to
__init__(...) of the superclass, e.g.::

    def __init__(self, **argd):
        super(ClassName, self).__init__(**argd)
        # get an initialisation parameter
        myparam = argd.get("myparam", defaultvalue)

The following methods are provided to be used by inherited objects:

- addListenEvents(list of events) -- Request reception of a list of events
- removeListenEvents(list of events) -- Stop reveiving events

The are inteded to simplify component handling. For their functionality
see their description.

The event identifier of the target component gets saved in
self.identifier. Use this variable in event handling to determine if the
target component has been hit.

Interactor components terminate if a producerFinished or
shutdownMicroprocess message is received on their "control" inbox. The
received message is also forwarded to the "signal" outbox. Upon
termination, this component does *not* unbind itself from the
OpenGLDisplay service and does not free any requested resources.

"""

import pygame
from pygame.locals import *
from OpenGLDisplay import *

import Axon

class Interactor(Axon.AdaptiveCommsComponent.AdaptiveCommsComponent):
    """\
    Interactor(...) -> A new Interactor object (not very useful, designed to be subclassed)

    This component implements the basic functionality of an Interactor. An
    Interactor listens to events of another component and tranlates them
    into movement which is applied to the target component. It provides
    methods to be overridden for adding functionality.

    Keyword arguments:

    - target    -- OpenGL component to interact with
    - nolink    -- if True, no linkages are made (default=False)
    """

    Inboxes = {
        "inbox"      : "not used",
        "control"    : "For shutdown messages",
        "events"     : "Input events",
        "callback"   : "for the response after a displayrequest",
    }

    Outboxes = {
        "outbox"        : "used for sending relative tranlational movement",
        "signal"        : "For shutdown messages",
        "display_signal": "Outbox used for communicating to the display surface",
    }

    def __init__(self, **argd):
        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
        super(Interactor, self).__init__()

        # get display service
        displayservice = OpenGLDisplay.getDisplayService()
        # link display_signal to displayservice
        self.link((self,"display_signal"), displayservice)

        self.target = argd.get("target")

        self.nolink = argd.get("nolink", False)

    def main(self):
        # create eventspy request
        self.eventspyrequest = { "EVENTSPYREQUEST" : True,
                                                   "objectid" : id(self),
                                                   "target": id(self.target),
                                                   "callback" : (self,"callback"),
                                                   "events" : (self, "events")  }

        # send display request
        self.send(self.eventspyrequest, "display_signal")

        # setup function from derived objects
        self.setup()

        # wait for response on displayrequest
        while not self.dataReady("callback"): yield 1
        self.identifier = self.recv("callback")

        while 1:
            yield 1

            while self.dataReady("control"):
                cmsg = self.recv("control")
                if isinstance(cmsg, producerFinished) or isinstance(cmsg, shutdownMicroprocess):
                    self.send(cmsg, "signal")
                    return

            # handle events function from derived objects
            self.handleEvents()
            # frame function from derived objects
            self.frame()
            while not self.anyReady():
                self.pause()
                yield 1

    ##
    # Methods to be used by derived objects
    ##

    def addListenEvents(self, events):
        """\
        Sends listening request for pygame events to the display service.
        The events parameter is expected to be a list of pygame event constants.
        """
        for event in events:
            self.send({"ADDLISTENEVENT":event, "objectid":id(self)}, "display_signal")

    def removeListenEvents(self, events):
        """\
        Sends stop listening request for pygame events to the display service.
        The events parameter is expected to be a list of pygame event constants.
        """
        for event in events:
            self.send({"REMOVELISTENEVENT":event, "objectid":id(self)}, "display_signal")

    ##
    # Method stubs to be overridden by derived objects
    ##
    def makeInteractorLinkages(self):
        """ Method stub """
        pass

    def handleEvents(self):
        """
        Method stub

        Override this method to do event handling inside.
        Should look like this::

            while self.dataReady("events"):
                event = self.recv("events")
                # handle event ...

        """
        pass

    def setup(self):
        """
        Method stub

        Override this method for component setup.
        It will be called on the first scheduling of the component.
        """
        pass

    def frame(self):
        """
        Method stub

        Override this method for operations you want to do every frame.
        It will be called every time the component is scheduled. Do not
        include infinite loops, the method has to return every time it
        gets called.
        """
        pass

__kamaelia_components__ = ( Interactor, )

# Licensed to the BBC under a Contributor Agreement: THF
<|endoftext|>


<commit_before>import pandas
import numpy
import itertools
import io
import cpgintegrate
from cpgintegrate import ColumnInfoFrame

def to_frame(file):
    # Blood pressure results from file-ish object

    file_as_string = file.read().decode('utf-8')

    if file_as_string.startswith("Measurement"):
        # Format from new software in June 2017, harmonise to old format even though it's objectively worse
        # print("New format: %s" % file.name)
        sheet = pandas.DataFrame(index=[0])

        data = pandas.read_csv(io.StringIO(file_as_string))
        data.columns = (col.strip() for col in data.columns)

        # Extra variable because new version doesn't have seconds in timestamp
        data['Meas_num'] = data.groupby("Measurement").cumcount()

        data_measures = data.melt(["Meas_num", "Measurement"], value_vars="Data")
        data_other = data.melt("Meas_num", ["Data & Alerts", "Date"]).drop_duplicates(["Meas_num", "variable"])
        data_measures['variable'] = data_measures['Measurement']

        data = pandas.concat([data_measures, data_other]).pivot("Meas_num", "variable", "value")

        data['Date'], data['Time'] = zip(*data['Date'].str.split())

        data.rename(columns={"Pulse": "Pulse (Pulses/min)",
                             "Systolic": "SYS (mmHg)",
                             "Diastolic": "DIA (mmHg)"}, inplace=True)

        data['Irregular Heartbeat (y or n)'], data['Excessive Movement (y or n)'] = zip(*[
            ("y" if alert == " Irregular Heartbeat" else "n",
             "y" if alert == " Excessive Movement" else "n") for alert in data["Data & Alerts"]
        ])

        data.drop("Data & Alerts", axis=1, inplace=True)
    else:
        sheet = pandas.DataFrame({"SubjectID": [file_as_string.splitlines()[0].split(",")[0]]})

        data = pandas.read_csv(io.StringIO(file_as_string), skiprows=2)

    avgs = ['SYS (mmHg)', 'DIA (mmHg)']

    # Mean of 2nd and 3rd if difference <= 10, otherwise mean of lowest difference pair
    for avg in avgs:
        if len(data[avg]) < 3:
            sheet[avg] = data[avg].iloc[-1]
        else:
            seq = data[avg][1:]
            if (seq[1] - seq[2]) < 10:
                sheet[avg] = seq[1:3].mean()
            else:
                pairs = [(numpy.mean([i, i1]), abs(i-i1)) for i, i1 in itertools.combinations(seq, 2)]
                sheet[avg] = min(pairs, key=lambda t: t[1])[0]

    sheet['Pulse (Pulses/min)'] = data['Pulse (Pulses/min)'][1:].mean()
    sheet['Irregular Hearbeats'] = len(data[data['Irregular Heartbeat (y or n)'] == 'y'].index)
    sheet['Excessive Movements'] = len(data[data['Excessive Movement (y or n)'] == 'y'].index)

    new_col_names = [col.split('(')[0].strip() for col in sheet.columns]
    col_info = {new: {cpgintegrate.UNITS_ATTRIBUTE_NAME: old.split('(')[1]}
                for old, new in zip(sheet.columns, new_col_names) if '(' in old}
    sheet.columns = new_col_names

    return ColumnInfoFrame(sheet,column_info=col_info)
<commit_msg>Corrects omron bp units<commit_after>import pandas
import numpy
import itertools
import io
import cpgintegrate
from cpgintegrate import ColumnInfoFrame

def to_frame(file):
    # Blood pressure results from file-ish object

    file_as_string = file.read().decode('utf-8')

    if file_as_string.startswith("Measurement"):
        # Format from new software in June 2017, harmonise to old format even though it's objectively worse
        # print("New format: %s" % file.name)
        sheet = pandas.DataFrame(index=[0])

        data = pandas.read_csv(io.StringIO(file_as_string))
        data.columns = (col.strip() for col in data.columns)

        # Extra variable because new version doesn't have seconds in timestamp
        data['Meas_num'] = data.groupby("Measurement").cumcount()

        data_measures = data.melt(["Meas_num", "Measurement"], value_vars="Data")
        data_other = data.melt("Meas_num", ["Data & Alerts", "Date"]).drop_duplicates(["Meas_num", "variable"])
        data_measures['variable'] = data_measures['Measurement']

        data = pandas.concat([data_measures, data_other]).pivot("Meas_num", "variable", "value")

        data['Date'], data['Time'] = zip(*data['Date'].str.split())

        data.rename(columns={"Pulse": "Pulse (Pulses/min)",
                             "Systolic": "SYS (mmHg)",
                             "Diastolic": "DIA (mmHg)"}, inplace=True)

        data['Irregular Heartbeat (y or n)'], data['Excessive Movement (y or n)'] = zip(*[
            ("y" if alert == " Irregular Heartbeat" else "n",
             "y" if alert == " Excessive Movement" else "n") for alert in data["Data & Alerts"]
        ])

        data.drop("Data & Alerts", axis=1, inplace=True)
    else:
        sheet = pandas.DataFrame({"SubjectID": [file_as_string.splitlines()[0].split(",")[0]]})

        data = pandas.read_csv(io.StringIO(file_as_string), skiprows=2)

    avgs = ['SYS (mmHg)', 'DIA (mmHg)']

    # Mean of 2nd and 3rd if difference <= 10, otherwise mean of lowest difference pair
    for avg in avgs:
        if len(data[avg]) < 3:
            sheet[avg] = data[avg].iloc[-1]
        else:
            seq = data[avg][1:]
            if (seq[1] - seq[2]) < 10:
                sheet[avg] = seq[1:3].mean()
            else:
                pairs = [(numpy.mean([i, i1]), abs(i-i1)) for i, i1 in itertools.combinations(seq, 2)]
                sheet[avg] = min(pairs, key=lambda t: t[1])[0]

    sheet['Pulse (Pulses/min)'] = data['Pulse (Pulses/min)'][1:].mean()
    sheet['Irregular Hearbeats'] = len(data[data['Irregular Heartbeat (y or n)'] == 'y'].index)
    sheet['Excessive Movements'] = len(data[data['Excessive Movement (y or n)'] == 'y'].index)

    new_col_names = [col.split('(')[0].strip() for col in sheet.columns]
    col_info = {new: {cpgintegrate.UNITS_ATTRIBUTE_NAME: old.split('(')[1][:-1]}
                for old, new in zip(sheet.columns, new_col_names) if '(' in old}
    sheet.columns = new_col_names

    return ColumnInfoFrame(sheet,column_info=col_info)
<|endoftext|>


<commit_before>#!/usr/bin/python

import sys
import subprocess
import os
import re

def main():
    check_inputs()
    path = get_path()
    files = get_files(path)
    for file in files :
        file_to_test = TestFile(file)
        file_to_test.run_tests()

def check_inputs():
    if len(sys.argv) != 2:
        print 'Usage: run_all_inputs.py <path_to_Input_folder>'
        sys.exit(1)

def get_path():
    path = sys.argv[1]
    return path

def get_files(path):
    full_paths=[]
    for root, dirs, files in os.walk(path, followlinks=True):
        if '.git' in dirs:
            dirs.remove('.git')
        for name in files:
            if re.search("test.*\.xml",name):
                full_paths.append(os.path.join(root, name))
            else :
                files.remove(name)
    print "The files to be tested are:"
    print full_paths
    return full_paths

class TestFile():
    """An object representing the inputxml file to test"""
    def __init__(self, file_path):
        self.name = file_path # strip off front bit

    def run_tests(self):
        """Runs all of the input file tests"""
        output = self.get_output()
        self.test_no_errors(output)
        self.test_expected(output)

    def get_output(self):
        """Returns the output from running the FileTest"""
        flags = " -v9"
        try :
            input_output = subprocess.Popen("./cyclus "+self.name+flags,
                    shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError, e:
            print(e)
        return output

    def test_no_errors(self, output):
        """returns true if there were no errors or segfaults running this TestFile"""
        to_ret = True
        print "Test " + self.name
        if re.search("ERROR",output) or re.search("Segmentation fault",output):
            to_ret = False
            print " resulted in errors: "
            print output
        else :
            print " passed. "
        return to_ret

    def test_expected(self, output):
        """This function is currently a placeholder. It is intended to print the
        difference between the current output and the output gathered the last
        time the test was run"""
        return True

if __name__ == '__main__' : main()
<commit_msg>got output part of io_tuple for return value<commit_after>#!/usr/bin/python

import sys
import subprocess
import os
import re

def main():
    check_inputs()
    path = get_path()
    files = get_files(path)
    for file in files :
        file_to_test = TestFile(file)
        file_to_test.run_tests()

def check_inputs():
    if len(sys.argv) != 2:
        print 'Usage: run_all_inputs.py <path_to_Input_folder>'
        sys.exit(1)

def get_path():
    path = sys.argv[1]
    return path

def get_files(path):
    full_paths=[]
    for root, dirs, files in os.walk(path, followlinks=True):
        if '.git' in dirs:
            dirs.remove('.git')
        for name in files:
            if re.search("test.*\.xml",name):
                full_paths.append(os.path.join(root, name))
            else :
                files.remove(name)
    print "The files to be tested are:"
    print full_paths
    return full_paths

class TestFile():
    """An object representing the inputxml file to test"""
    def __init__(self, file_path):
        self.name = file_path # strip off front bit

    def run_tests(self):
        """Runs all of the input file tests"""
        output = self.get_output()
        self.test_no_errors(output)
        self.test_expected(output)

    def get_output(self):
        """Returns the output from running the FileTest"""
        flags = " -v9"
        try :
            p = subprocess.Popen("./cyclus "+self.name+flags,
                    shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            io_tuple = p.communicate()
            output = io_tuple[1]
        except subprocess.CalledProcessError, e:
            print(e)
        return output

    def test_no_errors(self, output):
        """returns true if there were no errors or segfaults running this TestFile"""
        to_ret = True
        print "Test " + self.name
        if re.search("ERROR",output) or re.search("Segmentation fault",output):
            to_ret = False
            print " resulted in errors: "
            print output
        else :
            print " passed. "
        return to_ret

    def test_expected(self, output):
        """This function is currently a placeholder. It is intended to print the
        difference between the current output and the output gathered the last
        time the test was run"""
        return True

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


<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 OpenStack LLC.
# All Rights Reserved.
#
#    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.

from sqlalchemy import MetaData

meta = MetaData()

def upgrade(migrate_engine):
    meta.bind = migrate_engine

    # NOTE (ironcamel): The only table we are not converting to utf8 here is
    # dns_domains. This table has a primary key that is 512 characters wide.
    # When the mysql engine attempts to convert it to utf8, it complains about
    # not supporting key columns larger than 1000.

    if migrate_engine.name == "mysql":
        # The instances table has to be converted early on. Also, the
        # foreign_key_checks has to be disabled inside of the execute command
        # that converts the instances table.
        migrate_engine.execute("SET foreign_key_checks = 0;"
            "ALTER TABLE instances CONVERT TO CHARACTER SET utf8")
        tables = ["agent_builds", "aggregate_hosts", "aggregate_metadata",
            "aggregates", "auth_tokens", "block_device_mapping",
            "bw_usage_cache", "certificates", "compute_nodes", "console_pools",
            "consoles", "fixed_ips", "floating_ips", "instance_actions",
            "instance_faults", "instance_info_caches", "instance_metadata",
            "instance_type_extra_specs", "instance_types", "iscsi_targets",
            "key_pairs", "migrate_version", "migrations", "networks",
            "projects", "provider_fw_rules", "quotas", "s3_images",
            "security_group_instance_association", "security_group_rules",
            "security_groups", "services", "sm_backend_config", "sm_flavors",
            "sm_volume", "snapshots", "snapshots", "user_project_association",
            "user_project_role_association", "user_role_association", "users",
            "virtual_interfaces", "virtual_storage_arrays", "volume_metadata",
            "volumes", "volume_type_extra_specs", "volume_types", "zones"]
        for table in tables:
            migrate_engine.execute(
                "ALTER TABLE %s CONVERT TO CHARACTER SET utf8" % table)
        migrate_engine.execute("SET foreign_key_checks = 1")
        migrate_engine.execute(
            "ALTER DATABASE nova DEFAULT CHARACTER SET utf8")

def downgrade(migrate_engine):
    # utf8 tables should be backwards compatible, so lets leave it alone
    pass
<commit_msg>077_convert_to_utf8: Convert *all* FK tables early<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 OpenStack LLC.
# All Rights Reserved.
#
#    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.

from sqlalchemy import MetaData

meta = MetaData()

def upgrade(migrate_engine):
    meta.bind = migrate_engine

    # NOTE (ironcamel): The only table we are not converting to utf8 here is
    # dns_domains. This table has a primary key that is 512 characters wide.
    # When the mysql engine attempts to convert it to utf8, it complains about
    # not supporting key columns larger than 1000.

    if migrate_engine.name == "mysql":
        tables = [
            # tables that are FK parents, must be converted early
            "aggregates", "console_pools", "instance_types", "instances",
            "projects", "security_groups", "sm_backend_config", "sm_flavors",
            "snapshots", "user_project_association", "users", "volume_types",
            "volumes",
            # those that are children and others later
            "agent_builds", "aggregate_hosts", "aggregate_metadata",
            "auth_tokens", "block_device_mapping", "bw_usage_cache",
            "certificates", "compute_nodes", "consoles", "fixed_ips",
            "floating_ips", "instance_actions", "instance_faults",
            "instance_info_caches", "instance_metadata",
            "instance_type_extra_specs", "iscsi_targets", "key_pairs",
            "migrate_version", "migrations", "networks", "provider_fw_rules",
            "quotas", "s3_images", "security_group_instance_association",
            "security_group_rules", "services", "sm_volume",
            "user_project_role_association", "user_role_association",
            "virtual_interfaces", "virtual_storage_arrays", "volume_metadata",
            "volume_type_extra_specs", "zones"]
        sql = "SET foreign_key_checks = 0;"
        for table in tables:
            sql += "ALTER TABLE %s CONVERT TO CHARACTER SET utf8;" % table
        sql += "SET foreign_key_checks = 1;"
        sql += "ALTER DATABASE %s DEFAULT CHARACTER SET utf8;" \
            % migrate_engine.url.database
        migrate_engine.execute(sql)

def downgrade(migrate_engine):
    # utf8 tables should be backwards compatible, so lets leave it alone
    pass
<|endoftext|>


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

# Copyright(C) 2010  Romain Bignon, Florent Fourcot
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

from .base import IBaseCap, CapBaseObject, StringField, FloatField, DateField

__all__ = ['Gauge', 'GaugeMeasure', 'ICapWaterLevel']

class Gauge(CapBaseObject):
    """
    Gauge class.
    """
    name =      StringField('Name of gauge')
    river =     StringField('What river')
    level =     FloatField('Level of gauge')
    flow =      FloatField('Flow of gauge')
    lastdate =  DateField('Last measure')
    forecast =  StringField('Forecast')

class GaugeMeasure(CapBaseObject):
    """
    Measure of a gauge.
    """
    level =     FloatField('Level of measure')
    flow =      FloatField('Flow of measure')
    date =      DateField('Date of measure')

    def __init__(self):
        CapBaseObject.__init__(self, None)

class ICapWaterLevel(IBaseCap):
    def iter_gauge_history(self, id):
        """
        Get history of a gauge.

        :param id: ID of the river
        :type id: str
        :rtype: iter[:class:`GaugeMeasure`]
        """
        raise NotImplementedError()

    def get_last_measure(self, id):
        """
        Get last measure of the gauge.

        :param id: ID of the gauge
        :type id: str
        :rtype: :class:`GaugeMeasure`
        """
        raise NotImplementedError()

    def iter_gauges(self, pattern=None):
        """
        Iter gauges.

        :param pattern: if specified, used to search gauges
        :type pattern: str
        :rtype: iter[:class:`Gauge`]
        """
        raise NotImplementedError()
<commit_msg>fix copyright<commit_after># -*- coding: utf-8 -*-

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

from .base import IBaseCap, CapBaseObject, StringField, FloatField, DateField

__all__ = ['Gauge', 'GaugeMeasure', 'ICapWaterLevel']

class Gauge(CapBaseObject):
    """
    Gauge class.
    """
    name =      StringField('Name of gauge')
    river =     StringField('What river')
    level =     FloatField('Level of gauge')
    flow =      FloatField('Flow of gauge')
    lastdate =  DateField('Last measure')
    forecast =  StringField('Forecast')

class GaugeMeasure(CapBaseObject):
    """
    Measure of a gauge.
    """
    level =     FloatField('Level of measure')
    flow =      FloatField('Flow of measure')
    date =      DateField('Date of measure')

    def __init__(self):
        CapBaseObject.__init__(self, None)

class ICapWaterLevel(IBaseCap):
    def iter_gauge_history(self, id):
        """
        Get history of a gauge.

        :param id: ID of the river
        :type id: str
        :rtype: iter[:class:`GaugeMeasure`]
        """
        raise NotImplementedError()

    def get_last_measure(self, id):
        """
        Get last measure of the gauge.

        :param id: ID of the gauge
        :type id: str
        :rtype: :class:`GaugeMeasure`
        """
        raise NotImplementedError()

    def iter_gauges(self, pattern=None):
        """
        Iter gauges.

        :param pattern: if specified, used to search gauges
        :type pattern: str
        :rtype: iter[:class:`Gauge`]
        """
        raise NotImplementedError()
<|endoftext|>


<commit_before>import time
import datetime
import RPi.GPIO           as     GPIO
from IBMConnector         import IBMConnector
from Dallas               import Dallas
from DHT                  import DHT
from SystemData           import SystemData
from Weather              import Weather
from CSVPersistor         import CSVPersistor
from TimedDigitalActuator import TimedDigitalActuator
from Hatch                import Hatch
from Picture              import Picture
from Stepper              import Stepper

def commandCallback(cmd):

        print("Command received: %s with data: %s" % (cmd.command,cmd.data))

        if alloff:
            return

        if cmd.command == "InsideFan":
            insideFan.setTime(cmd.data)

        elif cmd.command == "OutsideFan":
            outsideFan.setTime(cmd.data)

        elif cmd.command == "Humidifier":
            humidifier.setTime(cmd.data)

        elif cmd.command == "Hatch":
            if cmd.data >= 0 and cmd.data <= 1:
                hatch.setHatch(cmd.data)

        elif cmd.command == "Stepper":
            stepper.setTime(cmd.data)

        elif cmd.command == "Picture":
            picture.makePicture()

        else:
            print "Unknown command"
            print(cmd.command)

if __name__ == '__main__':
    print "MS HAL start"

    #Connectors
    iotfClient       = IBMConnector(commandCallback)
    time.sleep(2)
    csvPersistor     = CSVPersistor("Plant1")
    time.sleep(1)

    #Sensors
    waterTemperature = Dallas()
    time.sleep(1)
    airInside        = DHT(23)
    time.sleep(1)
    airOutside       = DHT(24)
    time.sleep(1)
    systemData       = SystemData()
    time.sleep(1)
    weather          = Weather()
    time.sleep(1)

    #Actuators
    outsideFan = TimedDigitalActuator(20)
    time.sleep(1)
    insideFan  = TimedDigitalActuator(21)
    time.sleep(1)
    humidifier = TimedDigitalActuator(16)
    time.sleep(1)
    hatch = Hatch()
    time.sleep(1)
    stepper = Stepper()
    time.sleep(1)

    #picture
    picture = Picture("Plant1")

    #silencer
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    timeToSilence = 0
    alloff = False

    while True:

        if not GPIO.input(12):
            print "Silence"
            timeToSilence = time.time() + 60 * 60

        if timeToSilence > time.time():
            print "REMAINE SILENCE"
            hatch.setHatch(1)
            insideFan.setTime(0)
            outsideFan.setTime(0)
            humidifier.setTime(0)
            stepper.setTime(0)
            alloff = True
        else:
            alloff = False

        now = datetime.datetime.now()
        m = {}
        m['Timestamp']               = "%d-%d-%d-%d-%d-%d" % (now.year, now.month, now.day, now.hour, now.minute, now.second)
        m['Watertemperature']        = waterTemperature.getWaterTemp()
        m['InsideHumidity']          = airInside.getHumidity()
        m['InsideTemperature']       = airInside.getTemperature()
        m['OutsideHumidity']         = airOutside.getHumidity()
        m['OutsideTemperature']      = airOutside.getTemperature()
        m['CPUTemperature']          = systemData.getCPUTemp()
        m['GPUTemperature']          = systemData.getGPUTemp()
        m['CPUUsage']                = systemData.getCPUuse()
        m['Loadlevel']               = systemData.getLoadLevel()
        m['WeatherHumidity']         = weather.getHumidity()
        m['WeatherPressure']         = weather.getPressure()
        m['WeatherPressureTrent']    = weather.getPressureTrent()
        m['WeatherUV']               = weather.getUV()
        m['WeatherPreciptionTotal']  = weather.getPrecipTotal()
        m['WeatherPreciptionHourly'] = weather.getPrecipHrly()
        m['OutsideFan']              = outsideFan.getState()
        m['InsideFan']               = insideFan.getState()
        m['Humidifier']              = humidifier.getState()
        m['Hatch']                   = hatch.getHatch()
        m['Stepper']                 = stepper.getState()
        m['StepperPosition']         = stepper.getCounter()
        m['AllOff']                  = alloff
        iotfClient.pushDataToIBM(m)
        csvPersistor.persist(m)
        time.sleep(1)
<commit_msg>Adding debug<commit_after>import time
import datetime
import RPi.GPIO           as     GPIO
from IBMConnector         import IBMConnector
from Dallas               import Dallas
from DHT                  import DHT
from SystemData           import SystemData
from Weather              import Weather
from CSVPersistor         import CSVPersistor
from TimedDigitalActuator import TimedDigitalActuator
from Hatch                import Hatch
from Picture              import Picture
from Stepper              import Stepper

def commandCallback(cmd):

        print("Command received: %s with data: %s" % (cmd.command, cmd.data.d.value))

        if alloff:
            return

        if cmd.command == "InsideFan":
            insideFan.setTime(cmd.data.d.value)

        elif cmd.command == "OutsideFan":
            outsideFan.setTime(cmd.data.d.value)

        elif cmd.command == "Humidifier":
            humidifier.setTime(cmd.data.d.value)

        elif cmd.command == "Hatch":
            if cmd.data >= 0 and cmd.data <= 1:
                hatch.setHatch(cmd.data.d.value)

        elif cmd.command == "Stepper":
            stepper.setTime(cmd.data.d.value)

        elif cmd.command == "Picture":
            picture.makePicture()

        else:
            print "Unknown command"
            print(cmd.command)

if __name__ == '__main__':
    print "MS HAL start"

    #Connectors
    iotfClient       = IBMConnector(commandCallback)
    time.sleep(2)
    csvPersistor     = CSVPersistor("Plant1")
    time.sleep(1)

    #Sensors
    waterTemperature = Dallas()
    time.sleep(1)
    airInside        = DHT(23)
    time.sleep(1)
    airOutside       = DHT(24)
    time.sleep(1)
    systemData       = SystemData()
    time.sleep(1)
    weather          = Weather()
    time.sleep(1)

    #Actuators
    outsideFan = TimedDigitalActuator(20)
    time.sleep(1)
    insideFan  = TimedDigitalActuator(21)
    time.sleep(1)
    humidifier = TimedDigitalActuator(16)
    time.sleep(1)
    hatch = Hatch()
    time.sleep(1)
    stepper = Stepper()
    time.sleep(1)

    #picture
    picture = Picture("Plant1")

    #silencer
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    timeToSilence = 0
    alloff = False

    while True:

        if not GPIO.input(12):
            print "Silence"
            timeToSilence = time.time() + 60 * 60

        if timeToSilence > time.time():
            print "REMAINE SILENCE"
            hatch.setHatch(1)
            insideFan.setTime(0)
            outsideFan.setTime(0)
            humidifier.setTime(0)
            stepper.setTime(0)
            alloff = True
        else:
            alloff = False

        now = datetime.datetime.now()
        m = {}
        m['Timestamp']               = "%d-%d-%d-%d-%d-%d" % (now.year, now.month, now.day, now.hour, now.minute, now.second)
        m['Watertemperature']        = waterTemperature.getWaterTemp()
        m['InsideHumidity']          = airInside.getHumidity()
        m['InsideTemperature']       = airInside.getTemperature()
        m['OutsideHumidity']         = airOutside.getHumidity()
        m['OutsideTemperature']      = airOutside.getTemperature()
        m['CPUTemperature']          = systemData.getCPUTemp()
        m['GPUTemperature']          = systemData.getGPUTemp()
        m['CPUUsage']                = systemData.getCPUuse()
        m['Loadlevel']               = systemData.getLoadLevel()
        m['WeatherHumidity']         = weather.getHumidity()
        m['WeatherPressure']         = weather.getPressure()
        m['WeatherPressureTrent']    = weather.getPressureTrent()
        m['WeatherUV']               = weather.getUV()
        m['WeatherPreciptionTotal']  = weather.getPrecipTotal()
        m['WeatherPreciptionHourly'] = weather.getPrecipHrly()
        m['OutsideFan']              = outsideFan.getState()
        m['InsideFan']               = insideFan.getState()
        m['Humidifier']              = humidifier.getState()
        m['Hatch']                   = hatch.getHatch()
        m['Stepper']                 = stepper.getState()
        m['StepperPosition']         = stepper.getCounter()
        m['AllOff']                  = alloff
        iotfClient.pushDataToIBM(m)
        csvPersistor.persist(m)
        time.sleep(1)
<|endoftext|>


<commit_before>import csv

from django.contrib import admin
from django.http import HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib.admin.sites import NotRegistered

from daterange_filter.filter import DateRangeFilter
from wagtailmodeladmin.options import ModelAdmin as WagtailModelAdmin

from molo.profiles.admin_views import FrontendUsersAdminView

try:
    admin.site.unregister(User)
except NotRegistered:
    pass

def download_as_csv(ProfileUserAdmin, request, queryset):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;filename=export.csv'
    writer = csv.writer(response)
    user_model_fields = UserAdmin.list_display + ('date_joined', )
    profile_fields = ('alias', 'mobile_number')
    field_names = user_model_fields + profile_fields
    writer.writerow(field_names)
    for obj in queryset:
        if obj.profile.alias:
            obj.profile.alias = obj.profile.alias.encode('utf-8')
        obj.username = obj.username.encode('utf-8')
        obj.date_joined = obj.date_joined.strftime("%Y-%m-%d %H:%M")
        writer.writerow(
            [getattr(obj, field) for field in user_model_fields] +
            [getattr(obj.profile, field) for field in profile_fields])
    return response

download_as_csv.short_description = "Download selected as csv"

@admin.register(User)
class ProfileUserAdmin(UserAdmin):
    list_display = UserAdmin.list_display + (
        'date_joined', '_alias', '_mobile_number', '_date_of_birth')

    list_filter = UserAdmin.list_filter + ('date_joined', )

    actions = [download_as_csv]

    def _alias(self, obj, *args, **kwargs):
        if hasattr(obj, 'profile') and obj.profile.alias:
            return obj.profile.alias
        return ''

    def _mobile_number(self, obj, *args, **kwargs):
        if hasattr(obj, 'profile') and obj.profile.mobile_number:
            return obj.profile.mobile_number
        return ''

    def _date_of_birth(self, obj, *args, **kwargs):
        if hasattr(obj, 'profile') and obj.profile.date_of_birth:
            return obj.profile.date_of_birth
        return ''

# Below here is for Wagtail Admin
class FrontendUsersDateRangeFilter(DateRangeFilter):
    template = 'admin/frontend_users_date_range_filter.html'

class FrontendUsersModelAdmin(WagtailModelAdmin, ProfileUserAdmin):
    model = User
    menu_label = 'End Users'
    menu_icon = 'user'
    menu_order = 600
    index_view_class = FrontendUsersAdminView
    add_to_settings_menu = True
    list_display = ('username', '_alias', '_mobile_number', '_date_of_birth',
                    'email', 'date_joined', 'is_active')

    list_filter = (('date_joined', FrontendUsersDateRangeFilter), 'is_active')

    search_fields = ('username',)

    def get_queryset(self, request):
        queryset = User.objects.filter(is_staff=False)
        return queryset
<commit_msg>Adjust filter for End Users to exclude all Admin Users and Users that belong to any group<commit_after>import csv

from django.contrib import admin
from django.http import HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from django.contrib.admin.sites import NotRegistered

from daterange_filter.filter import DateRangeFilter
from wagtailmodeladmin.options import ModelAdmin as WagtailModelAdmin

from molo.profiles.admin_views import FrontendUsersAdminView

try:
    admin.site.unregister(User)
except NotRegistered:
    pass

def download_as_csv(ProfileUserAdmin, request, queryset):
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment;filename=export.csv'
    writer = csv.writer(response)
    user_model_fields = UserAdmin.list_display + ('date_joined', )
    profile_fields = ('alias', 'mobile_number')
    field_names = user_model_fields + profile_fields
    writer.writerow(field_names)
    for obj in queryset:
        if obj.profile.alias:
            obj.profile.alias = obj.profile.alias.encode('utf-8')
        obj.username = obj.username.encode('utf-8')
        obj.date_joined = obj.date_joined.strftime("%Y-%m-%d %H:%M")
        writer.writerow(
            [getattr(obj, field) for field in user_model_fields] +
            [getattr(obj.profile, field) for field in profile_fields])
    return response

download_as_csv.short_description = "Download selected as csv"

@admin.register(User)
class ProfileUserAdmin(UserAdmin):
    list_display = UserAdmin.list_display + (
        'date_joined', '_alias', '_mobile_number', '_date_of_birth')

    list_filter = UserAdmin.list_filter + ('date_joined', )

    actions = [download_as_csv]

    def _alias(self, obj, *args, **kwargs):
        if hasattr(obj, 'profile') and obj.profile.alias:
            return obj.profile.alias
        return ''

    def _mobile_number(self, obj, *args, **kwargs):
        if hasattr(obj, 'profile') and obj.profile.mobile_number:
            return obj.profile.mobile_number
        return ''

    def _date_of_birth(self, obj, *args, **kwargs):
        if hasattr(obj, 'profile') and obj.profile.date_of_birth:
            return obj.profile.date_of_birth
        return ''

# Below here is for Wagtail Admin
class FrontendUsersDateRangeFilter(DateRangeFilter):
    template = 'admin/frontend_users_date_range_filter.html'

class FrontendUsersModelAdmin(WagtailModelAdmin, ProfileUserAdmin):
    model = User
    menu_label = 'End Users'
    menu_icon = 'user'
    menu_order = 600
    index_view_class = FrontendUsersAdminView
    add_to_settings_menu = True
    list_display = ('username', '_alias', '_mobile_number', '_date_of_birth',
                    'email', 'date_joined', 'is_active')

    list_filter = (('date_joined', FrontendUsersDateRangeFilter), 'is_active')

    search_fields = ('username',)

    def get_queryset(self, request):
        queryset = User.objects.filter(is_staff=False, groups__isnull=True)
        return queryset
<|endoftext|>


<commit_before>from __future__ import unicode_literals, print_function
import redis
from rq import Connection, Queue, Worker
from rq.logutils import setup_loghandlers
from frappe.utils import cstr
from collections import defaultdict
import frappe
import os, socket, time
from frappe import _
from six import string_types

# imports - third-party imports

default_timeout = 300
queue_timeout = {
	'background': 2500,
	'long': 1500,
	'default': 300,
	'short': 300
}

redis_connection = None

def enqueue(method, queue='default', timeout=None, event=None,
	is_async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs):
	'''
		Enqueue method to be executed using a background worker

		:param method: method string or method object
		:param queue: should be either long, default or short
		:param timeout: should be set according to the functions
		:param event: this is passed to enable clearing of jobs from queues
		:param is_async: if is_async=False, the method is executed immediately, else via a worker
		:param job_name: can be used to name an enqueue call, which can be used to prevent duplicate calls
		:param now: if now=True, the method is executed via frappe.call
		:param kwargs: keyword arguments to be passed to the method
	'''
	# To handle older implementations
	is_async = kwargs.pop('async', is_async)

	if now or frappe.flags.in_migrate:
		return frappe.call(method, **kwargs)

	q = get_queue(queue, is_async=is_async)
	if not timeout:
		timeout = queue_timeout.get(queue) or 300
	queue_args = {
		"site": frappe.local.site,
		"user": frappe.session.user,
		"method": method,
		"event": event,
		"job_name": job_name or cstr(method),
		"is_async": is_async,
		"kwargs": kwargs
	}
	if enqueue_after_commit:
		if not frappe.flags.enqueue_after_commit:
			frappe.flags.enqueue_after_commit = []

		frappe.flags.enqueue_after_commit.append({
			"queue": queue,
			"is_async": is_async,
			"timeout": timeout,
			"queue_args":queue_args
		})
		return frappe.flags.enqueue_after_commit
	else:
		return q.enqueue_call(execute_job, timeout=timeout,
			kwargs=queue_args)

def enqueue_doc(doctype, name=None, method=None, queue='default', timeout=300,
	now=False, **kwargs):
	'''Enqueue a method to be run on a document'''
	enqueue('frappe.utils.background_jobs.run_doc_method', doctype=doctype, name=name,
		doc_method=method, queue=queue, timeout=timeout, now=now, **kwargs)

def run_doc_method(doctype, name, doc_method, **kwargs):
	getattr(frappe.get_doc(doctype, name), doc_method)(**kwargs)

def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True, retry=0):
	'''Executes job in a worker, performs commit/rollback and logs if there is any error'''
	from frappe.utils.scheduler import log

	if is_async:
		frappe.connect(site)
		if os.environ.get('CI'):
			frappe.flags.in_test = True

		if user:
			frappe.set_user(user)

	if isinstance(method, string_types):
		method_name = method
		method = frappe.get_attr(method)
	else:
		method_name = cstr(method.__name__)

	try:
		method(**kwargs)

	except (frappe.db.InternalError, frappe.RetryBackgroundJobError) as e:
		frappe.db.rollback()

		if (retry < 5 and
			(isinstance(e, frappe.RetryBackgroundJobError) or
				(frappe.db.is_deadlocked(e) or frappe.db.is_timedout(e)))):
			# retry the job if
			# 1213 = deadlock
			# 1205 = lock wait timeout
			# or RetryBackgroundJobError is explicitly raised
			frappe.destroy()
			time.sleep(retry+1)

			return execute_job(site, method, event, job_name, kwargs,
				is_async=is_async, retry=retry+1)

		else:
			log(method_name, message=repr(locals()))
			raise

	except:
		frappe.db.rollback()
		log(method_name, message=repr(locals()))
		raise

	else:
		frappe.db.commit()

	finally:
		if is_async:
			frappe.destroy()

def start_worker(queue=None, quiet = False):
	'''Wrapper to start rq worker. Connects to redis and monitors these queues.'''
	with frappe.init_site():
		# empty init is required to get redis_queue from common_site_config.json
		redis_connection = get_redis_conn()

	if os.environ.get('CI'):
		setup_loghandlers('ERROR')

	with Connection(redis_connection):
		queues = get_queue_list(queue)
		logging_level = "INFO"
		if quiet:
			logging_level = "WARNING"
		Worker(queues, name=get_worker_name(queue)).work(logging_level = logging_level)

def get_worker_name(queue):
	'''When limiting worker to a specific queue, also append queue name to default worker name'''
	name = None

	if queue:
		# hostname.pid is the default worker name
		name = '{hostname}.{pid}.{queue}'.format(
			hostname=socket.gethostname(),
			pid=os.getpid(),
			queue=queue)

	return name

def get_jobs(site=None, queue=None, key='method'):
	'''Gets jobs per queue or per site or both'''
	jobs_per_site = defaultdict(list)
	for queue in get_queue_list(queue):
		q = get_queue(queue)

		for job in q.jobs:
			if job.kwargs.get('site'):
				if site is None:
					# get jobs for all sites
					jobs_per_site[job.kwargs['site']].append(job.kwargs[key])

				elif job.kwargs['site'] == site:
					# get jobs only for given site
					jobs_per_site[site].append(job.kwargs[key])

			else:
				print('No site found in job', job.__dict__)

	return jobs_per_site

def get_queue_list(queue_list=None):
	'''Defines possible queues. Also wraps a given queue in a list after validating.'''
	default_queue_list = list(queue_timeout)
	if queue_list:
		if isinstance(queue_list, string_types):
			queue_list = [queue_list]

		for queue in queue_list:
			validate_queue(queue, default_queue_list)

		return queue_list

	else:
		return default_queue_list

def get_queue(queue, is_async=True):
	'''Returns a Queue object tied to a redis connection'''
	validate_queue(queue)

	kwargs = {
		'connection': get_redis_conn(),
		'async': is_async
	}

	return Queue(queue, **kwargs)

def validate_queue(queue, default_queue_list=None):
	if not default_queue_list:
		default_queue_list = list(queue_timeout)

	if queue not in default_queue_list:
		frappe.throw(_("Queue should be one of {0}").format(', '.join(default_queue_list)))

def get_redis_conn():
	if not hasattr(frappe.local, 'conf'):
		raise Exception('You need to call frappe.init')

	elif not frappe.local.conf.redis_queue:
		raise Exception('redis_queue missing in common_site_config.json')

	global redis_connection

	if not redis_connection:
		redis_connection = redis.from_url(frappe.local.conf.redis_queue)

	return redis_connection

def enqueue_test_job():
	enqueue('frappe.utils.background_jobs.test_job', s=100)

def test_job(s):
	import time
	print('sleeping...')
	time.sleep(s)
<commit_msg>fix(rq): randomize worker name with uuid<commit_after>from __future__ import unicode_literals, print_function
import redis
from rq import Connection, Queue, Worker
from rq.logutils import setup_loghandlers
from frappe.utils import cstr
from collections import defaultdict
import frappe
import os, socket, time
from frappe import _
from six import string_types
from uuid import uuid4

# imports - third-party imports

default_timeout = 300
queue_timeout = {
	'background': 2500,
	'long': 1500,
	'default': 300,
	'short': 300
}

redis_connection = None

def enqueue(method, queue='default', timeout=None, event=None,
	is_async=True, job_name=None, now=False, enqueue_after_commit=False, **kwargs):
	'''
		Enqueue method to be executed using a background worker

		:param method: method string or method object
		:param queue: should be either long, default or short
		:param timeout: should be set according to the functions
		:param event: this is passed to enable clearing of jobs from queues
		:param is_async: if is_async=False, the method is executed immediately, else via a worker
		:param job_name: can be used to name an enqueue call, which can be used to prevent duplicate calls
		:param now: if now=True, the method is executed via frappe.call
		:param kwargs: keyword arguments to be passed to the method
	'''
	# To handle older implementations
	is_async = kwargs.pop('async', is_async)

	if now or frappe.flags.in_migrate:
		return frappe.call(method, **kwargs)

	q = get_queue(queue, is_async=is_async)
	if not timeout:
		timeout = queue_timeout.get(queue) or 300
	queue_args = {
		"site": frappe.local.site,
		"user": frappe.session.user,
		"method": method,
		"event": event,
		"job_name": job_name or cstr(method),
		"is_async": is_async,
		"kwargs": kwargs
	}
	if enqueue_after_commit:
		if not frappe.flags.enqueue_after_commit:
			frappe.flags.enqueue_after_commit = []

		frappe.flags.enqueue_after_commit.append({
			"queue": queue,
			"is_async": is_async,
			"timeout": timeout,
			"queue_args":queue_args
		})
		return frappe.flags.enqueue_after_commit
	else:
		return q.enqueue_call(execute_job, timeout=timeout,
			kwargs=queue_args)

def enqueue_doc(doctype, name=None, method=None, queue='default', timeout=300,
	now=False, **kwargs):
	'''Enqueue a method to be run on a document'''
	enqueue('frappe.utils.background_jobs.run_doc_method', doctype=doctype, name=name,
		doc_method=method, queue=queue, timeout=timeout, now=now, **kwargs)

def run_doc_method(doctype, name, doc_method, **kwargs):
	getattr(frappe.get_doc(doctype, name), doc_method)(**kwargs)

def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True, retry=0):
	'''Executes job in a worker, performs commit/rollback and logs if there is any error'''
	from frappe.utils.scheduler import log

	if is_async:
		frappe.connect(site)
		if os.environ.get('CI'):
			frappe.flags.in_test = True

		if user:
			frappe.set_user(user)

	if isinstance(method, string_types):
		method_name = method
		method = frappe.get_attr(method)
	else:
		method_name = cstr(method.__name__)

	try:
		method(**kwargs)

	except (frappe.db.InternalError, frappe.RetryBackgroundJobError) as e:
		frappe.db.rollback()

		if (retry < 5 and
			(isinstance(e, frappe.RetryBackgroundJobError) or
				(frappe.db.is_deadlocked(e) or frappe.db.is_timedout(e)))):
			# retry the job if
			# 1213 = deadlock
			# 1205 = lock wait timeout
			# or RetryBackgroundJobError is explicitly raised
			frappe.destroy()
			time.sleep(retry+1)

			return execute_job(site, method, event, job_name, kwargs,
				is_async=is_async, retry=retry+1)

		else:
			log(method_name, message=repr(locals()))
			raise

	except:
		frappe.db.rollback()
		log(method_name, message=repr(locals()))
		raise

	else:
		frappe.db.commit()

	finally:
		if is_async:
			frappe.destroy()

def start_worker(queue=None, quiet = False):
	'''Wrapper to start rq worker. Connects to redis and monitors these queues.'''
	with frappe.init_site():
		# empty init is required to get redis_queue from common_site_config.json
		redis_connection = get_redis_conn()

	if os.environ.get('CI'):
		setup_loghandlers('ERROR')

	with Connection(redis_connection):
		queues = get_queue_list(queue)
		logging_level = "INFO"
		if quiet:
			logging_level = "WARNING"
		Worker(queues, name=get_worker_name(queue)).work(logging_level = logging_level)

def get_worker_name(queue):
	'''When limiting worker to a specific queue, also append queue name to default worker name'''
	name = None

	if queue:
		# hostname.pid is the default worker name
		name = '{uuid}.{hostname}.{pid}.{queue}'.format(
			uuid=uuid4().hex,
			hostname=socket.gethostname(),
			pid=os.getpid(),
			queue=queue)

	return name

def get_jobs(site=None, queue=None, key='method'):
	'''Gets jobs per queue or per site or both'''
	jobs_per_site = defaultdict(list)
	for queue in get_queue_list(queue):
		q = get_queue(queue)

		for job in q.jobs:
			if job.kwargs.get('site'):
				if site is None:
					# get jobs for all sites
					jobs_per_site[job.kwargs['site']].append(job.kwargs[key])

				elif job.kwargs['site'] == site:
					# get jobs only for given site
					jobs_per_site[site].append(job.kwargs[key])

			else:
				print('No site found in job', job.__dict__)

	return jobs_per_site

def get_queue_list(queue_list=None):
	'''Defines possible queues. Also wraps a given queue in a list after validating.'''
	default_queue_list = list(queue_timeout)
	if queue_list:
		if isinstance(queue_list, string_types):
			queue_list = [queue_list]

		for queue in queue_list:
			validate_queue(queue, default_queue_list)

		return queue_list

	else:
		return default_queue_list

def get_queue(queue, is_async=True):
	'''Returns a Queue object tied to a redis connection'''
	validate_queue(queue)

	kwargs = {
		'connection': get_redis_conn(),
		'async': is_async
	}

	return Queue(queue, **kwargs)

def validate_queue(queue, default_queue_list=None):
	if not default_queue_list:
		default_queue_list = list(queue_timeout)

	if queue not in default_queue_list:
		frappe.throw(_("Queue should be one of {0}").format(', '.join(default_queue_list)))

def get_redis_conn():
	if not hasattr(frappe.local, 'conf'):
		raise Exception('You need to call frappe.init')

	elif not frappe.local.conf.redis_queue:
		raise Exception('redis_queue missing in common_site_config.json')

	global redis_connection

	if not redis_connection:
		redis_connection = redis.from_url(frappe.local.conf.redis_queue)

	return redis_connection

def enqueue_test_job():
	enqueue('frappe.utils.background_jobs.test_job', s=100)

def test_job(s):
	import time
	print('sleeping...')
	time.sleep(s)
<|endoftext|>


<commit_before>#!/usr/bin/env python

# (C) 2004 British Broadcasting Corporation and Kamaelia Contributors(1)
#     All Rights Reserved.
#
# You may only modify and redistribute this under the terms of any of the
# following licenses(2): Mozilla Public License, V1.1, GNU General
# Public License, V2.0, GNU Lesser General Public License, V2.1
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://kamaelia.sourceforge.net/AUTHORS - please extend this file,
#     not this notice.
# (2) Reproduced in the COPYING file, and at:
#     http://kamaelia.sourceforge.net/COPYING
# Under section 3.5 of the MPL, we are using this text since we deem the MPL
# notice inappropriate for this file. As per MPL/GPL/LGPL removal of this
# notice is prohibited.
#
# Please contact us via: kamaelia-list-owner@lists.sourceforge.net
# to discuss alternative licensing.
# -------------------------------------------------------------------------

"""\
=============================
Simple line-of-text tokeniser
=============================

This component takes a line of text and splits it into space character
separated tokens. Tokens can be encapsulated with single or double quote marks,
allowing spaces to appear within a token.

Example Usage
-------------
::
    Pipeline( ConsoleReader(),
              lines_to_tokenlists(),
              ConsoleEchoer()
            ).run()

At runtime::
    >>> Hello world "how are you" 'john said "hi"' "i replied \"hi\"" "c:\\windows" end
    [ 'Hello',
      'world',
      'how are you',
      'john said "hi"',
      'i replied "hi"',
      'c:\windows',
      'end' ]

How does it work?
-----------------

lines_to_tokenlists receives individual lines of text on its "inbox" inbox. A
line is converted to a list of tokens, which is sent out of its "outbox"
outbox.

Space characters are treated as the token separator, however a token can be
encapsulated in single or double quotes allowing space characters to appear
within it.

If you need to use a quote mark or backslash within a token encapsulated by
quote marks, it must be escaped by prefixing it with a backslash. Only do
this if the token is encapsulated.

encapsulating quote marks are removed when the line is tokenised. Escaped
backslashes and quote marks are converted to plain backslashes and quote marks.

If a producerFinished() or shutdownMicroprocess() message is received on this
component's "control" inbox, then it will send it on out of its "signal" outbox
and immediately terminate. It will not flush any whole lines of text that may
still be buffered.
"""
import re

from Axon.Component import component

class lines_to_tokenlists(component):
    """\
    lines_to_tokenlists() -> new lines_to_tokenlists component.

    Takes individual lines of text and separates them into white
    space separated tokens. Tokens can be enclosed with single or
    double quote marks.
    """

    Inboxes = { "inbox" : "Individual lines of text",
                "control" : "Shutdown signalling",
              }
    Outboxes = { "outbox" : "list of tokens making up the line of text",
                 "signal" : "Shutdown signalling",
               }

    def __init__(self):
        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
        super(lines_to_tokenlists, self).__init__()

        doublequoted = r'(?:"((?:(?:\\.)|[^\\"])*)")'
        singlequoted = r"(?:'((?:(?:\\.)|[^\\'])*)')"
        unquoted     = r'([^"\'][^\s]*)'

        self.tokenpat = re.compile( r'\s*(?:' + unquoted +
                                          "|" + singlequoted +
                                          "|" + doublequoted +
                                          r')(?:\s+(.*))?$' )

    def main(self):
        """Main loop."""
        while not self.shutdown():
           while self.dataReady("inbox"):
               line = self.recv("inbox")
               tokens = self.lineToTokens(line)
               if tokens != []:
                   self.send(tokens, "outbox")
           self.pause()
           yield 1

    def lineToTokens(self, line):
        """\
        linesToTokens(line) -> list of tokens.

        Splits a line into individual white-space separated tokens.
        Tokens can be enclosed in single or double quotes to allow spaces
        to be used in them.

        Escape backslash and single or double quotes by prefixing them
        with a backslash *only* if used within an quote encapsulated string.
        """
        tokens = []    #re.split("\s+",line.strip())
        while line != None and line.strip() != "":
            match = self.tokenpat.match(line)
            if match != None:
                (uq, sq, dq, line) = match.groups()
                if uq != None:
                    tokens += [uq]
                elif sq != None:
                    tokens += [ re.sub(r'\\(.)', r'\1', sq) ]
                elif dq != None:
                    tokens += [ re.sub(r'\\(.)', r'\1', dq) ]
            else:
                return []
        return tokens

    def shutdown(self):
        """\
        Returns True if a shutdownMicroprocess or producerFinished message was received.
        """
        while self.dataReady("control"):
            msg = self.recv("control")
            if isinstance(msg, shutdownMicroprocess) or isinstance(msg, producerFinished):
                self.send(msg,"signal")
                return True
        return False

__kamaelia_components__  = ( lines_to_tokenlists, )
                                                                     <commit_msg>Bugfix - added necessary import.<commit_after>#!/usr/bin/env python

# (C) 2004 British Broadcasting Corporation and Kamaelia Contributors(1)
#     All Rights Reserved.
#
# You may only modify and redistribute this under the terms of any of the
# following licenses(2): Mozilla Public License, V1.1, GNU General
# Public License, V2.0, GNU Lesser General Public License, V2.1
#
# (1) Kamaelia Contributors are listed in the AUTHORS file and at
#     http://kamaelia.sourceforge.net/AUTHORS - please extend this file,
#     not this notice.
# (2) Reproduced in the COPYING file, and at:
#     http://kamaelia.sourceforge.net/COPYING
# Under section 3.5 of the MPL, we are using this text since we deem the MPL
# notice inappropriate for this file. As per MPL/GPL/LGPL removal of this
# notice is prohibited.
#
# Please contact us via: kamaelia-list-owner@lists.sourceforge.net
# to discuss alternative licensing.
# -------------------------------------------------------------------------

"""\
=============================
Simple line-of-text tokeniser
=============================

This component takes a line of text and splits it into space character
separated tokens. Tokens can be encapsulated with single or double quote marks,
allowing spaces to appear within a token.

Example Usage
-------------
::
    Pipeline( ConsoleReader(),
              lines_to_tokenlists(),
              ConsoleEchoer()
            ).run()

At runtime::
    >>> Hello world "how are you" 'john said "hi"' "i replied \"hi\"" "c:\\windows" end
    [ 'Hello',
      'world',
      'how are you',
      'john said "hi"',
      'i replied "hi"',
      'c:\windows',
      'end' ]

How does it work?
-----------------

lines_to_tokenlists receives individual lines of text on its "inbox" inbox. A
line is converted to a list of tokens, which is sent out of its "outbox"
outbox.

Space characters are treated as the token separator, however a token can be
encapsulated in single or double quotes allowing space characters to appear
within it.

If you need to use a quote mark or backslash within a token encapsulated by
quote marks, it must be escaped by prefixing it with a backslash. Only do
this if the token is encapsulated.

encapsulating quote marks are removed when the line is tokenised. Escaped
backslashes and quote marks are converted to plain backslashes and quote marks.

If a producerFinished() or shutdownMicroprocess() message is received on this
component's "control" inbox, then it will send it on out of its "signal" outbox
and immediately terminate. It will not flush any whole lines of text that may
still be buffered.
"""
import re

from Axon.Component import component
from Axon.Ipc import producerFinished, shutdownMicroprocess

class lines_to_tokenlists(component):
    """\
    lines_to_tokenlists() -> new lines_to_tokenlists component.

    Takes individual lines of text and separates them into white
    space separated tokens. Tokens can be enclosed with single or
    double quote marks.
    """

    Inboxes = { "inbox" : "Individual lines of text",
                "control" : "Shutdown signalling",
              }
    Outboxes = { "outbox" : "list of tokens making up the line of text",
                 "signal" : "Shutdown signalling",
               }

    def __init__(self):
        """x.__init__(...) initializes x; see x.__class__.__doc__ for signature"""
        super(lines_to_tokenlists, self).__init__()

        doublequoted = r'(?:"((?:(?:\\.)|[^\\"])*)")'
        singlequoted = r"(?:'((?:(?:\\.)|[^\\'])*)')"
        unquoted     = r'([^"\'][^\s]*)'

        self.tokenpat = re.compile( r'\s*(?:' + unquoted +
                                          "|" + singlequoted +
                                          "|" + doublequoted +
                                          r')(?:\s+(.*))?$' )

    def main(self):
        """Main loop."""
        while not self.shutdown():
           while self.dataReady("inbox"):
               line = self.recv("inbox")
               tokens = self.lineToTokens(line)
               if tokens != []:
                   self.send(tokens, "outbox")
           self.pause()
           yield 1

    def lineToTokens(self, line):
        """\
        linesToTokens(line) -> list of tokens.

        Splits a line into individual white-space separated tokens.
        Tokens can be enclosed in single or double quotes to allow spaces
        to be used in them.

        Escape backslash and single or double quotes by prefixing them
        with a backslash *only* if used within an quote encapsulated string.
        """
        tokens = []    #re.split("\s+",line.strip())
        while line != None and line.strip() != "":
            match = self.tokenpat.match(line)
            if match != None:
                (uq, sq, dq, line) = match.groups()
                if uq != None:
                    tokens += [uq]
                elif sq != None:
                    tokens += [ re.sub(r'\\(.)', r'\1', sq) ]
                elif dq != None:
                    tokens += [ re.sub(r'\\(.)', r'\1', dq) ]
            else:
                return []
        return tokens

    def shutdown(self):
        """\
        Returns True if a shutdownMicroprocess or producerFinished message was received.
        """
        while self.dataReady("control"):
            msg = self.recv("control")
            if isinstance(msg, shutdownMicroprocess) or isinstance(msg, producerFinished):
                self.send(msg,"signal")
                return True
        return False

__kamaelia_components__  = ( lines_to_tokenlists, )
<|endoftext|>


<commit_before>import asyncio
import logging

from aiohttp import web

from bottery import platform
from bottery.message import Message
from bottery.platform.telegram import TelegramAPI

logger = logging.getLogger('bottery.telegram')

class TelegramUser:
    '''
    Telegram User reference
    https://core.telegram.org/bots/api#user
    '''
    def __init__(self, sender):
        self.id = sender['id']
        self.first_name = sender['first_name']
        self.last_name = sender.get('last_name')
        self.username = sender.get('username')
        self.language = sender.get('language_code')

    def __str__(self):
        s = '{u.first_name}'
        if self.last_name:
            s += ' {u.last_name}'

        s += ' ({u.id})'

        return s.format(u=self)

class TelegramEngine(platform.BaseEngine):
    platform = 'telegram'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.api = TelegramAPI(self.token, session=self.session)

        # If no `mode` was defined at settings.py, use by default
        # polling mode. We need to test if `mode` is either `polling`
        # or `webhook`, if not, raise ImproperlyConfigured.
        if not hasattr(self, 'mode'):
            self.mode = 'polling'

    async def configure_polling(self):
        # TODO: Check API response
        await self.api.delete_webhook()
        self.tasks.append(self.polling)

    async def polling(self, last_update=None):
        payload = {}
        if last_update:
            # `offset` param prevets from getting duplicates updates
            # from Telegram API:
            # https://core.telegram.org/bots/api#getupdates
            payload['offset'] = last_update + 1

        updates = await self.api.get_updates(**payload)

        # If polling request returned at least one update, use its ID
        # to define the offset.
        if len(updates.get('result', [])):
            last_update = updates['result'][-1]['update_id']

        # Handle each new message, send its responses and then request
        # updates again.
        tasks = [self.message_handler(msg) for msg in updates['result']]
        await asyncio.gather(*tasks)
        asyncio.ensure_future(self.polling(last_update))

    async def configure_webhook(self):
        hostname = getattr(self.settings, 'HOSTNAME')
        if not hostname:
            raise Exception('Missing HOSTNAME setting')

        # TODO: Check API response
        await self.api.set_webhook(url=hostname)

        self.server.router.add_post('/', self.webhook)

    async def webhook(self, request):
        update = await request.json()
        await asyncio.gather(self.message_handler(update))
        return web.Response()

    async def configure(self):
        method_name = 'configure_{}'.format(self.mode)
        configure_mode = getattr(self, method_name, None)
        if not configure_mode:
            msg = "There's no method to configure %s mode" % self.mode
            raise Exception(msg)

        await configure_mode()

    def build_message(self, data):
        '''
        Return a Message instance according to the data received from
        Telegram API.
        https://core.telegram.org/bots/api#update
        '''
        message_data = data.get('message')

        if not message_data:
            return None

        return Message(
            id=message_data['message_id'],
            platform=self.platform,
            text=message_data['text'],
            user=TelegramUser(message_data['from']),
            timestamp=message_data['date'],
            raw=data,
        )

    async def message_handler(self, data):
        message = self.build_message(data)
        print('[%s] Message from %s' % (self.engine_name, message.user))

        # Try to find a view (best name?) to response the message
        view = self.discovery_view(message)
        if not view:
            return

        # TODO: Test if the view returned something or not
        response = await self.get_response(view, message)

        # TODO: Choose between Markdown and HTML
        # TODO: Verify response status
        await self.api.send_message(chat_id=message.user.id, text=response,
                                    parser_mode='markdown')
<commit_msg>Fix typo on Telegram parse mode<commit_after>import asyncio
import logging

from aiohttp import web

from bottery import platform
from bottery.message import Message
from bottery.platform.telegram import TelegramAPI

logger = logging.getLogger('bottery.telegram')

class TelegramUser:
    '''
    Telegram User reference
    https://core.telegram.org/bots/api#user
    '''
    def __init__(self, sender):
        self.id = sender['id']
        self.first_name = sender['first_name']
        self.last_name = sender.get('last_name')
        self.username = sender.get('username')
        self.language = sender.get('language_code')

    def __str__(self):
        s = '{u.first_name}'
        if self.last_name:
            s += ' {u.last_name}'

        s += ' ({u.id})'

        return s.format(u=self)

class TelegramEngine(platform.BaseEngine):
    platform = 'telegram'

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.api = TelegramAPI(self.token, session=self.session)

        # If no `mode` was defined at settings.py, use by default
        # polling mode. We need to test if `mode` is either `polling`
        # or `webhook`, if not, raise ImproperlyConfigured.
        if not hasattr(self, 'mode'):
            self.mode = 'polling'

    async def configure_polling(self):
        # TODO: Check API response
        await self.api.delete_webhook()
        self.tasks.append(self.polling)

    async def polling(self, last_update=None):
        payload = {}
        if last_update:
            # `offset` param prevets from getting duplicates updates
            # from Telegram API:
            # https://core.telegram.org/bots/api#getupdates
            payload['offset'] = last_update + 1

        updates = await self.api.get_updates(**payload)

        # If polling request returned at least one update, use its ID
        # to define the offset.
        if len(updates.get('result', [])):
            last_update = updates['result'][-1]['update_id']

        # Handle each new message, send its responses and then request
        # updates again.
        tasks = [self.message_handler(msg) for msg in updates['result']]
        await asyncio.gather(*tasks)
        asyncio.ensure_future(self.polling(last_update))

    async def configure_webhook(self):
        hostname = getattr(self.settings, 'HOSTNAME')
        if not hostname:
            raise Exception('Missing HOSTNAME setting')

        # TODO: Check API response
        await self.api.set_webhook(url=hostname)

        self.server.router.add_post('/', self.webhook)

    async def webhook(self, request):
        update = await request.json()
        await asyncio.gather(self.message_handler(update))
        return web.Response()

    async def configure(self):
        method_name = 'configure_{}'.format(self.mode)
        configure_mode = getattr(self, method_name, None)
        if not configure_mode:
            msg = "There's no method to configure %s mode" % self.mode
            raise Exception(msg)

        await configure_mode()

    def build_message(self, data):
        '''
        Return a Message instance according to the data received from
        Telegram API.
        https://core.telegram.org/bots/api#update
        '''
        message_data = data.get('message')

        if not message_data:
            return None

        return Message(
            id=message_data['message_id'],
            platform=self.platform,
            text=message_data['text'],
            user=TelegramUser(message_data['from']),
            timestamp=message_data['date'],
            raw=data,
        )

    async def message_handler(self, data):
        message = self.build_message(data)
        print('[%s] Message from %s' % (self.engine_name, message.user))

        # Try to find a view (best name?) to response the message
        view = self.discovery_view(message)
        if not view:
            return

        # TODO: Test if the view returned something or not
        response = await self.get_response(view, message)

        # TODO: Choose between Markdown and HTML
        # TODO: Verify response status
        await self.api.send_message(chat_id=message.user.id, text=response,
                                    parse_mode='markdown')
<|endoftext|>


<commit_before>from operator import not_
from collections import OrderedDict

from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404
from django.views.generic import ListView, DetailView
from django.views.decorators.csrf import csrf_exempt

from ci.models import Project, Commit, Build
from ci.plugins import BUILD_HOOKS
from ci.tasks import execute_build

def get_project_by_slug(slug):
    return get_object_or_404(Project, slug=slug)

@csrf_exempt
def build_hook(request, project_slug, hook_type):
    project = get_project_by_slug(project_slug)
    if hook_type not in BUILD_HOOKS:
        raise Http404
    hook = BUILD_HOOKS[hook_type](request)

    branches = {branch: project.commits.create(branch=branch)
                for branch in hook.get_changed_branches()}

    configurations = project.configurations.all()
    for branch, commit in branches.iteritems():
        nbuilds = 0
        for build_config in configurations:
            if build_config.should_build_branch(branch):
                nbuilds += 1
                build = commit.builds.create(configuration=build_config)
                execute_build.delay(build.id, build_config.builder)
        if nbuilds < 1:
            # Don't keep empty commits
            commit.delete()

    return HttpResponse()

class ProjectList(ListView):
    model = Project

    def get_context_data(self, **kwargs):
        context = super(ProjectList, self).get_context_data(**kwargs)
        context['projects'] = projects = []
        for project in self.object_list:
            unfinished_builds = {'active': project.get_active_builds().count(),
                                 'pending': project.get_pending_builds().count()}
            commit_pks = [c.pk for c in project.get_latest_branch_commits()]
            success_values = Build.objects.filter(commit__pk__in=commit_pks) \
                                          .values_list('was_successful', flat=True)
            finished_builds = len(success_values)
            failed_builds = len(filter(not_, success_values))
            state = 'unknown' if not finished_builds else \
                        ('failed' if failed_builds else 'successful')
            projects.append([
                project, state, unfinished_builds,
                finished_builds, failed_builds
            ])
        return context

class ProjectDetails(DetailView):
    model = Project

    def get_context_data(self, **kwargs):
        context = super(ProjectDetails, self).get_context_data(**kwargs)
        context['commits'] = self.object.get_branch_commits()
        return context

class CommitDetails(DetailView):
    model = Commit

    def get_context_data(self, **kwargs):
        context = super(CommitDetails, self).get_context_data(**kwargs)
        # TODO
        assert context['object'].vcs_id
        context['builds'] = self.get_builds_grouped_by_state()
        return context

    def get_builds_grouped_by_state(self):
        state_order = ['failed', 'successful', 'active', 'pending']
        return sorted(self.object.builds.all(),
                      key=lambda build: state_order.index(build.state))
<commit_msg>Refactoring<commit_after>from operator import not_
from collections import OrderedDict

from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404
from django.views.generic import ListView, DetailView
from django.views.decorators.csrf import csrf_exempt

from ci.models import Project, Commit, Build
from ci.plugins import BUILD_HOOKS
from ci.tasks import execute_build

def get_project_by_slug(slug):
    return get_object_or_404(Project, slug=slug)

@csrf_exempt
def build_hook(request, project_slug, hook_type):
    project = get_project_by_slug(project_slug)
    if hook_type not in BUILD_HOOKS:
        raise Http404
    hook = BUILD_HOOKS[hook_type](request)

    branches = {branch: project.commits.create(branch=branch)
                for branch in hook.get_changed_branches()}

    configurations = project.configurations.all()
    for branch, commit in branches.iteritems():
        nbuilds = 0
        for build_config in configurations:
            if build_config.should_build_branch(branch):
                nbuilds += 1
                build = commit.builds.create(configuration=build_config)
                execute_build.delay(build.id, build_config.builder)
        if nbuilds < 1:
            # Don't keep empty commits
            commit.delete()

    return HttpResponse()

class ProjectList(ListView):
    model = Project

    def get_context_data(self, **kwargs):
        context = super(ProjectList, self).get_context_data(**kwargs)
        context['projects'] = list(self.get_project_list())
        return context

    def get_project_list(self):
        for project in self.object_list:
            unfinished_builds = {'active': project.get_active_builds().count(),
                                 'pending': project.get_pending_builds().count()}
            commit_pks = [c.pk for c in project.get_latest_branch_commits()]
            success_values = Build.objects.filter(commit__pk__in=commit_pks) \
                                          .values_list('was_successful', flat=True)
            finished_builds = len(success_values)
            failed_builds = len(filter(not_, success_values))
            state = 'unknown' if not finished_builds else \
                        ('failed' if failed_builds else 'successful')

            yield project, state, unfinished_builds, finished_builds, failed_builds

class ProjectDetails(DetailView):
    model = Project

    def get_context_data(self, **kwargs):
        context = super(ProjectDetails, self).get_context_data(**kwargs)
        context['commits'] = self.object.get_branch_commits()
        return context

class CommitDetails(DetailView):
    model = Commit

    def get_context_data(self, **kwargs):
        context = super(CommitDetails, self).get_context_data(**kwargs)
        # TODO
        assert context['object'].vcs_id
        context['builds'] = self.get_builds_grouped_by_state()
        return context

    def get_builds_grouped_by_state(self):
        state_order = ['failed', 'successful', 'active', 'pending']
        return sorted(self.object.builds.all(),
                      key=lambda build: state_order.index(build.state))
<|endoftext|>