<commit_before>#!/usr/bin/python

# -*- coding: utf-8 -*-
# VISIT MY LABORATORY

from __future__ import print_function, with_statement

import fcntl, sys, re, time
import cherrypy, json
import expeyes.eyesj
import os.path

class ExpPage:
    """
    @class ExpPage HANDLE ALL WEB PAGE REQUESTS
    """

    def __init__(self):
        """
        The constructor.
        """
        self.active=True       # state of the automaton
        self.hw_lock=False     # a lockto prevent double initialization
        self.device=None       # Expeyes driver
        self.measurements=None # data returned by the measurement box
        self.oldMeasurements=None # backup data
        # backup data are served if too much requests are coming simultaneously
        self.mtype=''          # typeof data describing the measurements
        self.connect()         # initializes the driver
        self.first_config="true" # scope is not yet configured for samples, etc.
        return

    def connect(self):
        """
        tries to connect Expeyes-Jr. This should succeed if Expeyes-Jr
        is physically plugged, even if it is currently in "connected" state.
        """
        if self.device !=None:
            self.device.fd.close()
        self.device = expeyes.eyesj.open()
        return

    @cherrypy.expose
    def index(self):
	"""
        features the home page
        @return an HTML file with all necessary JS libraries included,
        """
        return file("templates/index-vml.html")

    @cherrypy.expose
    def reconnect(self):
        """
        Connects to the hardware again. Does nothing when self.active
        is False (engine is stopping) or self.hw_lock is True (the
        hardware is processing some call.
        @return True if the initialization has been triggered again, else False
        """
        if (not self.active) or self.hw_lock:
            return False
        self.hw_lock=True
        self.connect()
        sys.stdout.write('\nre-init called\n\n')
        self.__init__()
        self.hw_lock=False
        return True

    @cherrypy.expose
#    @cherrypy.tools.json_out()
    def oneScopeChannel(self, **kw):
        """
        This method launches a series of measurements made at one analog
        input and returns their values.
        @param kw json encoded dictionary of keywords. Allowed keywords are:
        - config:   boolean; when it is True or when the scope had never
          been configured, the other parameters are taken in account
        - input:    integer or string, selects an analog input;
          defaults to 1 (channel A1). If it is a string like "A1", "A2", etc.
          then the string will be converted to a relevant value.
        - samples:  integer, number of samples; defaults to 201 (200 intervals)
        - delay:    integer, delay in microsecond between two samples;
          defaults to 200 (200 * 200 microseconds= 40 ms)
        - duration: float, total time span of the measurements in second
        By default, measures voltage at input A1, 201 samples spanning 40 ms.
        If the keyword 'duration' is used, it will redefine the value of
        delay, which is 200 microseconds by default.
        @return measurement values
        """
        kw=json.loads(kw["options"])
        print("GRRR kw=", kw)
        # default values
        expeyes_inputs={
            "A1":1,
            "A2":2,
            }

        if ("config"in kw and kw["config"]) or self.first_config:
            if self.first_config:
                print ("GRRR first configuration")
                self.first_config=False
                self.inp = 1
                self.samples = 201
                self.delay = 200

            if 'input' in kw and kw['input']:
                # sets the input according to parameters
                input=kw['input']
                if input in expeyes_inputs:
                    input=expeyes_inputs[input]
                    self.inp=input
                    print ("GRRR self.inp set to", self.inp)
                else:
                    try :
                        input=int(input)
                        self.inp=input
                        print ("GRRR self.inp set to", self.inp)
                    except:
                        pass

            if 'samples' in kw and kw['samples']:
                try:
                    self.samples=kw['samples']
                    print ("GRRRR self.samples set to", self.samples)
                except:
                    pass
            if 'delay' in kw and kw['delay']:
                try:
                    self.delay=int(kw['delay']*1000000)
                    print ("GRRRR self.delay set to", self.delay)
                except:
                    pass
            if 'duration' in kw and kw['duration']:
                try:
                    self.delay=int(1000000*kw['duration']/(self.samples-1))
                    print ("GRRRR self.delay set to", self.delay, "due to duration parameter")
                except:
                    pass

        self.mtype = 't,v' # two arrays, first for time, second for voltage
        if self.hw_lock:
            return json.dumps(self.oldMeasurements)
        self.hw_lock=True
        self.oldMeasurements=self.measurements # backups old data
        print ("GRRR self.device.capture(self.inp, self.samples, self.delay)= self.device.capture(%s, %s, %s)" %(self.inp, self.samples, self.delay))
        self.measurements = self.device.capture(self.inp, self.samples, self.delay)
        self.hw_lock=False
        return json.dumps(self.measurements)

    sampleArray=[11,21,51,101,201,501,1001]

    @cherrypy.expose
    def sampleMinus(self, **kw):
        """
        chooses a lower value for self.samples if possible
        @param kw a dummy dictionary to catch the session param
        """
        if self.samples in ExpPage.sampleArray:
            i=ExpPage.sampleArray.index(self.samples);
            if i > 0:
                self.samples=ExpPage.sampleArray[i-1]
        else:
            i=0;
            while i < len(ExpPage.sampleArray)-2 and self.samples > ExpPage.sampleArray[i+1]:
                i+=1
            self.samples=ExpPage.sampleArray[i]
        return

    @cherrypy.expose
    def samplePlus(self, **kw):
        """
        chooses a higher value for self.samples if possible
        @param kw a dummy dictionary to catch the session param
        """
        if self.samples in ExpPage.sampleArray:
            i=ExpPage.sampleArray.index(self.samples);
            if i < len(ExpPage.sampleArray)-1:
                self.samples=ExpPage.sampleArray[i+1]
        else:
            i=len(ExpPage.sampleArray)-1;
            while i > 0 and self.samples < ExpPage.sampleArray[i-1]:
                i-=1
            self.samples=ExpPage.sampleArray[i]
        return

    @cherrypy.expose
    def getValues(self, **kw):
        """
        a routine to get measured values as a useful file
        @param kw keywords; allowed keywords are:
        - mode: the way you want to get the values
        The default mode is "ascii", which means that
        values are formated as ascii lines (space-separated numbers).

        Other supported modes are not yet implemented
        @return a stream with the relevant MIMEtype.
        """
        if 'mode' in kw:
            mode=kw['mode']
        else:
            mode='ascii'
        if mode=="ascii":
            ## define response headers
            cherrypy.response.headers["Content-Type"]="text/ascii;charset=utf-8"
            ## this one needs a fix !!!
            filename="values-{0}.txt".format(time.strftime("%Y-%m-%d_%H:%M:%S"))
            print("The file name should be:",filename)
            cherrypy.response.headers["File-Name"]=filename

            if self.mtype=='t,v':
                result=""
                t,v = self.measurements
                for i in range(len(t)):
                    result+="{0:f} {1:f}\n".format(t[i], v[i])
                return result
            else:
                return "mode = '%s', measurement type '%s' not supported." %(mode, self.mtype)
        return "non-supported mode %s" %mode

def stopit():
    """
    Callback function which is assigned to channels "stop" and "exit"
    """
    global app # this one is defined during the call to startServer
    app.active=False
    if cherrypy.engine.state != cherrypy.engine.states.STARTED:
        sys.exit(1)
    return

def checkLock(lockFileName='expeyes-server.lock'):
    """
    checks that the server is launched only once. Uses a lock file
    @param lockFileName the name of the lock file. The default value
    should be used.
    @return true if the process can control the lock file
    """
    fp = open(lockFileName, 'w')
    try:
        fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
    except IOError:
        # another instance is running
        sys.stdout.write ("Another instance is running. Not starting.\n")
        sys.exit(1)
    return True

def startServer():
    """
    Starts the web service
    """
    global app
    abspath=os.path.abspath('.')
    conffile = os.path.join(abspath, 'server.conf')
    confdict={
        "/": {
            'tools.staticfile.root': abspath,
            'tools.staticdir.root': abspath,
        },
    }
    cherrypy.config.update(confdict)
    cherrypy.config.update(conffile)
    app = cherrypy.tree.mount(ExpPage(), '/', conffile)
    app.merge(confdict)
    stopit.priority = 1
    cherrypy.engine.subscribe('stop', stopit)
    cherrypy.engine.subscribe('exit', stopit)
    cherrypy.engine.start()
    cherrypy.engine.block()
    return

if __name__=='__main__':
    checkLock() # aborts if the server is already running.
    app=None # global variable
    startServer()

# Local Variables:
# mode: Python
# python-indent: 4
# End:
<commit_msg>implemented sampleMinus and samplePlus buttons, better<commit_after>#!/usr/bin/python

# -*- coding: utf-8 -*-
# VISIT MY LABORATORY

from __future__ import print_function, with_statement

import fcntl, sys, re, time
import cherrypy, json
import expeyes.eyesj
import os.path

class ExpPage:
    """
    @class ExpPage HANDLE ALL WEB PAGE REQUESTS
    """

    def __init__(self):
        """
        The constructor.
        """
        self.active=True       # state of the automaton
        self.hw_lock=False     # a lockto prevent double initialization
        self.device=None       # Expeyes driver
        self.measurements=None # data returned by the measurement box
        self.oldMeasurements=None # backup data
        # backup data are served if too much requests are coming simultaneously
        self.mtype=''          # typeof data describing the measurements
        self.connect()         # initializes the driver
        self.first_config="true" # scope is not yet configured for samples, etc.
        return

    def connect(self):
        """
        tries to connect Expeyes-Jr. This should succeed if Expeyes-Jr
        is physically plugged, even if it is currently in "connected" state.
        """
        if self.device !=None:
            self.device.fd.close()
        self.device = expeyes.eyesj.open()
        return

    @cherrypy.expose
    def index(self):
	"""
        features the home page
        @return an HTML file with all necessary JS libraries included,
        """
        return file("templates/index-vml.html")

    @cherrypy.expose
    def reconnect(self):
        """
        Connects to the hardware again. Does nothing when self.active
        is False (engine is stopping) or self.hw_lock is True (the
        hardware is processing some call.
        @return True if the initialization has been triggered again, else False
        """
        if (not self.active) or self.hw_lock:
            return False
        self.hw_lock=True
        self.connect()
        sys.stdout.write('\nre-init called\n\n')
        self.__init__()
        self.hw_lock=False
        return True

    @cherrypy.expose
#    @cherrypy.tools.json_out()
    def oneScopeChannel(self, **kw):
        """
        This method launches a series of measurements made at one analog
        input and returns their values.
        @param kw json encoded dictionary of keywords. Allowed keywords are:
        - config:   boolean; when it is True or when the scope had never
          been configured, the other parameters are taken in account
        - input:    integer or string, selects an analog input;
          defaults to 1 (channel A1). If it is a string like "A1", "A2", etc.
          then the string will be converted to a relevant value.
        - samples:  integer, number of samples; defaults to 201 (200 intervals)
        - delay:    integer, delay in microsecond between two samples;
          defaults to 200 (200 * 200 microseconds= 40 ms)
        - duration: float, total time span of the measurements in second
        By default, measures voltage at input A1, 201 samples spanning 40 ms.
        If the keyword 'duration' is used, it will redefine the value of
        delay, which is 200 microseconds by default.
        @return measurement values
        """
        kw=json.loads(kw["options"])
        print("GRRR kw=", kw)
        # default values
        expeyes_inputs={
            "A1":1,
            "A2":2,
            }

        if ("config"in kw and kw["config"]) or self.first_config:
            if self.first_config:
                print ("GRRR first configuration")
                self.first_config=False
                self.inp = 1
                self.samples = 201
                self.delay = 200

            if 'input' in kw and kw['input']:
                # sets the input according to parameters
                input=kw['input']
                if input in expeyes_inputs:
                    input=expeyes_inputs[input]
                    self.inp=input
                    print ("GRRR self.inp set to", self.inp)
                else:
                    try :
                        input=int(input)
                        self.inp=input
                        print ("GRRR self.inp set to", self.inp)
                    except:
                        pass

            if 'samples' in kw and kw['samples']:
                try:
                    self.samples=kw['samples']
                    print ("GRRRR self.samples set to", self.samples)
                except:
                    pass
            if 'delay' in kw and kw['delay']:
                try:
                    self.delay=int(kw['delay']*1000000)
                    print ("GRRRR self.delay set to", self.delay)
                except:
                    pass
            if 'duration' in kw and kw['duration']:
                try:
                    self.delay=int(1000000*kw['duration']/(self.samples-1))
                    print ("GRRRR self.delay set to", self.delay, "due to duration parameter")
                except:
                    pass

        self.mtype = 't,v' # two arrays, first for time, second for voltage
        if self.hw_lock:
            return json.dumps(self.oldMeasurements)
        self.hw_lock=True
        self.oldMeasurements=self.measurements # backups old data
        print ("GRRR self.device.capture(self.inp, self.samples, self.delay)= self.device.capture(%s, %s, %s)" %(self.inp, self.samples, self.delay))
        self.measurements = self.device.capture(self.inp, self.samples, self.delay)
        self.hw_lock=False
        return json.dumps(self.measurements)

    sampleArray=[11,21,51,101,201,501,1001]

    @cherrypy.expose
    def sampleMinus(self, **kw):
        """
        chooses a lower value for self.samples if possible,
        while keeping the same total duration
        @param kw a dummy dictionary to catch the session param
        """
        oldSamples=self.samples
        if self.samples in ExpPage.sampleArray:
            i=ExpPage.sampleArray.index(self.samples);
            if i > 0:
                self.samples=ExpPage.sampleArray[i-1]
        else:
            i=0;
            while i < len(ExpPage.sampleArray)-2 and self.samples > ExpPage.sampleArray[i+1]:
                i+=1
            self.samples=ExpPage.sampleArray[i]
        if oldSamples != self.samples:
            self.delay=int(self.delay*(oldSamples-1)/(self.samples-1))
        return

    @cherrypy.expose
    def samplePlus(self, **kw):
        """
        chooses a higher value for self.samples if possible
        @param kw a dummy dictionary to catch the session param
        """
        if self.samples in ExpPage.sampleArray:
            i=ExpPage.sampleArray.index(self.samples);
            if i < len(ExpPage.sampleArray)-1:
                self.samples=ExpPage.sampleArray[i+1]
        else:
            i=len(ExpPage.sampleArray)-1;
            while i > 0 and self.samples < ExpPage.sampleArray[i-1]:
                i-=1
            self.samples=ExpPage.sampleArray[i]
        if oldSamples != self.samples:
            self.delay=int(self.delay*(oldSamples-1)/(self.samples-1))
        return

    @cherrypy.expose
    def getValues(self, **kw):
        """
        a routine to get measured values as a useful file
        @param kw keywords; allowed keywords are:
        - mode: the way you want to get the values
        The default mode is "ascii", which means that
        values are formated as ascii lines (space-separated numbers).

        Other supported modes are not yet implemented
        @return a stream with the relevant MIMEtype.
        """
        if 'mode' in kw:
            mode=kw['mode']
        else:
            mode='ascii'
        if mode=="ascii":
            ## define response headers
            cherrypy.response.headers["Content-Type"]="text/ascii;charset=utf-8"
            ## this one needs a fix !!!
            filename="values-{0}.txt".format(time.strftime("%Y-%m-%d_%H:%M:%S"))
            print("The file name should be:",filename)
            cherrypy.response.headers["File-Name"]=filename

            if self.mtype=='t,v':
                result=""
                t,v = self.measurements
                for i in range(len(t)):
                    result+="{0:f} {1:f}\n".format(t[i], v[i])
                return result
            else:
                return "mode = '%s', measurement type '%s' not supported." %(mode, self.mtype)
        return "non-supported mode %s" %mode

def stopit():
    """
    Callback function which is assigned to channels "stop" and "exit"
    """
    global app # this one is defined during the call to startServer
    app.active=False
    if cherrypy.engine.state != cherrypy.engine.states.STARTED:
        sys.exit(1)
    return

def checkLock(lockFileName='expeyes-server.lock'):
    """
    checks that the server is launched only once. Uses a lock file
    @param lockFileName the name of the lock file. The default value
    should be used.
    @return true if the process can control the lock file
    """
    fp = open(lockFileName, 'w')
    try:
        fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB)
    except IOError:
        # another instance is running
        sys.stdout.write ("Another instance is running. Not starting.\n")
        sys.exit(1)
    return True

def startServer():
    """
    Starts the web service
    """
    global app
    abspath=os.path.abspath('.')
    conffile = os.path.join(abspath, 'server.conf')
    confdict={
        "/": {
            'tools.staticfile.root': abspath,
            'tools.staticdir.root': abspath,
        },
    }
    cherrypy.config.update(confdict)
    cherrypy.config.update(conffile)
    app = cherrypy.tree.mount(ExpPage(), '/', conffile)
    app.merge(confdict)
    stopit.priority = 1
    cherrypy.engine.subscribe('stop', stopit)
    cherrypy.engine.subscribe('exit', stopit)
    cherrypy.engine.start()
    cherrypy.engine.block()
    return

if __name__=='__main__':
    checkLock() # aborts if the server is already running.
    app=None # global variable
    startServer()

# Local Variables:
# mode: Python
# python-indent: 4
# End:
<|endoftext|>


<commit_before>import argparse
import inspect
import logging
import voltverine.plugins
import voltverine.actions

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

_PLUGIN_BLACKLIST = ['BasePlugin', 'BaseDbusPlugin']

class VoltverineApp(object):

    def __init__(self):
        self._parse_args()
        if self.args.verbose:
            # get the "root" logger and set it to DEBUG
            logging.getLogger().setLevel(logging.DEBUG)
        self._find_plugins()
        self._action = voltverine.actions.LogindPoweroff()

    def _parse_args(self):
        parser = argparse.ArgumentParser(description='maybe shutdown the machine')
        parser.add_argument('-d', '--daemonize', action='store_true')
        parser.add_argument('-f', '--foreground', action='store_true')
        parser.add_argument('-n', '--dry-run', action='store_true')
        parser.add_argument('-v', '--verbose', action='store_true')
        parser.add_argument('-c', '--config', action='store')
        parser.add_argument('-a', '--all-plugins', action='store_true')
        parser.add_argument('--version', action='version', version='%(prog)s 0.1.0')
        self.args = parser.parse_args()

    def _find_plugins(self):
        self._plugins = inspect.getmembers(voltverine.plugins,
                                           lambda x: inspect.isclass(x) and
                                           x.__name__ not in _PLUGIN_BLACKLIST)

    def run(self):
        if self.args.daemonize:
            # do something to run self._run() as a daemon
            pass
        elif self.args.foreground:
            # do something to run self._run() in a loop in foreground
            pass
        else:
            self._run()

    def _run(self):
        results = {voltverine.plugins.NOT_OK: 0, voltverine.plugins.OK: 0, voltverine.plugins.DUNNO: 0}
        for plugin in self._plugins:
            logger.debug("Trying %s", plugin[0])
            pobj = plugin[1]()
            (result, info) = pobj.analyze()
            if result is voltverine.plugins.NOT_OK and not self.args.all_plugins:
                logger.info("%s decided we cannot shutdown now, skipping the other plugins", plugin[0])
                return
            logger.info((result, info))
            results[result] += 1
        if results[voltverine.plugins.NOT_OK] > 0:
            logger.debug("plugins decided not to take action")
        elif results[voltverine.plugins.OK] > 0:
            logger.debug("executing action")
            if not self.args.dry_run:
                self._action.execute()
        else:
            logger.info("nobody said it is ok to execute an action")
<commit_msg>implement loading of configuration files<commit_after>import argparse
import inspect
import logging
import os
import sys
import yaml
import voltverine.plugins
import voltverine.actions

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

_PLUGIN_BLACKLIST = ['BasePlugin', 'BaseDbusPlugin']
_DEFAULT_CONFIG = {'action': 'LogindPoweroff'}

class VoltverineApp(object):

    def __init__(self):
        self._parse_args()
        if self.args.verbose:
            # get the "root" logger and set it to DEBUG
            logging.getLogger().setLevel(logging.DEBUG)
        self._parse_config()
        self._find_plugins()
        self._action = voltverine.actions.LogindPoweroff()

    def _parse_args(self):
        parser = argparse.ArgumentParser(description='maybe shutdown the machine')
        parser.add_argument('-d', '--daemonize', action='store_true')
        parser.add_argument('-f', '--foreground', action='store_true')
        parser.add_argument('-n', '--dry-run', action='store_true')
        parser.add_argument('-v', '--verbose', action='store_true')
        parser.add_argument('-c', '--config', action='store')
        parser.add_argument('-a', '--all-plugins', action='store_true')
        parser.add_argument('--version', action='version', version='%(prog)s 0.1.0')
        self.args = parser.parse_args()

    def _parse_config(self):
        self.config = _DEFAULT_CONFIG
        if not self.args.config:
            for f in ['voltverine.conf', os.path.expanduser('~/.config/voltverine/voltverine.conf'), '/etc/voltverine/voltverine.conf']:
                if os.path.isfile(f) and os.access(f, os.R_OK):
                    self.args.config = f
                    break
        elif not (os.path.isfile(self.args.config) and os.access(self.args.config, os.R_OK)):
            logger.error("The configuration file is not readable, exiting.")
            sys.exit(1)
        if self.args.config:
            with open(self.args.config) as configfile:
                self.config.update(yaml.safe_load(configfile))
        _args_config = {
            'daemonize': self.args.daemonize,
            'foreground': self.args.foreground,
            'dry_run': self.args.dry_run,
            'verbose': self.args.verbose,
            'all_plugins': self.args.all_plugins,
            }
        self.config.update(_args_config)

    def _find_plugins(self):
        self._plugins = inspect.getmembers(voltverine.plugins,
                                           lambda x: inspect.isclass(x) and
                                           x.__name__ not in _PLUGIN_BLACKLIST)

    def run(self):
        if self.args.daemonize:
            # do something to run self._run() as a daemon
            pass
        elif self.args.foreground:
            # do something to run self._run() in a loop in foreground
            pass
        else:
            self._run()

    def _run(self):
        results = {voltverine.plugins.NOT_OK: 0, voltverine.plugins.OK: 0, voltverine.plugins.DUNNO: 0}
        for plugin in self._plugins:
            logger.debug("Trying %s", plugin[0])
            pobj = plugin[1]()
            (result, info) = pobj.analyze()
            if result is voltverine.plugins.NOT_OK and not self.args.all_plugins:
                logger.info("%s decided we cannot shutdown now, skipping the other plugins", plugin[0])
                return
            logger.info((result, info))
            results[result] += 1
        if results[voltverine.plugins.NOT_OK] > 0:
            logger.debug("plugins decided not to take action")
        elif results[voltverine.plugins.OK] > 0:
            logger.debug("executing action")
            if not self.args.dry_run:
                self._action.execute()
        else:
            logger.info("nobody said it is ok to execute an action")
<|endoftext|>


<commit_before>"""Visual profiler for Python."""
import argparse
import functools
import json
import profile
import stats_server
import subprocess
import sys

_MODULE_DESC = 'Python visual profiler.'
_HOST = 'localhost'
_PORT = 8000

def main():
    parser = argparse.ArgumentParser(description=_MODULE_DESC)
    parser.add_argument('source', metavar='src', nargs=1,
                        help='Python program to profile.')
    args = parser.parse_args()
    sys.argv[:] = args.source

    print('Collecting profile stats...')
    program_info = profile.CProfile(args.source[0]).run()

    partial_handler = functools.partial(
        stats_server.StatsHandler, profile_json=json.dumps(program_info))
    subprocess.call(['open', 'http://%s:%s' % (_HOST, _PORT)])
    stats_server.start(_HOST, _PORT, partial_handler)

if __name__ == "__main__":
    main()
<commit_msg>Add profilers selection as CLI option.<commit_after>"""Visual profiler for Python."""
import argparse
import functools
import json
import profile
import stats_server
import subprocess
import sys

_MODULE_DESC = 'Python visual profiler.'
_HOST = 'localhost'
_PORT = 8000

_PROFILE_MAP = {
    'c': profile.CProfile
}

def main():
    parser = argparse.ArgumentParser(description=_MODULE_DESC)
    parser.add_argument('profilers', metavar='opts',
                        help='Profilers configuration')
    parser.add_argument('source', metavar='src', nargs=1,
                        help='Python program to profile.')
    args = parser.parse_args()

    sys.argv[:] = args.source
    program_name = args.source[0]

    if len(args.profilers) > len(set(args.profilers)):
        print('Profiler configuration is ambiguous. Remove duplicates.')
        sys.exit(1)

    for prof_option in args.profilers:
        if prof_option not in _PROFILE_MAP:
            print('Unrecognized option: %s' % prof_option)
            sys.exit(2)

    print('Collecting profile stats...')

    prof_option = args.profilers[0]
    profiler = _PROFILE_MAP[prof_option]
    program_info = profile.CProfile(args.source[0]).run()

    partial_handler = functools.partial(
        stats_server.StatsHandler, profile_json=json.dumps(program_info))
    subprocess.call(['open', 'http://%s:%s' % (_HOST, _PORT)])
    stats_server.start(_HOST, _PORT, partial_handler)

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


<commit_before>"""
Functions to read values direction from a configuration namespace.  Values
will be validated, but will not be wrapped in a Proxy.

.. code-block:: python

    import staticconf

    max_value = staticconf.read_int('max_value')
    # Read a value from a namespace
    intervals = staticconf.read_float('intervals', namespace='something')

Readers can be attached to a namespace using a NamespaceReaders object.

.. code-block:: python

    import staticconf

    bling_reader = staticconf.NamespaceReader('bling')

    currency = bling_reader.read_string('currency')
    value = bling_reader.read_float('value')

"""
from staticconf import validation, config, errors
from staticconf.proxy import UndefToken

def _read_config(config_key, config_namespace, default):
    value = config_namespace.get(config_key, default=default)
    if value is UndefToken:
        msg = '%s missing value for %s' % (config_namespace, config_key)
        raise errors.ConfigurationError(msg)
    return value

def build_reader(validator, reader_namespace=config.DEFAULT):
    def reader(config_key, default=UndefToken, namespace=None):
        config_namespace = config.get_namespace(namespace or reader_namespace)
        return validator(_read_config(config_key, config_namespace, default))
    return reader

class ReaderNameFactory(object):
    """Factory used to create the NamespaceReaders object."""

    @staticmethod
    def get_name(name):
        return 'read_%s' % name if name else 'read'

    @staticmethod
    def get_list_of_name(name):
        return 'read_list_of_%s' % name

def get_all_accessors(name_factory):
    for name, validator in validation.get_validators():
        yield name_factory.get_name(name), validator
        yield (name_factory.get_list_of_name(name),
               validation.build_list_type_validator(validator))

class NamespaceAccessor(object):

    def __init__(self, name, accessor_map, builder):
        self.accessor_map       = accessor_map
        self.builder            = builder
        self.namespace          = name

    def __getattr__(self, item):
        if item not in self.accessor_map:
            raise AttributeError(item)
        return self.builder(self.accessor_map[item], self.namespace)

    def get_methods(self):
        return dict((name, getattr(self, name)) for name in self.accessor_map)

def build_accessor_type(name_factory, builder):
    accessor_map = dict(get_all_accessors(name_factory))
    return lambda name: NamespaceAccessor(name, accessor_map, builder)

NamespaceReaders = build_accessor_type(ReaderNameFactory, build_reader)

default_readers = NamespaceReaders(config.DEFAULT)
globals().update(default_readers.get_methods())

__all__ = ['NamespaceReaders'] + list(default_readers.get_methods())
<commit_msg>Document list of reader accessors<commit_after>"""
Functions to read values directly from a configuration namespace.  Values
will be validated, but will not be wrapped in a Proxy.

.. code-block:: python

    import staticconf

    max_value = staticconf.read_int('max_value')
    # Read a value from a namespace
    intervals = staticconf.read_float('intervals', namespace='something')

Readers can be attached to a namespace using a NamespaceReaders object.

.. code-block:: python

    import staticconf

    bling_reader = staticconf.NamespaceReader('bling')

    currency = bling_reader.read_string('currency')
    value = bling_reader.read_float('value')

Available reader accessors include:

    - read_bool()
    - read_date()
    - read_datetime()
    - read_float()
    - read_int()
    - read_list()
    - read_list_of_bool()
    - read_list_of_date()
    - read_list_of_datetime()
    - read_list_of_float()
    - read_list_of_int()
    - read_list_of_list()
    - read_list_of_set()
    - read_list_of_time()
    - read_list_of_tuple()
    - read_regex()
    - read_set()
    - read_string()
    - read_tuple()
"""
from staticconf import validation, config, errors
from staticconf.proxy import UndefToken

def _read_config(config_key, config_namespace, default):
    value = config_namespace.get(config_key, default=default)
    if value is UndefToken:
        msg = '%s missing value for %s' % (config_namespace, config_key)
        raise errors.ConfigurationError(msg)
    return value

def build_reader(validator, reader_namespace=config.DEFAULT):
    def reader(config_key, default=UndefToken, namespace=None):
        config_namespace = config.get_namespace(namespace or reader_namespace)
        return validator(_read_config(config_key, config_namespace, default))
    return reader

class ReaderNameFactory(object):
    """Factory used to create the NamespaceReaders object."""

    @staticmethod
    def get_name(name):
        return 'read_%s' % name if name else 'read'

    @staticmethod
    def get_list_of_name(name):
        return 'read_list_of_%s' % name

def get_all_accessors(name_factory):
    for name, validator in validation.get_validators():
        yield name_factory.get_name(name), validator
        yield (name_factory.get_list_of_name(name),
               validation.build_list_type_validator(validator))

class NamespaceAccessor(object):

    def __init__(self, name, accessor_map, builder):
        self.accessor_map       = accessor_map
        self.builder            = builder
        self.namespace          = name

    def __getattr__(self, item):
        if item not in self.accessor_map:
            raise AttributeError(item)
        return self.builder(self.accessor_map[item], self.namespace)

    def get_methods(self):
        return dict((name, getattr(self, name)) for name in self.accessor_map)

def build_accessor_type(name_factory, builder):
    accessor_map = dict(get_all_accessors(name_factory))
    return lambda name: NamespaceAccessor(name, accessor_map, builder)

NamespaceReaders = build_accessor_type(ReaderNameFactory, build_reader)

default_readers = NamespaceReaders(config.DEFAULT)
globals().update(default_readers.get_methods())

__all__ = ['NamespaceReaders'] + list(default_readers.get_methods())
<|endoftext|>


<commit_before>import abc
import collections
import json
import time
import datetime

import sqlalchemy as sa
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import scoped_session

class BaseModelClass(object):
    id = sa.Column(sa.Integer, primary_key=True)
    timestamp = sa.Column(sa.DateTime, nullable=False, index=True)

class ScalarModelClass(BaseModelClass):
    scalar = sa.Column(sa.Integer, nullable=False)

    @classmethod
    def to_csv(cls, instances):
        return "\n".join([
            "%0.2f, %i" % (time.mktime(ins.timestamp.timetuple()), ins.scalar)
            for ins in instances
        ])

class CategorizedModelClass(BaseModelClass):
    category = sa.Column(sa.UnicodeText, nullable=False)
    scalar = sa.Column(sa.Integer, nullable=False)

    @classmethod
    def collate(cls, instances):
        categories = set([i.category for i in instances])

        results = collections.OrderedDict()
        for instance in instances:
            tstamp = time.mktime(instance.timestamp.timetuple())
            if tstamp not in results:
                results[tstamp] = collections.OrderedDict(zip(
                    categories, [0] * len(categories)))
            results[tstamp][instance.category] = instance.scalar

        return results

    @classmethod
    def to_csv(cls, instances):
        results = cls.collate(instances)
        return "\n".join([
            "%0.2f, %s" % (tstamp, ", ".join(map(str, result.values())))
            for tstamp, result in results.items()
        ])

class CategorizedLogModelClass(BaseModelClass):
    category = sa.Column(sa.UnicodeText, nullable=False, index=True)
    message = sa.Column(sa.UnicodeText, nullable=False)

    @classmethod
    def to_csv(cls, instances):
        return "\n".join([
            "%0.2f, %s, %s" % (
                time.mktime(instance.timestamp.timetuple()),
                instance.category, instance.message)
            for instance in instances
        ])

    @classmethod
    def to_json(cls, instances):
        return json.dumps([
            {
                'timestamp': time.mktime(instance.timestamp.timetuple()),
                'category': instance.category,
                'message': instance.message
            } for instance in instances
        ])

class ConstrainedCategorizedLogModelClass(CategorizedLogModelClass):
    category_constraint = sa.Column(sa.UnicodeText, nullable=True)

ScalarModel = declarative_base(cls=ScalarModelClass)
CategorizedModel = declarative_base(cls=CategorizedModelClass)
CategorizedLogModel = declarative_base(cls=CategorizedLogModelClass)
ConstrainedCategorizedLogModel = declarative_base(
    cls=ConstrainedCategorizedLogModelClass)
BaseModel = declarative_base(cls=BaseModelClass)

def init_model(db_url):
    engine = create_engine(db_url)

    scopedsession = scoped_session(sessionmaker(bind=engine))
    return scopedsession

def create_tables(db_url):
    engine = create_engine(db_url, echo=True)
    ScalarModel.metadata.create_all(engine)
    CategorizedModel.metadata.create_all(engine)
    CategorizedLogModel.metadata.create_all(engine)
    ConstrainedCategorizedLogModel.metadata.create_all(engine)
    BaseModel.metadata.create_all(engine)

class BasePlugin(object):
    __meta__ = abc.ABCMeta

    name = None
    summary = None
    description = None
    frequency = None # this can just be None

    datagrepper_endpoint = 'https://apps.fedoraproject.org/datagrepper/raw/'

    def __init__(self, config, model=None):
        self.config = config
        self.model = model or self.make_model()

        required = ['name', 'summary', 'description']
        for attr in required:
            if not getattr(self, attr):
                raise ValueError("%r must define %r" % (self, attr))
        if (not isinstance(self.frequency, Frequency) and
            self.frequency is not None):
            raise TypeError(("The 'frequency' attribute of %r must be an " +
                "an instance of %r if present") % (self, Frequency))

    @property
    def ident(self):
        """
        Stringify this plugin's name to use as a (hopefully) unique identifier
        """
        ident = self.name.lower().replace(" ", "-")

        bad = ['"', "'", '(', ')', '*', '&', '?', ',']
        replacements = dict(zip(bad, [''] * len(bad)))
        for a, b in replacements.items():
            ident = ident.replace(a, b)
        frequency = getattr(self, 'frequency', None)
        if frequency:
            ident += '-{}'.format(frequency)
        return ident

    @abc.abstractmethod
    def handle(self, session, timestamp, messages):
        """ Process messages produced as of the given timestamp """
        pass

class Frequency(datetime.timedelta):
    """ timedelta extension with nicer printing """
    def __init__(self, days=0, hours=0, minutes=0, seconds=0):
        super(Frequency, self).__init__(days=days,
                                        seconds=(hours*60+minutes)*60+seconds)

    @property
    def hours(self):
        return self.seconds // (60*60)

    @property
    def minutes(self):
        return (self.seconds // 60) % 60

    @property
    def mod_seconds(self):
        return self.seconds % 60

    def __str__(self):
        # Pretty-print a timedelta in the format [[[#d]#h]#m]#s
        s = ''
        if self.days:
            s = str(days) + 'd'
        if self.hours:
            s = ''.join([s, str(self.hours), 'h'])
        if self.minutes:
            s = ''.join([s, str(self.minutes), 'm'])
        if self.mod_seconds or not s:
            s = ''.join([s, str(self.mod_seconds), 's'])
        return s

    def __repr__(self):
        kwargs = []
        for (kw, arg) in [('days', self.days),
                          ('hours', self.hours),
                          ('minutes', self.minutes),
                          ('seconds', self.mod_seconds)]:
            if arg:
                kwargs.append('='.join([kw, str(arg)]))
        return ''.join([self.__name__, '(', ','.join(kwargs), ')'])

    def __json__(self):
        return self.total_seconds()

    def __int__(self):
        return self.total_seconds()

    def __float__(self):
        return int(self) + self.microseconds / 1000
<commit_msg>Update statscache.plugins.Frequency<commit_after>import abc
import collections
import json
import time
import datetime

import sqlalchemy as sa
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.orm import scoped_session

class BaseModelClass(object):
    id = sa.Column(sa.Integer, primary_key=True)
    timestamp = sa.Column(sa.DateTime, nullable=False, index=True)

class ScalarModelClass(BaseModelClass):
    scalar = sa.Column(sa.Integer, nullable=False)

    @classmethod
    def to_csv(cls, instances):
        return "\n".join([
            "%0.2f, %i" % (time.mktime(ins.timestamp.timetuple()), ins.scalar)
            for ins in instances
        ])

class CategorizedModelClass(BaseModelClass):
    category = sa.Column(sa.UnicodeText, nullable=False)
    scalar = sa.Column(sa.Integer, nullable=False)

    @classmethod
    def collate(cls, instances):
        categories = set([i.category for i in instances])

        results = collections.OrderedDict()
        for instance in instances:
            tstamp = time.mktime(instance.timestamp.timetuple())
            if tstamp not in results:
                results[tstamp] = collections.OrderedDict(zip(
                    categories, [0] * len(categories)))
            results[tstamp][instance.category] = instance.scalar

        return results

    @classmethod
    def to_csv(cls, instances):
        results = cls.collate(instances)
        return "\n".join([
            "%0.2f, %s" % (tstamp, ", ".join(map(str, result.values())))
            for tstamp, result in results.items()
        ])

class CategorizedLogModelClass(BaseModelClass):
    category = sa.Column(sa.UnicodeText, nullable=False, index=True)
    message = sa.Column(sa.UnicodeText, nullable=False)

    @classmethod
    def to_csv(cls, instances):
        return "\n".join([
            "%0.2f, %s, %s" % (
                time.mktime(instance.timestamp.timetuple()),
                instance.category, instance.message)
            for instance in instances
        ])

    @classmethod
    def to_json(cls, instances):
        return json.dumps([
            {
                'timestamp': time.mktime(instance.timestamp.timetuple()),
                'category': instance.category,
                'message': instance.message
            } for instance in instances
        ])

class ConstrainedCategorizedLogModelClass(CategorizedLogModelClass):
    category_constraint = sa.Column(sa.UnicodeText, nullable=True)

ScalarModel = declarative_base(cls=ScalarModelClass)
CategorizedModel = declarative_base(cls=CategorizedModelClass)
CategorizedLogModel = declarative_base(cls=CategorizedLogModelClass)
ConstrainedCategorizedLogModel = declarative_base(
    cls=ConstrainedCategorizedLogModelClass)
BaseModel = declarative_base(cls=BaseModelClass)

def init_model(db_url):
    engine = create_engine(db_url)

    scopedsession = scoped_session(sessionmaker(bind=engine))
    return scopedsession

def create_tables(db_url):
    engine = create_engine(db_url, echo=True)
    ScalarModel.metadata.create_all(engine)
    CategorizedModel.metadata.create_all(engine)
    CategorizedLogModel.metadata.create_all(engine)
    ConstrainedCategorizedLogModel.metadata.create_all(engine)
    BaseModel.metadata.create_all(engine)

class BasePlugin(object):
    __meta__ = abc.ABCMeta

    name = None
    summary = None
    description = None
    frequency = None # this may be left as None

    datagrepper_endpoint = 'https://apps.fedoraproject.org/datagrepper/raw/'

    def __init__(self, config, model=None):
        self.config = config
        self.model = model or self.make_model()

        required = ['name', 'summary', 'description']
        for attr in required:
            if not getattr(self, attr):
                raise ValueError("%r must define %r" % (self, attr))
        if (not isinstance(self.frequency, Frequency) and
            self.frequency is not None):
            raise TypeError(("The 'frequency' attribute of %r must be an " +
                "an instance of %r if present") % (self, Frequency))

    @property
    def ident(self):
        """
        Stringify this plugin's name to use as a (hopefully) unique identifier
        """
        ident = self.name.lower().replace(" ", "-")

        bad = ['"', "'", '(', ')', '*', '&', '?', ',']
        replacements = dict(zip(bad, [''] * len(bad)))
        for a, b in replacements.items():
            ident = ident.replace(a, b)
        frequency = getattr(self, 'frequency', None)
        if frequency:
            ident += '-{}'.format(frequency)
        return ident

    @abc.abstractmethod
    def handle(self, session, timestamp, messages):
        """ Process messages produced as of the given timestamp """
        pass

class Frequency(object):
    """ A repeating interval synchronized on UTC midnight """
    def __init__(self, days=0, hours=0, minutes=0, seconds=0):
        self.interval = datetime.timedelta(days=days, hours=hours,
            minutes=minutes, seconds=seconds)

    def __eq__(self, other):
        if isinstance(other, Frequency):
            other = other.interval
        elif not isinstance(other, datetime.timedelta):
            raise NotImplementedError()
        return self.interval == other

    def __ne__(self, other):
        return not (self == other)

    def __hash__(self):
        # the value of the object is uniquely determined by its interval
        return hash(self.interval)

    @property
    def days(self):
        return self.interval.days

    @property
    def hours(self):
        return self.interval.seconds // (60*60)

    @property
    def minutes(self):
        return (self.interval.seconds // 60) % 60

    @property
    def seconds(self):
        return self.interval.seconds % 60

    def __str__(self):
        # Pretty-print in the format [[[#d]#h]#m]#s
        s = ''
        if self.days:
            s = str(days) + 'd'
        if self.hours:
            s = ''.join([s, str(self.hours), 'h'])
        if self.minutes:
            s = ''.join([s, str(self.minutes), 'm'])
        if self.seconds or not s:
            s = ''.join([s, str(self.seconds), 's'])
        return s

    def __repr__(self):
        kwargs = []
        for (kw, arg) in [('days', self.days),
                          ('hours', self.hours),
                          ('minutes', self.minutes),
                          ('seconds', self.seconds)]:
            if arg:
                kwargs.append('='.join([kw, str(arg)]))
        return ''.join([type(self).__name__, '(', ','.join(kwargs), ')'])

    def time_to_fire(self, now=datetime.datetime.utcnow()):
        """ Get the remaining time-to-fire synchronized on UTC midnight """
        mid = datetime.datetime.utcnow().replace(hour=0,
                                                 minute=0,
                                                 second=0,
                                                 microsecond=0)
        rem = self.interval.seconds - (now-mid).seconds % self.interval.seconds
        return datetime.timedelta(seconds=rem - 1,
                                  microseconds=10**6-now.microsecond)

    def last(self, now=datetime.datetime.utcnow()):
        """ Get the last time-to-fire synchronized on UTC midnight """
        return self.next(now=now) - self.interval

    def next(self, now=datetime.datetime.utcnow()):
        """ Get the next time-to-fire synchronized on UTC midnight """
        return now + self.time_to_fire(now=now)

    def __json__(self):
        return self.interval.seconds

    def __float__(self):
        return self.time_to_fire().total_seconds()
<|endoftext|>


<commit_before>from asyncio import Future, get_event_loop, coroutine, iscoroutinefunction
from functools import wraps

from again.utils import unique_hex

# Service Client decorators

def make_request(func, self, args, kwargs, method):
    params = func(self, *args, **kwargs)
    entity = params.pop('entity', None)
    self = params.pop('self')
    response = yield from self._send_http_request(method, entity, params)
    return response

def get(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'get')

    return wrapper

def head(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'head')

    return wrapper

def options(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'options')

    return wrapper

def patch(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'patch')

    return wrapper

def post(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'post')

    return wrapper

def put(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'put')

    return wrapper

def trace(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'trace')

    return wrapper

def delete(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'delete')

    return wrapper

def subscribe(func):
    """
    use to listen for publications from a specific endpoint of a service,
    this method receives a publication from a remote service
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)

    wrapper.is_subscribe = True
    return wrapper

def request(func):
    """
    use to request an api call from a specific endpoint
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):
        params = func(self, *args, **kwargs)
        self = params.pop('self')
        entity = params.pop('entity', None)
        request_id = unique_hex()
        params['request_id'] = request_id
        future = self._send_request(endpoint=func.__name__, entity=entity, params=params)
        return future

    wrapper.is_request = True
    return wrapper

def message_sub(func):
    """
    use to listen for publications from a specific endpoint of a service,
    this method receives a publication from a remote service
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):
        params = func(self, *args, **kwargs)
        entity = params.pop('entity')
        self._send_message_sub(endpoint=func.__name__, entity=entity)

    wrapper.is_directed_subscribe = True
    return wrapper

# Service Host Decorators

def publish(func):
    """
    publish the return value of this function as a message from this endpoint
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):  # outgoing
        payload = func(self, *args, **kwargs)
        self._publish(func.__name__, payload)
        return None

    wrapper.is_publish = True

    return wrapper

def message_pub(func):
    """
    publish the return value of this function as a message from this endpoint
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):  # outgoing
        payload = func(self, *args, **kwargs)
        entity = payload.pop('entity')
        self._message(func.__name__, payload, entity)
        return None

    wrapper.is_publish = True

    return wrapper

def api(func):  # incoming
    """
    provide a request/response api
    receives any requests here and return value is the response
    all functions must have the following signature
        - request_id
        - entity (partition/routing key)
        followed by kwargs
    """
    @coroutine
    @wraps(func)
    def wrapper(*args, **kwargs):
        self = args[0]
        rid = kwargs.pop('request_id')
        entity = kwargs.pop('entity')
        from_id = kwargs.pop('from_id')
        result = None
        if len(kwargs):
            if iscoroutinefunction(func):
                result = yield from func(self, **kwargs)
            else:
                result = func(self, **kwargs)
        else:
            if iscoroutinefunction(func):
                result = yield from func()
            else:
                result = func()

        return self._make_response_packet(request_id=rid, from_id=from_id, entity=entity, result=result)

    wrapper.is_api = True
    return wrapper

class Service:
    _PUB_PKT_STR = 'publish'
    _REQ_PKT_STR = 'request'
    _RES_PKT_STR = 'response'
    _MSG_PUB_PKT_STR = 'message_pub'
    _MSG_SUB_PKT_STR = 'message_sub'

    def __init__(self, service_name, service_version, app_name):
        self._service_name = service_name
        self._service_version = service_version
        self._app_name = app_name
        self._bus = None

    @property
    def name(self):
        return self._service_name

    @property
    def version(self):
        return self._service_version

    @property
    def app_name(self):
        return self._app_name

    @property
    def properties(self):
        return self.app_name, self.name, self.version

    @property
    def bus(self):
        return self._bus

    @bus.setter
    def bus(self, bus):
        self._bus = bus

    @staticmethod
    def time_future(future:Future, timeout:int):
        def timer_callback(f):
            if not f.done() and not f.cancelled():
                f.set_exception(TimeoutError())

        get_event_loop().call_later(timeout, timer_callback, future)

class TCPServiceClient(Service):
    REQUEST_TIMEOUT_SECS = 10

    def __init__(self, service_name, service_version, app_name):
        super(TCPServiceClient, self).__init__(service_name, service_version, app_name)
        self._pending_requests = {}

    def _send_request(self, endpoint, entity, params):
        packet = self._make_packet(Service._REQ_PKT_STR, endpoint, params, entity)
        future = Future()
        request_id = params['request_id']
        self._pending_requests[request_id] = future
        self._bus.send(packet)
        Service.time_future(future, TCPServiceClient.REQUEST_TIMEOUT_SECS)
        return future

    def _send_message_sub(self, endpoint, entity):
        packet = self._make_packet(Service._MSG_SUB_PKT_STR, endpoint, None, entity)
        self._bus.send(packet)

    def process_packet(self, packet):
        if packet['type'] == Service._RES_PKT_STR:
            self._process_response(packet)
        elif packet['type'] == Service._PUB_PKT_STR:
            self._process_publication(packet)
        else:
            print('Invalid packet', packet)

    def _process_response(self, packet):
        payload = packet['payload']
        request_id = payload['request_id']
        has_result = 'result' in payload
        has_error = 'error' in payload
        future = self._pending_requests.pop(request_id)
        if has_result:
            future.set_result(payload['result'])
        elif has_error:
            exception = RequestException()
            exception.error = payload['error']
            future.set_exception(exception)
        else:
            print('Invalid response to request:', packet)

    def _process_publication(self, packet):
        endpoint = packet['endpoint']
        func = getattr(self, endpoint)
        func(**packet['payload'])

    def _make_packet(self, packet_type, endpoint, params, entity):
        packet = {'pid': unique_hex(),
                  'app': self.app_name,
                  'service': self.name,
                  'version': self.version,
                  'entity': entity,
                  'endpoint': endpoint,
                  'type': packet_type,
                  'payload': params}
        return packet

class _ServiceHost(Service):
    def __init__(self, service_name, service_version, app_name, host_ip, host_port):
        super(_ServiceHost, self).__init__(service_name, service_version, app_name)
        self._ip = host_ip
        self._port = host_port
        self._ronin = False

    def is_for_me(self, app, service, version):
        return app == self.app_name and \
               service == self.name and \
               int(version) == self.version

    @property
    def socket_address(self):
        return self._ip, self._port

    @property
    def ronin(self):
        return self._ronin

    @ronin.setter
    def ronin(self, value:bool):
        self._ronin = value

class _TCPServiceHost(_ServiceHost):
    def __init__(self, service_name, service_version, app_name, host_ip, host_port):
        # TODO: to be multi-tenant make app_name a list
        super(_TCPServiceHost, self).__init__(service_name, service_version, app_name, host_ip, host_port)

    def _publish(self, publication_name, payload):
        packet = self._make_publish_packet(Service._PUB_PKT_STR, publication_name, payload)
        self._bus.send(packet)

    def _message(self, message_name, payload, entity):
        packet = self._make_publish_packet(Service._MSG_PUB_PKT_STR, message_name, payload)
        packet['entity'] = entity
        self._bus.send(packet)

    def _make_response_packet(self, request_id: str, from_id: str, entity: str, result: object):
        packet = {'pid': unique_hex(),
                  'to': from_id,
                  'entity': entity,
                  'type': Service._RES_PKT_STR,
                  'payload': {'request_id': request_id, 'result': result}}
        return packet

    def _make_publish_packet(self, packet_type: str, publication_name: str, payload: dict):
        packet = {'app': self.app_name,
                  'service': self.name,
                  'version': self.version,
                  'endpoint': publication_name,
                  'type': packet_type,
                  'payload': payload}
        return packet

class RequestException(Exception):
    pass

class _HTTPServiceHost(_ServiceHost):
    def __init__(self, service_name, service_version, app_name, host_ip, host_port):
        # TODO: to be multi-tenant make app_name a list
        super(_HTTPServiceHost, self).__init__(service_name, service_version, app_name, host_ip, host_port)

    def get_routes(self):
        """
        :return: A list of 3-tuples - (HTTP method name, path, handler_function)
        """
        raise NotImplementedError()

class TCPApplicationService(_TCPServiceHost):
    pass

class TCPDomainService(_TCPServiceHost):
    pass

class TCPInfraService(_TCPServiceHost):
    pass

class HTTPApplicationService(_HTTPServiceHost):
    def get_routes(self):
        raise NotImplementedError()

class HTTPDomainService(_HTTPServiceHost):
    def get_routes(self):
        raise NotImplementedError()

class HTTPInfraService(_HTTPServiceHost):
    def get_routes(self):
        raise NotImplementedError()

class HTTPServiceClient(Service):
    def __init__(self, service_name, service_version, app_name):
        super(HTTPServiceClient, self).__init__(service_name, service_version, app_name)

    def _send_http_request(self, method, entity, params):
        response = yield from self._bus.send_http_request(self.app_name, self.name, self.version, method, entity,
                                                          params)
        return response
<commit_msg>Making service class private<commit_after>from asyncio import Future, get_event_loop, coroutine, iscoroutinefunction
from functools import wraps

from again.utils import unique_hex

# Service Client decorators

def make_request(func, self, args, kwargs, method):
    params = func(self, *args, **kwargs)
    entity = params.pop('entity', None)
    self = params.pop('self')
    response = yield from self._send_http_request(method, entity, params)
    return response

def get(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'get')

    return wrapper

def head(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'head')

    return wrapper

def options(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'options')

    return wrapper

def patch(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'patch')

    return wrapper

def post(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'post')

    return wrapper

def put(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'put')

    return wrapper

def trace(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'trace')

    return wrapper

def delete(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        return make_request(func, self, args, kwargs, 'delete')

    return wrapper

def subscribe(func):
    """
    use to listen for publications from a specific endpoint of a service,
    this method receives a publication from a remote service
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)

    wrapper.is_subscribe = True
    return wrapper

def request(func):
    """
    use to request an api call from a specific endpoint
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):
        params = func(self, *args, **kwargs)
        self = params.pop('self')
        entity = params.pop('entity', None)
        request_id = unique_hex()
        params['request_id'] = request_id
        future = self._send_request(endpoint=func.__name__, entity=entity, params=params)
        return future

    wrapper.is_request = True
    return wrapper

def message_sub(func):
    """
    use to listen for publications from a specific endpoint of a service,
    this method receives a publication from a remote service
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):
        params = func(self, *args, **kwargs)
        entity = params.pop('entity')
        self._send_message_sub(endpoint=func.__name__, entity=entity)

    wrapper.is_directed_subscribe = True
    return wrapper

# Service Host Decorators

def publish(func):
    """
    publish the return value of this function as a message from this endpoint
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):  # outgoing
        payload = func(self, *args, **kwargs)
        self._publish(func.__name__, payload)
        return None

    wrapper.is_publish = True

    return wrapper

def message_pub(func):
    """
    publish the return value of this function as a message from this endpoint
    """

    @wraps(func)
    def wrapper(self, *args, **kwargs):  # outgoing
        payload = func(self, *args, **kwargs)
        entity = payload.pop('entity')
        self._message(func.__name__, payload, entity)
        return None

    wrapper.is_publish = True

    return wrapper

def api(func):  # incoming
    """
    provide a request/response api
    receives any requests here and return value is the response
    all functions must have the following signature
        - request_id
        - entity (partition/routing key)
        followed by kwargs
    """
    @coroutine
    @wraps(func)
    def wrapper(*args, **kwargs):
        self = args[0]
        rid = kwargs.pop('request_id')
        entity = kwargs.pop('entity')
        from_id = kwargs.pop('from_id')
        result = None
        if len(kwargs):
            if iscoroutinefunction(func):
                result = yield from func(self, **kwargs)
            else:
                result = func(self, **kwargs)
        else:
            if iscoroutinefunction(func):
                result = yield from func()
            else:
                result = func()

        return self._make_response_packet(request_id=rid, from_id=from_id, entity=entity, result=result)

    wrapper.is_api = True
    return wrapper

class _Service:
    _PUB_PKT_STR = 'publish'
    _REQ_PKT_STR = 'request'
    _RES_PKT_STR = 'response'
    _MSG_PUB_PKT_STR = 'message_pub'
    _MSG_SUB_PKT_STR = 'message_sub'

    def __init__(self, service_name, service_version, app_name):
        self._service_name = service_name
        self._service_version = service_version
        self._app_name = app_name
        self._bus = None

    @property
    def name(self):
        return self._service_name

    @property
    def version(self):
        return self._service_version

    @property
    def app_name(self):
        return self._app_name

    @property
    def properties(self):
        return self.app_name, self.name, self.version

    @property
    def bus(self):
        return self._bus

    @bus.setter
    def bus(self, bus):
        self._bus = bus

    @staticmethod
    def time_future(future:Future, timeout:int):
        def timer_callback(f):
            if not f.done() and not f.cancelled():
                f.set_exception(TimeoutError())

        get_event_loop().call_later(timeout, timer_callback, future)

class TCPServiceClient(_Service):
    REQUEST_TIMEOUT_SECS = 10

    def __init__(self, service_name, service_version, app_name):
        super(TCPServiceClient, self).__init__(service_name, service_version, app_name)
        self._pending_requests = {}

    def _send_request(self, endpoint, entity, params):
        packet = self._make_packet(_Service._REQ_PKT_STR, endpoint, params, entity)
        future = Future()
        request_id = params['request_id']
        self._pending_requests[request_id] = future
        self._bus.send(packet)
        _Service.time_future(future, TCPServiceClient.REQUEST_TIMEOUT_SECS)
        return future

    def _send_message_sub(self, endpoint, entity):
        packet = self._make_packet(_Service._MSG_SUB_PKT_STR, endpoint, None, entity)
        self._bus.send(packet)

    def process_packet(self, packet):
        if packet['type'] == _Service._RES_PKT_STR:
            self._process_response(packet)
        elif packet['type'] == _Service._PUB_PKT_STR:
            self._process_publication(packet)
        else:
            print('Invalid packet', packet)

    def _process_response(self, packet):
        payload = packet['payload']
        request_id = payload['request_id']
        has_result = 'result' in payload
        has_error = 'error' in payload
        future = self._pending_requests.pop(request_id)
        if has_result:
            future.set_result(payload['result'])
        elif has_error:
            exception = RequestException()
            exception.error = payload['error']
            future.set_exception(exception)
        else:
            print('Invalid response to request:', packet)

    def _process_publication(self, packet):
        endpoint = packet['endpoint']
        func = getattr(self, endpoint)
        func(**packet['payload'])

    def _make_packet(self, packet_type, endpoint, params, entity):
        packet = {'pid': unique_hex(),
                  'app': self.app_name,
                  'service': self.name,
                  'version': self.version,
                  'entity': entity,
                  'endpoint': endpoint,
                  'type': packet_type,
                  'payload': params}
        return packet

class _ServiceHost(_Service):
    def __init__(self, service_name, service_version, app_name, host_ip, host_port):
        super(_ServiceHost, self).__init__(service_name, service_version, app_name)
        self._ip = host_ip
        self._port = host_port
        self._ronin = False

    def is_for_me(self, app, service, version):
        return app == self.app_name and \
               service == self.name and \
               int(version) == self.version

    @property
    def socket_address(self):
        return self._ip, self._port

    @property
    def ronin(self):
        return self._ronin

    @ronin.setter
    def ronin(self, value:bool):
        self._ronin = value

class _TCPServiceHost(_ServiceHost):
    def __init__(self, service_name, service_version, app_name, host_ip, host_port):
        # TODO: to be multi-tenant make app_name a list
        super(_TCPServiceHost, self).__init__(service_name, service_version, app_name, host_ip, host_port)

    def _publish(self, publication_name, payload):
        packet = self._make_publish_packet(_Service._PUB_PKT_STR, publication_name, payload)
        self._bus.send(packet)

    def _message(self, message_name, payload, entity):
        packet = self._make_publish_packet(_Service._MSG_PUB_PKT_STR, message_name, payload)
        packet['entity'] = entity
        self._bus.send(packet)

    def _make_response_packet(self, request_id: str, from_id: str, entity: str, result: object):
        packet = {'pid': unique_hex(),
                  'to': from_id,
                  'entity': entity,
                  'type': _Service._RES_PKT_STR,
                  'payload': {'request_id': request_id, 'result': result}}
        return packet

    def _make_publish_packet(self, packet_type: str, publication_name: str, payload: dict):
        packet = {'app': self.app_name,
                  'service': self.name,
                  'version': self.version,
                  'endpoint': publication_name,
                  'type': packet_type,
                  'payload': payload}
        return packet

class RequestException(Exception):
    pass

class _HTTPServiceHost(_ServiceHost):
    def __init__(self, service_name, service_version, app_name, host_ip, host_port):
        # TODO: to be multi-tenant make app_name a list
        super(_HTTPServiceHost, self).__init__(service_name, service_version, app_name, host_ip, host_port)

    def get_routes(self):
        """
        :return: A list of 3-tuples - (HTTP method name, path, handler_function)
        """
        raise NotImplementedError()

class TCPApplicationService(_TCPServiceHost):
    pass

class TCPDomainService(_TCPServiceHost):
    pass

class TCPInfraService(_TCPServiceHost):
    pass

class HTTPApplicationService(_HTTPServiceHost):
    def get_routes(self):
        raise NotImplementedError()

class HTTPDomainService(_HTTPServiceHost):
    def get_routes(self):
        raise NotImplementedError()

class HTTPInfraService(_HTTPServiceHost):
    def get_routes(self):
        raise NotImplementedError()

class HTTPServiceClient(_Service):
    def __init__(self, service_name, service_version, app_name):
        super(HTTPServiceClient, self).__init__(service_name, service_version, app_name)

    def _send_http_request(self, method, entity, params):
        response = yield from self._bus.send_http_request(self.app_name, self.name, self.version, method, entity,
                                                          params)
        return response
<|endoftext|>


<commit_before><commit_msg>Add version to wafer package.<commit_after>"""Wafer, a light-weight conference management library for Django."""

__version__ = "0.1.0a"
<|endoftext|>


<commit_before>from .streaming import streaming
from .visualize import visualize<commit_msg>Delete __init__.py<commit_after><|endoftext|>


<commit_before># plays stop action movies created by stop-action-record
# v2 adds command line support

import cv2
import sys
import time
import argparse
import os

RBG_GREEN = (0, 255, 0)		# green (red, green, blue)
FILE_TYPE = '.png'			# images will be saved as .png files
COUNT_TYPE = '.count'		# file type for the file containing the image count
TEXT_COLOR = RBG_GREEN		# frame number text color
TEXT_THICKNESS = 1			# frame number text thickness
TEXT_ORIGIN = (10, 25)		# location to place frame number text
TEXT_FONT_SCALE = 0.65		# font size for frame number textpress
DEFAULT_FPS = 10			# default frames per second
ESCAPE_KEY = 27				# ASCII value for the ESC key
LOWERCASE_F = 102 			# ASCII value for 'f'
READ_ONLY = 'r'				# read only parameter for opening files
BACKWARDS = 'backwards'     # text to use in messages about playback sequence
FORWARDS = 'forwards'		# text to use in messages about playback sequence
FIRST_FRAME_REPEAT = 0 		# number of times to repeat the frst frame on playback
LAST_FRAME_REPEAT = 0		# number of times to repeat the last frame on playback

# print debugging messages prefixed by the name of the program
def debug(programName, displayText):
	if printDebugMessages:
		print programName + ':', displayText
	return

# extract the parameters specified on the command line
parser = argparse.ArgumentParser(description='Stop action movie player')
parser.add_argument('moviename',  help='file name of the stop action movie')
parser.add_argument('-f', '--FPS', dest='framesPerSecond', default=DEFAULT_FPS, type=int, help='frames per second')
parser.add_argument('-s', '--suppressframenumbers', dest='suppressFrameText', action='store_true', help='suppress display of frame numbers')
parser.add_argument('-d', '--debug', dest='debugSwitch', action='store_true', help='display debugging messages')
parser.add_argument('-b', '--playbackwards', dest='playBackwards', action='store_true', help='play the movie backwards')
parser.add_argument('-a', '--firstframerepeat', dest='firstFrameRepeat', default=FIRST_FRAME_REPEAT, type=int, help='number of times to repeat the first frame on playback')
parser.add_argument('-z', '--lastframerepeat', dest='lastFrameRepeat', default=LAST_FRAME_REPEAT, type=int, help='number of times to repeat the last frame on playback')
args = parser.parse_args()

# save the values from the command parser
progName = parser.prog.rsplit( ".", 1 )[ 0 ]		# remove the .py from the program name
movieName = args.moviename
framesPerSecond = args.framesPerSecond
printDebugMessages = args.debugSwitch
suppressFrameText = args.suppressFrameText
playBackwards = args.playBackwards
firstFrameRepeat = args.firstFrameRepeat
lastFrameRepeat = args.lastFrameRepeat

# check for invalid frames per second setting
if framesPerSecond < 1:
	print "frames per second must be one or higher"
	sys.exit()

# determine how to play the movie
playSetting = BACKWARDS if playBackwards else FORWARDS

# calculate the delay in millseconds between frames
timeBetweenFrames = int(1000 / framesPerSecond)

# display the command parameters if debug is turned on
debug(progName, 'movie name is ' + movieName)
debug(progName, 'frames per second are ' + str(framesPerSecond))
debug(progName, 'time delay between frame is ' + str(timeBetweenFrames))
debug(progName, 'debug is set to ' + str(printDebugMessages))
debug(progName, 'movie will be played ' + playSetting)
debug(progName, 'first frame will be repeated ' + str(firstFrameRepeat) + ' times')
debug(progName, 'last frame will be repeated ' + str(lastFrameRepeat) + ' times')

# construct the file name for file containing the count of images in the movie
fn = movieName + COUNT_TYPE
debug(progName, 'count file name is ' + fn)

# verify the frame count file exists before trying to open it
if os.path.isfile(fn):
	f = open(fn, READ_ONLY)

	# read the number of frames in the moview
	count = int(f.read())
	debug(progName, 'frame count is ' + str(count))

	if count < 2:
		print "movie must contain at least two frames"
		sys.exit()

	# close the frame count file
	f.close()

	# loop reading and displaying all the frames until the ESC key is pressed
	keep_playing = True

	# create the sequence of frames to play
	playSequence = range(1, count + 1, 1)

	# if play backwards was specified, reverse the play sequence
	if playBackwards:
		playSequence.reverse()

	debug(progName, 'frame play sequence: ' + str(playSequence))

	firstFrame = playSequence[0]							# get the first frame in the sequence specified by the user
	lastFrame = playSequence[-1] 							# get the last frame in the sequence specified by the user

	debug(progName, 'first frame is ' + str(firstFrame))
	debug(progName, 'last frame is ' + str(lastFrame))

	while keep_playing:										# play the movie until the user presses the escape key

		for i in playSequence:								# loop through all the image files
			sequence = str(i).zfill(3)						# construct the image number used in the file name
			fn = movieName + "." + sequence + FILE_TYPE		# construct the file name
			debug(progName, 'displaying ' + fn)

			# verify the frame image file exists before trying to read it
			if os.path.isfile(fn):

				# read the image from the file
				dispImage = cv2.imread(fn, 1)

				# ensure c has a value since some paths do not call waitkey
				c = 0

				# if this is the first frame, repeat it according to what the user specified
				if i == firstFrame:

					# display the first frame the number of times specified
					for r in range(0, firstFrameRepeat):

						debug(progName, 're-displaying ' + fn + ' ' + str(r).zfill(3))

						# make a copy of the image so there's a clean copy used to add text each iteration
						dispTempImage = dispImage.copy()

						# check to see whether to suppress the display of frames per second, frame number, and repeat number
						if not suppressFrameText:
							frameText = 'FPS: ' + str(framesPerSecond) + ' Frame: ' + sequence + ' Repeat: ' + str(r).zfill(3)
							cv2.putText(dispTempImage, frameText, TEXT_ORIGIN, cv2.FONT_HERSHEY_SIMPLEX, TEXT_FONT_SCALE, TEXT_COLOR, TEXT_THICKNESS)

						# display the frame
						cv2.imshow(movieName, dispTempImage)

						# delay between frames and check to see if a key was pressed
						c = cv2.waitKey(timeBetweenFrames)

						# if lower case f is pressed, toggle the display of the frame numbers
						if c == LOWERCASE_F:
							suppressFrameText = not suppressFrameText

						# if the escape key was pressed exit the loops
						if c == ESCAPE_KEY:
							keep_playing = False
							break

				# if this is the last frame, repeat it according to what the user specified
				elif i == lastFrame:

					# display the last frame the number of times specified
					for r in range(0, lastFrameRepeat):
						debug(progName, 're-displaying ' + fn + ' ' + str(r).zfill(3))

						# make a copy of the image so there's a clean copy used to add text each iteration
						dispTempImage = dispImage.copy()

						# check to see whether to suppress the display of frames per second, frame number, and repeat number
						if not suppressFrameText:
							frameText = 'FPS: ' + str(framesPerSecond) + ' Frame: ' + sequence + ' Repeat: ' + str(r).zfill(3)
							cv2.putText(dispTempImage, frameText, TEXT_ORIGIN, cv2.FONT_HERSHEY_SIMPLEX, TEXT_FONT_SCALE, TEXT_COLOR, TEXT_THICKNESS)

						# display the frame
						cv2.imshow(movieName, dispTempImage)

						# delay between frames and check to see if a key was pressed
						c = cv2.waitKey(timeBetweenFrames)

						# if lower case f is pressed, toggle the display of the frame numbers
						if c == LOWERCASE_F:
							suppressFrameText = not suppressFrameText

						# if the escape key was pressed exit the loops
						if c == ESCAPE_KEY:
							keep_playing = False
							break

				# this is not the first or last frame so just display it once
				else:

					# check to see whether to suppress the display of frames per second and the frame number
					if not suppressFrameText:
						frameText = 'FPS: ' + str(framesPerSecond) + ' Frame: ' + sequence
						cv2.putText(dispImage, frameText, TEXT_ORIGIN, cv2.FONT_HERSHEY_SIMPLEX, TEXT_FONT_SCALE, TEXT_COLOR, TEXT_THICKNESS)

					# display the frame
					cv2.imshow(movieName, dispImage)

					# delay between frames and check to see if a key was pressed
					c = cv2.waitKey(timeBetweenFrames)

					# if lower case f is pressed, toggle the display of the frame numbers
					if c == LOWERCASE_F:
						suppressFrameText = not suppressFrameText

					# if the escape key was pressed exit the loops
					if c == ESCAPE_KEY:
						keep_playing = False
						break

			# the frame file does not exist: print an error and exit
			else:
				print "frame file " + fn + " does not exist"
				sys.exit()

	# clean everything up and exit
	cv2.destroyAllWindows()

# the frame count file does not exist: print an error message
else:
	print "can not open frame count file " + fn

debug(progName, 'exiting')
<commit_msg>bug fixes<commit_after># plays stop action movies created by stop-action-record
# v2 adds command line support

import cv2
import sys
import time
import argparse
import os

RBG_GREEN = (0, 255, 0)		# green (red, green, blue)
FILE_TYPE = '.png'			# images will be saved as .png files
COUNT_TYPE = '.count'		# file type for the file containing the image count
TEXT_COLOR = RBG_GREEN		# frame number text color
TEXT_THICKNESS = 1			# frame number text thickness
TEXT_ORIGIN = (10, 25)		# location to place frame number text
TEXT_FONT_SCALE = 0.65		# font size for frame number textpress
DEFAULT_FPS = 10			# default frames per second
ESCAPE_KEY = 27				# ASCII value for the ESC key
LOWERCASE_F = 102 			# ASCII value for 'f'
READ_ONLY = 'r'				# read only parameter for opening files
BACKWARDS = 'backwards'     # text to use in messages about playback sequence
FORWARDS = 'forwards'		# text to use in messages about playback sequence
FIRST_FRAME_REPEAT = 0 		# number of times to repeat the frst frame on playback
LAST_FRAME_REPEAT = 0		# number of times to repeat the last frame on playback

# print debugging messages prefixed by the name of the program
def debug(programName, displayText):
	if printDebugMessages:
		print programName + ':', displayText
	return

# extract the parameters specified on the command line
parser = argparse.ArgumentParser(description='Stop action movie player')
parser.add_argument('moviename',  help='file name of the stop action movie')
parser.add_argument('-f', '--FPS', dest='framesPerSecond', default=DEFAULT_FPS, type=int, help='frames per second')
parser.add_argument('-s', '--suppressframenumbers', dest='suppressFrameText', action='store_true', help='suppress display of frame numbers')
parser.add_argument('-d', '--debug', dest='debugSwitch', action='store_true', help='display debugging messages')
parser.add_argument('-b', '--playbackwards', dest='playBackwards', action='store_true', help='play the movie backwards')
parser.add_argument('-a', '--firstframerepeat', dest='firstFrameRepeat', default=FIRST_FRAME_REPEAT, type=int, help='number of times to repeat the first frame on playback')
parser.add_argument('-z', '--lastframerepeat', dest='lastFrameRepeat', default=LAST_FRAME_REPEAT, type=int, help='number of times to repeat the last frame on playback')
args = parser.parse_args()

# save the values from the command parser
progName = parser.prog.rsplit( ".", 1 )[ 0 ]		# remove the .py from the program name
movieName = args.moviename
framesPerSecond = args.framesPerSecond
printDebugMessages = args.debugSwitch
suppressFrameText = args.suppressFrameText
playBackwards = args.playBackwards
firstFrameRepeat = args.firstFrameRepeat
lastFrameRepeat = args.lastFrameRepeat

# check for invalid frames per second setting
if framesPerSecond < 1:
	print "frames per second must be one or higher"
	sys.exit()

# determine how to play the movie
playSetting = BACKWARDS if playBackwards else FORWARDS

# calculate the delay in millseconds between frames
timeBetweenFrames = int(1000 / framesPerSecond)

# display the command parameters if debug is turned on
debug(progName, 'movie name is ' + movieName)
debug(progName, 'frames per second are ' + str(framesPerSecond))
debug(progName, 'time delay between frame is ' + str(timeBetweenFrames))
debug(progName, 'debug is set to ' + str(printDebugMessages))
debug(progName, 'movie will be played ' + playSetting)
debug(progName, 'first frame will be repeated ' + str(firstFrameRepeat) + ' times')
debug(progName, 'last frame will be repeated ' + str(lastFrameRepeat) + ' times')

# construct the file name for file containing the count of images in the movie
fn = movieName + COUNT_TYPE
debug(progName, 'count file name is ' + fn)

# verify the frame count file exists before trying to open it
if os.path.isfile(fn):
	f = open(fn, READ_ONLY)

	# read the number of frames in the moview
	count = int(f.read())
	debug(progName, 'frame count is ' + str(count))

	# make sure the movie has at least two frames
	if count < 2:
		print "movie must contain at least two frames"
		sys.exit()

	# close the frame count file
	f.close()

	# loop reading and displaying all the frames until the ESC key is pressed
	keep_playing = True

	# create the sequence of frames to play
	playSequence = range(1, count + 1, 1)

	# if play backwards was specified, reverse the play sequence
	if playBackwards:
		playSequence.reverse()

	debug(progName, 'frame play sequence: ' + str(playSequence))

	firstFrame = playSequence[0]							# get the first frame in the sequence specified by the user
	lastFrame = playSequence[-1] 							# get the last frame in the sequence specified by the user

	debug(progName, 'first frame is ' + str(firstFrame))
	debug(progName, 'last frame is ' + str(lastFrame))

	while keep_playing:										# play the movie until the user presses the escape key

		for i in playSequence:								# loop through all the image files
			sequence = str(i).zfill(3)						# construct the image number used in the file name
			fn = movieName + "." + sequence + FILE_TYPE		# construct the file name
			debug(progName, 'displaying ' + fn)

			# verify the frame image file exists before trying to read it
			if os.path.isfile(fn):

				# read the image from the file
				dispImage = cv2.imread(fn, 1)

				# ensure c has a value since some paths do not call waitkey
				c = 0

				# if this is the first frame, repeat it according to what the user specified
				if i == firstFrame:

					# display the first frame the number of times specified
					for r in range(0, firstFrameRepeat):

						debug(progName, 're-displaying ' + fn + ' ' + str(r).zfill(3))

						# make a copy of the image so there's a clean copy used to add text each iteration
						dispTempImage = dispImage.copy()

						# check to see whether to suppress the display of frames per second, frame number, and repeat number
						if not suppressFrameText:
							frameText = 'FPS: ' + str(framesPerSecond) + ' Frame: ' + sequence + ' Repeat: ' + str(r).zfill(3)
							cv2.putText(dispTempImage, frameText, TEXT_ORIGIN, cv2.FONT_HERSHEY_SIMPLEX, TEXT_FONT_SCALE, TEXT_COLOR, TEXT_THICKNESS)

						# display the frame
						cv2.imshow(movieName, dispTempImage)

						# delay between frames and check to see if a key was pressed
						c = cv2.waitKey(timeBetweenFrames)

						# if lower case f is pressed, toggle the display of the frame numbers
						if c == LOWERCASE_F:
							suppressFrameText = not suppressFrameText

						# if the escape key was pressed exit the loops
						if c == ESCAPE_KEY:
							keep_playing = False
							break

				# if this is the last frame, repeat it according to what the user specified
				elif i == lastFrame:

					# display the last frame the number of times specified
					for r in range(0, lastFrameRepeat):
						debug(progName, 're-displaying ' + fn + ' ' + str(r).zfill(3))

						# make a copy of the image so there's a clean copy used to add text each iteration
						dispTempImage = dispImage.copy()

						# check to see whether to suppress the display of frames per second, frame number, and repeat number
						if not suppressFrameText:
							frameText = 'FPS: ' + str(framesPerSecond) + ' Frame: ' + sequence + ' Repeat: ' + str(r).zfill(3)
							cv2.putText(dispTempImage, frameText, TEXT_ORIGIN, cv2.FONT_HERSHEY_SIMPLEX, TEXT_FONT_SCALE, TEXT_COLOR, TEXT_THICKNESS)

						# display the frame
						cv2.imshow(movieName, dispTempImage)

						# delay between frames and check to see if a key was pressed
						c = cv2.waitKey(timeBetweenFrames)

						# if lower case f is pressed, toggle the display of the frame numbers
						if c == LOWERCASE_F:
							suppressFrameText = not suppressFrameText

						# if the escape key was pressed exit the loops
						if c == ESCAPE_KEY:
							keep_playing = False
							break

				# this is not the first or last frame so just display it once
				else:

					# check to see whether to suppress the display of frames per second and the frame number
					if not suppressFrameText:
						frameText = 'FPS: ' + str(framesPerSecond) + ' Frame: ' + sequence
						cv2.putText(dispImage, frameText, TEXT_ORIGIN, cv2.FONT_HERSHEY_SIMPLEX, TEXT_FONT_SCALE, TEXT_COLOR, TEXT_THICKNESS)

					# display the frame
					cv2.imshow(movieName, dispImage)

					# delay between frames and check to see if a key was pressed
					c = cv2.waitKey(timeBetweenFrames)

					# if lower case f is pressed, toggle the display of the frame numbers
					if c == LOWERCASE_F:
						suppressFrameText = not suppressFrameText

					# if the escape key was pressed exit the loops
					if c == ESCAPE_KEY:
						keep_playing = False
						break

			# the frame file does not exist: print an error and exit
			else:
				print "frame file " + fn + " does not exist"
				sys.exit()

	# clean everything up and exit
	cv2.destroyAllWindows()

# the frame count file does not exist: print an error message
else:
	print "can not open frame count file " + fn

debug(progName, 'exiting')
<|endoftext|>


<commit_before>"""A collection of tools to handle genomic tests.
Part of the structmap package.
"""
from __future__ import absolute_import, division, print_function

import dendropy
from structmap.seqtools import (_var_site, _join_alignments,
                                _sliding_window_var_sites)

def tajimas_d(alignment, window=None, step=3):
    """
    Use DendroPy package to calculate Tajimas D.
    Several optimisations performed to speed up the calculation
    Input needs to be a string representing multiple sequence alignments in
    fasta format.
    Output is Tajima's D value.
    """
    if window:
        results = {}
        prev_win = None
        prev_d = None
        slide = _sliding_window_var_sites(alignment, window, step=step,
                                          isfile=False)
        for i, win in enumerate(slide):
            centre = i*step + 1 + (window-1)/2
            if win == prev_win:
                results[centre] = prev_d
            else:
                current_d = _tajimas_d(win)
                results[centre] = current_d
                prev_d = current_d
                prev_win = win
        return results
    else:
        #Generate alignment containing only polymorphic sites
        alignment = _join_alignments(_var_site(alignment))
        return _tajimas_d(alignment)

def _tajimas_d(alignment):
    """
    Use DendroPy to calculate tajimas D.
    """
    if not alignment or len(alignment[0]) == 0:
        return None
    try:
        seq = dendropy.DnaCharacterMatrix.get(data=alignment.format('fasta'),
                                              schema='fasta')
        taj_d = dendropy.calculate.popgenstat.tajimas_d(seq)
    except ZeroDivisionError:
        taj_d = None
    return taj_d
<commit_msg>No need to optimise taj D calculation if dendropy is optimised<commit_after>"""A collection of tools to handle genomic tests.
Part of the structmap package.
"""
from __future__ import absolute_import, division, print_function

import dendropy
from structmap.seqtools import (_var_site, _join_alignments,
                                _sliding_window_var_sites)

def tajimas_d(alignment, window=None, step=3):
    """
    Use DendroPy package to calculate Tajimas D.
    Several optimisations performed to speed up the calculation
    Input needs to be a string representing multiple sequence alignments in
    fasta format.
    Output is Tajima's D value.
    """
    if window:
        results = {}
        prev_win = None
        prev_d = None
        slide = _sliding_window_var_sites(alignment, window, step=step,
                                          isfile=False)
        for i, win in enumerate(slide):
            centre = i*step + 1 + (window-1)/2
            if win == prev_win:
                results[centre] = prev_d
            else:
                current_d = _tajimas_d(win)
                results[centre] = current_d
                prev_d = current_d
                prev_win = win
        return results
    else:
        return _tajimas_d(alignment)

def _tajimas_d(alignment):
    """
    Use DendroPy to calculate tajimas D.
    """
    if not alignment or len(alignment[0]) == 0:
        return None
    try:
        seq = dendropy.DnaCharacterMatrix.get(data=alignment.format('fasta'),
                                              schema='fasta')
        taj_d = dendropy.calculate.popgenstat.tajimas_d(seq)
    except ZeroDivisionError:
        taj_d = None
    return taj_d
<|endoftext|>