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

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

# pylint: disable=wrong-import-order

"""Main Qiskit public functionality."""

import pkgutil
import warnings

# First, check for required Python and API version
from . import util

# qiskit errors operator
from .exceptions import QiskitError

# The main qiskit operators
from qiskit.circuit import ClassicalRegister
from qiskit.circuit import QuantumRegister
from qiskit.circuit import QuantumCircuit
from qiskit.execute import execute
from qiskit.compiler import transpile, assemble

# The qiskit.extensions.x imports needs to be placed here due to the
# mechanism for adding gates dynamically.
import qiskit.extensions
import qiskit.circuit.measure
import qiskit.circuit.reset

# Allow extending this namespace. Please note that currently this line needs
# to be placed *before* the wrapper imports or any non-import code AND *before*
# importing the package you want to allow extensions for (in this case `backends`).
__path__ = pkgutil.extend_path(__path__, __name__)

# Please note these are global instances, not modules.
from qiskit.providers.basicaer import BasicAer

# Try to import the Aer provider if installed.
try:
    from qiskit.providers.aer import Aer
except ImportError:
    warnings.warn('Could not import the Aer provider from the qiskit-aer '
                  'package. Install qiskit-aer or check your installation.',
                  ImportWarning)
# Try to import the IBMQ provider if installed.
try:
    from qiskit.providers.ibmq import IBMQ
except ImportError:
    warnings.warn('Could not import the IBMQ provider from the '
                  'qiskit-ibmq-provider package. Install qiskit-ibmq-provider '
                  'or check your installation.',
                  ImportWarning)

from .version import __version__
from .version import __qiskit_version__
<commit_msg>Change warning class for Aer and IBMQ warning (#2977)<commit_after># -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

# pylint: disable=wrong-import-order

"""Main Qiskit public functionality."""

import pkgutil
import warnings

# First, check for required Python and API version
from . import util

# qiskit errors operator
from .exceptions import QiskitError

# The main qiskit operators
from qiskit.circuit import ClassicalRegister
from qiskit.circuit import QuantumRegister
from qiskit.circuit import QuantumCircuit
from qiskit.execute import execute
from qiskit.compiler import transpile, assemble

# The qiskit.extensions.x imports needs to be placed here due to the
# mechanism for adding gates dynamically.
import qiskit.extensions
import qiskit.circuit.measure
import qiskit.circuit.reset

# Allow extending this namespace. Please note that currently this line needs
# to be placed *before* the wrapper imports or any non-import code AND *before*
# importing the package you want to allow extensions for (in this case `backends`).
__path__ = pkgutil.extend_path(__path__, __name__)

# Please note these are global instances, not modules.
from qiskit.providers.basicaer import BasicAer

# Try to import the Aer provider if installed.
try:
    from qiskit.providers.aer import Aer
except ImportError:
    warnings.warn('Could not import the Aer provider from the qiskit-aer '
                  'package. Install qiskit-aer or check your installation.',
                  RuntimeWarning)
# Try to import the IBMQ provider if installed.
try:
    from qiskit.providers.ibmq import IBMQ
except ImportError:
    warnings.warn('Could not import the IBMQ provider from the '
                  'qiskit-ibmq-provider package. Install qiskit-ibmq-provider '
                  'or check your installation.',
                  RuntimeWarning)

from .version import __version__
from .version import __qiskit_version__
<|endoftext|>


<commit_before># -*- encoding: utf8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2017 Wojtek Porczyk <woju@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

import qubes.api
import qubes.ext

class AdminExtension(qubes.ext.Extension):
    # pylint: disable=too-few-public-methods
    @qubes.ext.handler(
        'mgmt-permission:admin.vm.tag.Set',
        'mgmt-permission:admin.vm.tag.Remove')
    def on_tag_set_or_remove(self, vm, event, arg, **kwargs):
        '''Forbid changing specific tags'''
        # pylint: disable=no-self-use,unused-argument
        if arg.startswith('created-by-'):
            raise qubes.api.PermissionDenied()

    # TODO create that extension in the first place
<commit_msg>ext/admin: add explanation to PermissionDenied<commit_after># -*- encoding: utf8 -*-
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2017 Wojtek Porczyk <woju@invisiblethingslab.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, see <http://www.gnu.org/licenses/>.

import qubes.api
import qubes.ext

class AdminExtension(qubes.ext.Extension):
    # pylint: disable=too-few-public-methods
    @qubes.ext.handler(
        'mgmt-permission:admin.vm.tag.Set',
        'mgmt-permission:admin.vm.tag.Remove')
    def on_tag_set_or_remove(self, vm, event, arg, **kwargs):
        '''Forbid changing specific tags'''
        # pylint: disable=no-self-use,unused-argument
        if arg.startswith('created-by-'):
            raise qubes.api.PermissionDenied(
                'changing this tag is prohibited by {}.{}'.format(
                    __name__, type(self).__name__))

    # TODO create that tag here (need to figure out how to pass mgmtvm name)
<|endoftext|>


<commit_before>"""The Session class allows for a unified (and simplified) view of
interfacing with a PostgreSQL database server.

Connection details are passed in as a PostgreSQL URI and connections are pooled
by default, allowing for reuse of connections across modules in the Python
runtime without having to pass around the object handle.

While you can still access the raw `psycopg2` connection and cursor objects to
provide ultimate flexibility in how you use the queries.Session object, there
are convenience methods designed to simplify the interaction with PostgreSQL.
For `psycopg2` functionality outside of what is exposed in Session, simply
use the Session.connection or Session.cursor properties to gain access to
either object just as you would in a program using psycopg2 directly.

"""
import contextlib
import logging

import psycopg2
from psycopg2 import extensions
from psycopg2 import extras

from queries import pool
from queries import utils

LOGGER = logging.getLogger(__name__)

from queries import DEFAULT_URI
from queries import PYPY

DEFAULT_ENCODING = 'UTF8'

class Session(object):
    """The Session class allows for a unified (and simplified) view of
    interfacing with a PostgreSQL database server. The Session object can
    act as a context manager, providing automated cleanup and simple, pythoic
    way of interacting with the object:

    .. code:: python

        import queries

        with queries.Session('pgsql://postgres@localhost/postgres') as session:
            for row in session.Query('SELECT * FROM table'):
                print row

    :param str uri: PostgreSQL connection URI
    :param psycopg2.cursor: The cursor type to use
    :param bool use_pool: Use the connection pool

    """
    _from_pool = False
    _tpc_id = None

    # Connection status constants
    INTRANS = extensions.STATUS_IN_TRANSACTION
    PREPARED = extensions.STATUS_PREPARED
    READY = extensions.STATUS_READY

    # Transaction status constants
    TX_ACTIVE = extensions.TRANSACTION_STATUS_ACTIVE
    TX_IDLE = extensions.TRANSACTION_STATUS_IDLE
    TX_INERROR = extensions.TRANSACTION_STATUS_INERROR
    TX_INTRANS = extensions.TRANSACTION_STATUS_INTRANS
    TX_UNKNOWN = extensions.TRANSACTION_STATUS_UNKNOWN

    def __init__(self, uri=DEFAULT_URI,
                 cursor_factory=extras.RealDictCursor,
                 use_pool=True):
        """Connect to a PostgreSQL server using the module wide connection and
        set the isolation level.

        :param str uri: PostgreSQL connection URI
        :param psycopg2.cursor: The cursor type to use
        :param bool use_pool: Use the connection pool

        """
        self._uri = uri
        self._use_pool = use_pool
        self._conn = self._connect()
        self._cursor = self._get_cursor(cursor_factory)
        self._autocommit()

    def __del__(self):
        """When deleting the context, ensure the instance is removed from
        caches, etc.

        """
        #self._cleanup()
        pass

    def __enter__(self):
        """For use as a context manager, return a handle to this object
        instance.

        :rtype: PgSQL

        """
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """When leaving the context, ensure the instance is removed from
        caches, etc.

        """
        #self._cleanup()
        pass

    @property
    def backend_pid(self):
        """Return the backend process ID of the PostgreSQL server that this
        session is connected to.

        :rtype: int

        """
        return self._conn.get_backend_pid()

    def close(self):
        """Explicitly close the connection and remove it from the connection
        pool if pooling is enabled.

        :raises: AssertionError

        """
        if not self._conn:
            raise AssertionError('Connection not open')
        self._conn.close()
        if self._use_pool:
            pool.remove_connection(self._uri)
        self._conn = None
        self._cursor = None

    @property
    def connection(self):
        """Returns the psycopg2 PostgreSQL connection instance

        :rtype: psycopg2.connection

        """
        return self._conn

    @property
    def cursor(self):
        """Returns the cursor instance

        :rtype: psycopg2._psycopg.cursor

        """
        return self._cursor

    @property
    def encoding(self):
        """The current client encoding value.

        :rtype: str

        """
        return self._conn.encoding

    @property
    def notices(self):
        """A list of up to the last 50 server notices sent to the client.

        :rtype: list

        """
        return self._conn.notices

    def set_encoding(self, value=DEFAULT_ENCODING):
        """Set the client encoding for the session if the value specified
        is different than the current client encoding.

        :param str value: The encoding value to use

        """
        if self._conn.encoding != value:
            self._conn.set_client_encoding(value)

    @property
    def status(self):
        """Return the current connection status as an integer value.

        The status should match one of the following constants:

        - queries.Session.INTRANS: Connection established, in transaction
        - queries.Session.PREPARED: Prepared for second phase of transaction
        - queries.Session.READY: Connected, no active transaction

        :rtype: int

        """
        if self._conn.status == psycopg2.extensions.STATUS_BEGIN:
            return self.READY
        return self._conn.status

    # Querying, executing, copying, etc

    def callproc(self, name, parameters=None):
        """Call a stored procedure on the server and return an iterator of the
        result set for easy access to the data.

        .. code:: python

            for row in session.callproc('now'):
                print row

        :param str name: The procedure name
        :param list parameters: The list of parameters to pass in
        :return: iterator

        """
        self._cursor.callproc(name, parameters)
        for record in self._cursor:
            yield record

    def callproc_all(self, name, parameters=None):
        """Call a stored procedure on the server returning all of the rows
        returned by the server.

        :rtype: list

        """
        self._cursor.callproc(name, parameters)
        return self._cursor.fetchall()

    def query(self, sql, parameters=None):
        """A generator to issue a query on the server, mogrifying the
        parameters against the sql statement and returning the results as an
        iterator.

        .. code:: python

            for row in session.query('SELECT * FROM foo WHERE bar=%(bar)s',
                                     {'bar': 'baz'}):
              print row

        :param str sql: The SQL statement
        :param dict parameters: A dictionary of query parameters
        :rtype: iterator

        """
        self._cursor.execute(sql, parameters)
        for record in self._cursor:
            yield record

    def query_all(self, sql, parameters=None):
        """Issue a query on the server mogrifying the parameters against the
        sql statement and returning the entire result set as a list.

        :param str sql: The SQL statement
        :param dict parameters: A dictionary of query parameters
        :rtype: list

        """
        self._cursor.execute(sql, parameters or {})
        return self._cursor.fetchall()

    # Listen Notify

    def listen(self, channel, callback=None):
        pass

    def notifications(self):
        pass

    # TPC Transaction Functionality

    def tx_begin(self):
        """Begin a new transaction"""
        # Ensure that auto-commit is off
        if self._conn.autocommit:
            self._conn.autocommit = False

    def tx_commit(self):
        self._conn.commit()

    def tx_rollback(self):
        self._conn.rollback()

    @property
    def tx_status(self):
        """Return the transaction status for the current connection.

        Values should be one of:

        - queries.Session.TX_IDLE: Idle without an active session
        - queries.Session.TX_ACTIVE: A command is currently in progress
        - queries.Session.TX_INTRANS: Idle in a valid transaction
        - queries.Session.TX_INERROR: Idle in a failed transaction
        - queries.Session.TX_UNKNOWN: Connection error

        :rtype: int

        """
        return self._conn.get_transaction_status()

    # Internal methods

    def _autocommit(self):
        """Set the isolation level automatically to commit after every query"""
        self._conn.autocommit = True

    def _cleanup(self):
        """Remove the connection from the stack, closing out the cursor"""
        if self._cursor:
            self._cursor.close()
            self._cursor = None
        if self._conn:
            pool.free_connection(self._uri)
            self._conn = None

    def _connect(self):
        """Connect to PostgreSQL, either by reusing a connection from the pool
        if possible, or by creating the new connection.

        :rtype: psycopg2.connection

        """
        # Attempt to get a cached connection from the connection pool
        if self._use_pool:
            connection = pool.get_connection(self._uri)
            if connection:
                self._from_pool = True
                return connection

        # Create a new PostgreSQL connection
        LOGGER.debug('Connection KWARGS: %r', utils.uri_to_kwargs(self._uri))
        connection = psycopg2.connect(**utils.uri_to_kwargs(self._uri))

        # Add it to the pool, if pooling is enabled
        if self._use_pool:
            pool.add_connection(self._uri, connection)

        # Added in because psycopg2ct connects and leaves the connection in
        # a weird state: consts.STATUS_DATESTYLE, returning from
        # Connection._setup without setting the state as const.STATUS_OK
        if PYPY:
            connection.reset()

        # Register the custom data types
        self._register_json(connection)
        self._register_unicode(connection)
        self._register_uuid(connection)

        return connection

    def _get_cursor(self, cursor_factory):
        """Return a cursor for the given cursor_factory.

        :param psycopg2.cursor: The cursor type to use
        :rtype: psycopg2.extensions.cursor

        """
        return self._conn.cursor(cursor_factory=cursor_factory)

    @staticmethod
    def _register_json(connection):
        """Register the JSON extension from the psycopg2.extras module

        :param psycopg2.connection connection: The connection to register on

        """
        psycopg2.extras.register_json(conn_or_curs=connection)

    @staticmethod
    def _register_unicode(connection):
        """Register the cursor to be able to receive Unicode string.

        :param psycopg2.connection connection: The connection to register on

        """
        psycopg2.extensions.register_type(psycopg2.extensions.UNICODE,
                                          connection)
        psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY,
                                          connection)

    @staticmethod
    def _register_uuid(connection):
        """Register the UUID extension from the psycopg2.extra module

        :param psycopg2.connection connection: The connection to register on

        """
        psycopg2.extras.register_uuid(conn_or_curs=connection)
<commit_msg>Move cleanup back after finding issue that they were commented out for<commit_after>"""The Session class allows for a unified (and simplified) view of
interfacing with a PostgreSQL database server.

Connection details are passed in as a PostgreSQL URI and connections are pooled
by default, allowing for reuse of connections across modules in the Python
runtime without having to pass around the object handle.

While you can still access the raw `psycopg2` connection and cursor objects to
provide ultimate flexibility in how you use the queries.Session object, there
are convenience methods designed to simplify the interaction with PostgreSQL.
For `psycopg2` functionality outside of what is exposed in Session, simply
use the Session.connection or Session.cursor properties to gain access to
either object just as you would in a program using psycopg2 directly.

"""
import contextlib
import logging

import psycopg2
from psycopg2 import extensions
from psycopg2 import extras

from queries import pool
from queries import utils

LOGGER = logging.getLogger(__name__)

from queries import DEFAULT_URI
from queries import PYPY

DEFAULT_ENCODING = 'UTF8'

class Session(object):
    """The Session class allows for a unified (and simplified) view of
    interfacing with a PostgreSQL database server. The Session object can
    act as a context manager, providing automated cleanup and simple, pythoic
    way of interacting with the object:

    .. code:: python

        import queries

        with queries.Session('pgsql://postgres@localhost/postgres') as session:
            for row in session.Query('SELECT * FROM table'):
                print row

    :param str uri: PostgreSQL connection URI
    :param psycopg2.cursor: The cursor type to use
    :param bool use_pool: Use the connection pool

    """
    _from_pool = False
    _tpc_id = None

    # Connection status constants
    INTRANS = extensions.STATUS_IN_TRANSACTION
    PREPARED = extensions.STATUS_PREPARED
    READY = extensions.STATUS_READY

    # Transaction status constants
    TX_ACTIVE = extensions.TRANSACTION_STATUS_ACTIVE
    TX_IDLE = extensions.TRANSACTION_STATUS_IDLE
    TX_INERROR = extensions.TRANSACTION_STATUS_INERROR
    TX_INTRANS = extensions.TRANSACTION_STATUS_INTRANS
    TX_UNKNOWN = extensions.TRANSACTION_STATUS_UNKNOWN

    def __init__(self, uri=DEFAULT_URI,
                 cursor_factory=extras.RealDictCursor,
                 use_pool=True):
        """Connect to a PostgreSQL server using the module wide connection and
        set the isolation level.

        :param str uri: PostgreSQL connection URI
        :param psycopg2.cursor: The cursor type to use
        :param bool use_pool: Use the connection pool

        """
        self._uri = uri
        self._use_pool = use_pool
        self._conn = self._connect()
        self._cursor = self._get_cursor(cursor_factory)
        self._autocommit()

    def __del__(self):
        """When deleting the context, ensure the instance is removed from
        caches, etc.

        """
        self._cleanup()

    def __enter__(self):
        """For use as a context manager, return a handle to this object
        instance.

        :rtype: PgSQL

        """
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """When leaving the context, ensure the instance is removed from
        caches, etc.

        """
        self._cleanup()

    @property
    def backend_pid(self):
        """Return the backend process ID of the PostgreSQL server that this
        session is connected to.

        :rtype: int

        """
        return self._conn.get_backend_pid()

    def close(self):
        """Explicitly close the connection and remove it from the connection
        pool if pooling is enabled.

        :raises: AssertionError

        """
        if not self._conn:
            raise AssertionError('Connection not open')
        self._conn.close()
        if self._use_pool:
            pool.remove_connection(self._uri)
        self._conn = None
        self._cursor = None

    @property
    def connection(self):
        """Returns the psycopg2 PostgreSQL connection instance

        :rtype: psycopg2.connection

        """
        return self._conn

    @property
    def cursor(self):
        """Returns the cursor instance

        :rtype: psycopg2._psycopg.cursor

        """
        return self._cursor

    @property
    def encoding(self):
        """The current client encoding value.

        :rtype: str

        """
        return self._conn.encoding

    @property
    def notices(self):
        """A list of up to the last 50 server notices sent to the client.

        :rtype: list

        """
        return self._conn.notices

    def set_encoding(self, value=DEFAULT_ENCODING):
        """Set the client encoding for the session if the value specified
        is different than the current client encoding.

        :param str value: The encoding value to use

        """
        if self._conn.encoding != value:
            self._conn.set_client_encoding(value)

    @property
    def status(self):
        """Return the current connection status as an integer value.

        The status should match one of the following constants:

        - queries.Session.INTRANS: Connection established, in transaction
        - queries.Session.PREPARED: Prepared for second phase of transaction
        - queries.Session.READY: Connected, no active transaction

        :rtype: int

        """
        if self._conn.status == psycopg2.extensions.STATUS_BEGIN:
            return self.READY
        return self._conn.status

    # Querying, executing, copying, etc

    def callproc(self, name, parameters=None):
        """Call a stored procedure on the server and return an iterator of the
        result set for easy access to the data.

        .. code:: python

            for row in session.callproc('now'):
                print row

        :param str name: The procedure name
        :param list parameters: The list of parameters to pass in
        :return: iterator

        """
        self._cursor.callproc(name, parameters)
        for record in self._cursor:
            yield record

    def callproc_all(self, name, parameters=None):
        """Call a stored procedure on the server returning all of the rows
        returned by the server.

        :rtype: list

        """
        self._cursor.callproc(name, parameters)
        return self._cursor.fetchall()

    def query(self, sql, parameters=None):
        """A generator to issue a query on the server, mogrifying the
        parameters against the sql statement and returning the results as an
        iterator.

        .. code:: python

            for row in session.query('SELECT * FROM foo WHERE bar=%(bar)s',
                                     {'bar': 'baz'}):
              print row

        :param str sql: The SQL statement
        :param dict parameters: A dictionary of query parameters
        :rtype: iterator

        """
        self._cursor.execute(sql, parameters)
        for record in self._cursor:
            yield record

    def query_all(self, sql, parameters=None):
        """Issue a query on the server mogrifying the parameters against the
        sql statement and returning the entire result set as a list.

        :param str sql: The SQL statement
        :param dict parameters: A dictionary of query parameters
        :rtype: list

        """
        self._cursor.execute(sql, parameters or {})
        return self._cursor.fetchall()

    # Listen Notify

    def listen(self, channel, callback=None):
        pass

    def notifications(self):
        pass

    # TPC Transaction Functionality

    def tx_begin(self):
        """Begin a new transaction"""
        # Ensure that auto-commit is off
        if self._conn.autocommit:
            self._conn.autocommit = False

    def tx_commit(self):
        self._conn.commit()

    def tx_rollback(self):
        self._conn.rollback()

    @property
    def tx_status(self):
        """Return the transaction status for the current connection.

        Values should be one of:

        - queries.Session.TX_IDLE: Idle without an active session
        - queries.Session.TX_ACTIVE: A command is currently in progress
        - queries.Session.TX_INTRANS: Idle in a valid transaction
        - queries.Session.TX_INERROR: Idle in a failed transaction
        - queries.Session.TX_UNKNOWN: Connection error

        :rtype: int

        """
        return self._conn.get_transaction_status()

    # Internal methods

    def _autocommit(self):
        """Set the isolation level automatically to commit after every query"""
        self._conn.autocommit = True

    def _cleanup(self):
        """Remove the connection from the stack, closing out the cursor"""
        if self._cursor:
            self._cursor.close()
            self._cursor = None
        if self._conn:
            pool.free_connection(self._uri)
            self._conn = None

    def _connect(self):
        """Connect to PostgreSQL, either by reusing a connection from the pool
        if possible, or by creating the new connection.

        :rtype: psycopg2.connection

        """
        # Attempt to get a cached connection from the connection pool
        if self._use_pool:
            connection = pool.get_connection(self._uri)
            if connection:
                self._from_pool = True
                return connection

        # Create a new PostgreSQL connection
        LOGGER.debug('Connection KWARGS: %r', utils.uri_to_kwargs(self._uri))
        connection = psycopg2.connect(**utils.uri_to_kwargs(self._uri))

        # Add it to the pool, if pooling is enabled
        if self._use_pool:
            pool.add_connection(self._uri, connection)

        # Added in because psycopg2ct connects and leaves the connection in
        # a weird state: consts.STATUS_DATESTYLE, returning from
        # Connection._setup without setting the state as const.STATUS_OK
        if PYPY:
            connection.reset()

        # Register the custom data types
        self._register_json(connection)
        self._register_unicode(connection)
        self._register_uuid(connection)

        return connection

    def _get_cursor(self, cursor_factory):
        """Return a cursor for the given cursor_factory.

        :param psycopg2.cursor: The cursor type to use
        :rtype: psycopg2.extensions.cursor

        """
        return self._conn.cursor(cursor_factory=cursor_factory)

    @staticmethod
    def _register_json(connection):
        """Register the JSON extension from the psycopg2.extras module

        :param psycopg2.connection connection: The connection to register on

        """
        psycopg2.extras.register_json(conn_or_curs=connection)

    @staticmethod
    def _register_unicode(connection):
        """Register the cursor to be able to receive Unicode string.

        :param psycopg2.connection connection: The connection to register on

        """
        psycopg2.extensions.register_type(psycopg2.extensions.UNICODE,
                                          connection)
        psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY,
                                          connection)

    @staticmethod
    def _register_uuid(connection):
        """Register the UUID extension from the psycopg2.extra module

        :param psycopg2.connection connection: The connection to register on

        """
        psycopg2.extras.register_uuid(conn_or_curs=connection)
<|endoftext|>


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

from __future__ import print_function

# stdlib
import string
import tempfile
import shutil

# installed:
from sh import svn

class MultipleMatchException(Exception):
    pass

class Subversion(object):
    '''
    This class encapsulates interaction with Subversion
    '''

    def __init__(self, config):
        self.config = config
        self.strippers = ''.join(['/', string.whitespace])

    def get_branches(self):
        '''
        Returns a list of branches in the SVN repo based on the 'branch_url'
        given in the configuration file.
        '''

        cmd = svn.ls(self.config['branch_url'])
        return [x.rstrip(self.strippers) for x in cmd]

    def get_unique_branch(self, search_string):
        '''
        Given a search string attempts to find one branch that contains the
        string in it's name. If more than one branch matches then an exception
        is raised.
        '''

        branches = self.get_branches()
        branch = [x.rstrip(self.strippers)
                for x in branches if search_string in x]
        if len(branch) > 1:
            raise MultipleMatchException('more than one branch matches "{}"')

        return branch[0]

    def diff(self, branch):

        trunk = self.config['trunk_url']
        branch = '/'.join([self.config['branch_url'], branch])
        # if filterdiff exists, pipe diff through it to clean up parts that
        # Crucible doesn't like
        try:
            from sh import filterdiff
            proc = filterdiff(svn.diff(trunk, branch, diff_cmd='diff', x='-U 300 -a'), clean=True)

        # if there's no filterdiff then hope for the best:
        except CommandNotFound:
            proc = svn.diff(trunk, branch, diff_cmd='diff', x='-U 300 -a')
        return proc.stdout

    def reintegrate(self, branch):
        #TODO: pass commit message as param

        trunk_url = self.config['trunk_url']
        branch_url = '/'.join([self.config['branch_url'], branch])
        # checkout trunk
        working_dir = tempfile.mkdtemp()
        svn.co(trunk_url, working_dir)
        # merge
        svn.merge(branch_url, working_dir, reintegrate=True)
        # commit
        svn.commit(m='reintegrating into trunk', _cwd=working_dir)

        #shutil.rmtree(working_dir)

    def make_branch(self, name, commit_msg):

        src = self.config['trunk_url']
        dest = '{}/{}'.format(self.config['branch_url'], name)

        process = svn.copy(src, dest, m=commit_msg)
        return process
<commit_msg>importing CommandNotFound<commit_after>#!/usr/bin/env python

from __future__ import print_function

# stdlib
import string
import tempfile
import shutil

# installed:
from sh import svn
from sh import CommandNotFound

class MultipleMatchException(Exception):
    pass

class Subversion(object):
    '''
    This class encapsulates interaction with Subversion
    '''

    def __init__(self, config):
        self.config = config
        self.strippers = ''.join(['/', string.whitespace])

    def get_branches(self):
        '''
        Returns a list of branches in the SVN repo based on the 'branch_url'
        given in the configuration file.
        '''

        cmd = svn.ls(self.config['branch_url'])
        return [x.rstrip(self.strippers) for x in cmd]

    def get_unique_branch(self, search_string):
        '''
        Given a search string attempts to find one branch that contains the
        string in it's name. If more than one branch matches then an exception
        is raised.
        '''

        branches = self.get_branches()
        branch = [x.rstrip(self.strippers)
                for x in branches if search_string in x]
        if len(branch) > 1:
            raise MultipleMatchException('more than one branch matches "{}"')

        return branch[0]

    def diff(self, branch):

        trunk = self.config['trunk_url']
        branch = '/'.join([self.config['branch_url'], branch])
        # if filterdiff exists, pipe diff through it to clean up parts that
        # Crucible doesn't like
        try:
            from sh import filterdiff
            proc = filterdiff(svn.diff(trunk, branch, diff_cmd='diff', x='-U 300 -a'), clean=True)

        # if there's no filterdiff then hope for the best:
        except CommandNotFound:
            proc = svn.diff(trunk, branch, diff_cmd='diff', x='-U 300 -a')
        return proc.stdout

    def reintegrate(self, branch):
        #TODO: pass commit message as param

        trunk_url = self.config['trunk_url']
        branch_url = '/'.join([self.config['branch_url'], branch])
        # checkout trunk
        working_dir = tempfile.mkdtemp()
        svn.co(trunk_url, working_dir)
        # merge
        svn.merge(branch_url, working_dir, reintegrate=True)
        # commit
        svn.commit(m='reintegrating into trunk', _cwd=working_dir)

        #shutil.rmtree(working_dir)

    def make_branch(self, name, commit_msg):

        src = self.config['trunk_url']
        dest = '{}/{}'.format(self.config['branch_url'], name)

        process = svn.copy(src, dest, m=commit_msg)
        return process
<|endoftext|>


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

import os
import subprocess
import sys
import uuid

if __name__ == '__main__':
    dir_name = sys.argv[1]

    for file_name in os.listdir(dir_name):
        rand_name = uuid.uuid4().hex
        src = os.path.join(dir_name, file_name)
        subprocess.check_call(['eyeD3', '--artist', rand_name, '--album', rand_name, src])

        os.rename(src, os.path.join(dir_name, '{} {}'.format(rand_name, file_name)))

<commit_msg>Generalize randomize script to work recursively and on more than just music<commit_after>#!/usr/bin/env python

import os
import subprocess
import sys
import uuid

if __name__ == '__main__':
    dir_name = sys.argv[1]

    for root, dirs, files in os.walk(dir_name):
        for file_name in files:
            rand_name = uuid.uuid4().hex
            src = os.path.join(root, file_name)
            if src.endswith('.mp3'):
                subprocess.check_call(['eyeD3', '--artist', rand_name, '--album', rand_name, src])

            os.rename(src, os.path.join(root, '{} {}'.format(rand_name, file_name)))

<|endoftext|>


<commit_before>import logging

import argparse
from typing import List, Text, Optional

import rasa.cli.utils as cli_utils
import rasa.core.utils as rasa_core_utils
from rasa.cli.arguments import export as arguments
from rasa.core.brokers.broker import EventBroker
from rasa.core.brokers.pika import PikaEventBroker
from rasa.core.migrator import Migrator
from rasa.core.tracker_store import TrackerStore
from rasa.core.utils import AvailableEndpoints
from rasa.exceptions import (
    PublishingError,
    RasaException,
)

logger = logging.getLogger(__name__)

# noinspection PyProtectedMember
def add_subparser(
    subparsers: argparse._SubParsersAction, parents: List[argparse.ArgumentParser]
) -> None:
    export_parser_args = {
        "parents": parents,
        "conflict_handler": "resolve",
        "formatter_class": argparse.ArgumentDefaultsHelpFormatter,
        "help": "Export Rasa trackers using an event broker.",
    }

    shell_parser = subparsers.add_parser("export", **export_parser_args)
    shell_parser.set_defaults(func=export_trackers)

    arguments.set_export_arguments(shell_parser)

def _get_tracker_store(endpoints: AvailableEndpoints) -> TrackerStore:
    """Get tracker store from `endpoints`.

    Prints an error and exits if no tracker store could be loaded.

    Args:
        endpoints: `AvailableEndpoints` to initialize the tracker store from.

    Returns:
        Initialized tracker store.

    """
    if not endpoints.tracker_store:
        cli_utils.print_error_and_exit(
            "Could not find a `tracker_store` section in the supplied "
            "endpoints file. Exiting."
        )

    return TrackerStore.create(endpoints.tracker_store)

def _get_event_broker(endpoints: AvailableEndpoints) -> Optional[EventBroker]:
    """Get event broker from `endpoints`.

    Prints an error and exits if no event broker could be loaded.

    Args:
        endpoints: `AvailableEndpoints` to initialize the event broker from.

    Returns:
        Initialized event broker.

    """
    if not endpoints.event_broker:
        cli_utils.print_error_and_exit(
            "Could not find an `event_broker` section in the supplied "
            "endpoints file. Exiting."
        )

    return EventBroker.create(endpoints.event_broker)

def _get_requested_conversation_ids(
    conversation_ids_arg: Optional[Text] = None,
) -> Optional[List[Text]]:
    """Get list of conversation IDs requested as a command-line argument.

    Args:
        conversation_ids_arg: Value of `--conversation-ids` command-line argument.
            If provided, this is a string of comma-separated conversation IDs.

    Return:
        List of conversation IDs requested as a command-line argument.
        `None` if that argument was left unspecified.

    """
    if not conversation_ids_arg:
        return None

    return conversation_ids_arg.split(",")

def _validate_timestamp_options(args: argparse.Namespace) -> None:
    """Inspect CLI timestamp parameters.

    Prints an error and exits if a maximum timestamp is provided that is smaller
    than the provided minimum timestamp.

    Args:
        args: Command-line arguments to process.

    """
    min_timestamp = args.minimum_timestamp
    max_timestamp = args.maximum_timestamp

    if (
        min_timestamp is not None
        and max_timestamp is not None
        and max_timestamp < min_timestamp
    ):
        cli_utils.print_error_and_exit(
            f"Maximum timestamp '{max_timestamp}' is smaller than minimum "
            f"timestamp '{min_timestamp}'. Exiting."
        )

def _prepare_event_broker(event_broker: EventBroker) -> None:
    """Sets `should_keep_unpublished_messages` flag to `False` if
    `self.event_broker` is a `PikaEventBroker`.

    If publishing of events fails, the `PikaEventBroker` instance should not keep a
    list of unpublished messages, so we can retry publishing them. This is because
    the instance is launched as part of this short-lived export script, meaning the
    object is destroyed before it might be published.

    In addition, wait until the event broker reports a `ready` state.

    """
    if isinstance(event_broker, PikaEventBroker):
        event_broker.should_keep_unpublished_messages = False
        event_broker.raise_on_failure = True

    if not event_broker.is_ready():
        cli_utils.print_error_and_exit(
            f"Event broker of type '{type(event_broker)}' is not ready. " f"Exiting."
        )

def export_trackers(args: argparse.Namespace) -> None:
    """Export events for a connected tracker store using an event broker.

    Args:
        args: Command-line arguments to process.

    """
    _validate_timestamp_options(args)

    endpoints = rasa_core_utils.read_endpoints_from_path(args.endpoints)
    tracker_store = _get_tracker_store(endpoints)
    event_broker = _get_event_broker(endpoints)
    _prepare_event_broker(event_broker)
    requested_conversation_ids = _get_requested_conversation_ids(args.conversation_ids)

    try:
        migrator = Migrator(
            tracker_store,
            event_broker,
            args.endpoints,
            requested_conversation_ids,
            args.minimum_timestamp,
            args.maximum_timestamp,
        )
        published_events = migrator.publish_events()
        cli_utils.print_success(
            f"Done! Successfully published '{published_events}' events 🎉"
        )

    except PublishingError as e:
        # noinspection PyUnboundLocalVariable
        command = _get_continuation_command(migrator, float(e))
        cli_utils.print_error_and_exit(
            f"Encountered error while publishing event with timestamp '{e}'. To "
            f"continue where I left off, run the following command:"
            f"\n\n\t{command}\n\nExiting."
        )

    except RasaException as e:
        cli_utils.print_error_and_exit(str(e))

def _get_continuation_command(migrator: Migrator, timestamp: float) -> Text:
    """Build CLI command to continue 'rasa export' where it was interrupted.

    Called when event publishing stops due to an error.

    Args:
        migrator: Migrator object containing objects relevant for this export.
        timestamp: Timestamp of the last event attempted to be published.

    """
    # build CLI command command based on supplied timestamp and options
    command = f"rasa export"

    if migrator.endpoints_path is not None:
        command += f" --endpoints {migrator.endpoints_path}"

    command += f" --minimum-timestamp {timestamp}"

    if migrator.maximum_timestamp is not None:
        command += f" --maximum-timestamp {migrator.maximum_timestamp}"

    if migrator.requested_conversation_ids:
        command += (
            f" --conversation-ids {','.join(migrator.requested_conversation_ids)}"
        )

    return command
<commit_msg>fix unbound local<commit_after>import logging

import argparse
from typing import List, Text, Optional

import rasa.cli.utils as cli_utils
import rasa.core.utils as rasa_core_utils
from rasa.cli.arguments import export as arguments
from rasa.core.brokers.broker import EventBroker
from rasa.core.brokers.pika import PikaEventBroker
from rasa.core.migrator import Migrator
from rasa.core.tracker_store import TrackerStore
from rasa.core.utils import AvailableEndpoints
from rasa.exceptions import (
    PublishingError,
    RasaException,
)

logger = logging.getLogger(__name__)

# noinspection PyProtectedMember
def add_subparser(
    subparsers: argparse._SubParsersAction, parents: List[argparse.ArgumentParser]
) -> None:
    export_parser_args = {
        "parents": parents,
        "conflict_handler": "resolve",
        "formatter_class": argparse.ArgumentDefaultsHelpFormatter,
        "help": "Export Rasa trackers using an event broker.",
    }

    shell_parser = subparsers.add_parser("export", **export_parser_args)
    shell_parser.set_defaults(func=export_trackers)

    arguments.set_export_arguments(shell_parser)

def _get_tracker_store(endpoints: AvailableEndpoints) -> TrackerStore:
    """Get tracker store from `endpoints`.

    Prints an error and exits if no tracker store could be loaded.

    Args:
        endpoints: `AvailableEndpoints` to initialize the tracker store from.

    Returns:
        Initialized tracker store.

    """
    if not endpoints.tracker_store:
        cli_utils.print_error_and_exit(
            "Could not find a `tracker_store` section in the supplied "
            "endpoints file. Exiting."
        )

    return TrackerStore.create(endpoints.tracker_store)

def _get_event_broker(endpoints: AvailableEndpoints) -> Optional[EventBroker]:
    """Get event broker from `endpoints`.

    Prints an error and exits if no event broker could be loaded.

    Args:
        endpoints: `AvailableEndpoints` to initialize the event broker from.

    Returns:
        Initialized event broker.

    """
    if not endpoints.event_broker:
        cli_utils.print_error_and_exit(
            "Could not find an `event_broker` section in the supplied "
            "endpoints file. Exiting."
        )

    return EventBroker.create(endpoints.event_broker)

def _get_requested_conversation_ids(
    conversation_ids_arg: Optional[Text] = None,
) -> Optional[List[Text]]:
    """Get list of conversation IDs requested as a command-line argument.

    Args:
        conversation_ids_arg: Value of `--conversation-ids` command-line argument.
            If provided, this is a string of comma-separated conversation IDs.

    Return:
        List of conversation IDs requested as a command-line argument.
        `None` if that argument was left unspecified.

    """
    if not conversation_ids_arg:
        return None

    return conversation_ids_arg.split(",")

def _validate_timestamp_options(args: argparse.Namespace) -> None:
    """Inspect CLI timestamp parameters.

    Prints an error and exits if a maximum timestamp is provided that is smaller
    than the provided minimum timestamp.

    Args:
        args: Command-line arguments to process.

    """
    min_timestamp = args.minimum_timestamp
    max_timestamp = args.maximum_timestamp

    if (
        min_timestamp is not None
        and max_timestamp is not None
        and max_timestamp < min_timestamp
    ):
        cli_utils.print_error_and_exit(
            f"Maximum timestamp '{max_timestamp}' is smaller than minimum "
            f"timestamp '{min_timestamp}'. Exiting."
        )

def _prepare_event_broker(event_broker: EventBroker) -> None:
    """Sets `should_keep_unpublished_messages` flag to `False` if
    `self.event_broker` is a `PikaEventBroker`.

    If publishing of events fails, the `PikaEventBroker` instance should not keep a
    list of unpublished messages, so we can retry publishing them. This is because
    the instance is launched as part of this short-lived export script, meaning the
    object is destroyed before it might be published.

    In addition, wait until the event broker reports a `ready` state.

    """
    if isinstance(event_broker, PikaEventBroker):
        event_broker.should_keep_unpublished_messages = False
        event_broker.raise_on_failure = True

    if not event_broker.is_ready():
        cli_utils.print_error_and_exit(
            f"Event broker of type '{type(event_broker)}' is not ready. " f"Exiting."
        )

def export_trackers(args: argparse.Namespace) -> None:
    """Export events for a connected tracker store using an event broker.

    Args:
        args: Command-line arguments to process.

    """
    _validate_timestamp_options(args)

    endpoints = rasa_core_utils.read_endpoints_from_path(args.endpoints)
    tracker_store = _get_tracker_store(endpoints)
    event_broker = _get_event_broker(endpoints)
    _prepare_event_broker(event_broker)
    requested_conversation_ids = _get_requested_conversation_ids(args.conversation_ids)

    migrator = Migrator(
        tracker_store,
        event_broker,
        args.endpoints,
        requested_conversation_ids,
        args.minimum_timestamp,
        args.maximum_timestamp,
    )

    try:
        published_events = migrator.publish_events()
        cli_utils.print_success(
            f"Done! Successfully published '{published_events}' events 🎉"
        )

    except PublishingError as e:
        command = _get_continuation_command(migrator, float(e))
        cli_utils.print_error_and_exit(
            f"Encountered error while publishing event with timestamp '{e}'. To "
            f"continue where I left off, run the following command:"
            f"\n\n\t{command}\n\nExiting."
        )

    except RasaException as e:
        cli_utils.print_error_and_exit(str(e))

def _get_continuation_command(migrator: Migrator, timestamp: float) -> Text:
    """Build CLI command to continue 'rasa export' where it was interrupted.

    Called when event publishing stops due to an error.

    Args:
        migrator: Migrator object containing objects relevant for this export.
        timestamp: Timestamp of the last event attempted to be published.

    """
    # build CLI command command based on supplied timestamp and options
    command = f"rasa export"

    if migrator.endpoints_path is not None:
        command += f" --endpoints {migrator.endpoints_path}"

    command += f" --minimum-timestamp {timestamp}"

    if migrator.maximum_timestamp is not None:
        command += f" --maximum-timestamp {migrator.maximum_timestamp}"

    if migrator.requested_conversation_ids:
        command += (
            f" --conversation-ids {','.join(migrator.requested_conversation_ids)}"
        )

    return command
<|endoftext|>


<commit_before>"""Implements the serial interface protocol of RaspiBot's Attiny firmware."""

from collections import namedtuple

EncoderValues = namedtuple('EncoderValues', 'left right')

# Named byte values for the protocol commands

# Requests
ALIVE = b'\x01'

ENCODERS_RIGHT = b'\x02'
ENCODERS_LEFT = b'\x03'
ENCODERS_BOTH = b'\x04'

ENCODERS_RESET_RIGHT = b'\x05'
ENCODERS_RESET_LEFT = b'\x06'
ENCODERS_RESET_BOTH = b'\x07'

SET_LEFT_MOTOR = b'\x29'
SET_RIGHT_MOTOR = b'\x25'
SET_BOTH_MOTORS = b'\x2D'
STOP_MOTORS = b'\x21'

# Responses
ACK = b'\x10'
NAK = b'\x14'

MOTOR_MIN = -127
MOTOR_MAX = 127

def _clamp(value, minimum, maximum):
    return min(maximum, max(minimum, value))

class InvalidResponseException(Exception):
    """
    Raised when the protocol implementation reads an unexpected byte.

    This is typically something that is neither an ACK nor a NAK.
    """

    pass

class AttinyProtocol(object):
    """Provides methods for protocol transactions."""

    def __init__(self, serial):
        """Create a protocol instance on a serial interface."""
        super(AttinyProtocol, self).__init__()
        self._serial = serial

    def get_encoders(self):
        """Request both left and right encoder values."""
        self._serial.write(ENCODERS_BOTH)
        response = self._serial.read(4)
        left = int.from_bytes(response[:2], 'big')
        right = int.from_bytes(response[2:], 'big')
        return EncoderValues(left, right)

    def get_left_encoder(self):
        """Request the left encoder value."""
        self._serial.write(ENCODERS_LEFT)
        response = self._serial.read(2)
        value = int.from_bytes(response, 'big')
        return value

    def get_right_encoder(self):
        """Request the right encoder value."""
        self._serial.write(ENCODERS_RIGHT)
        response = self._serial.read(2)
        value = int.from_bytes(response, 'big')
        return value

    def reset_encoders(self):
        """Reset both left and right encoder counters to zero."""
        self._serial.write(ENCODERS_RESET_BOTH)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def reset_left_encoder(self):
        """Reset the left encoder counter to zero."""
        self._serial.write(ENCODERS_RESET_LEFT)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def reset_right_encoder(self):
        """Reset the right encoder counter to zero."""
        self._serial.write(ENCODERS_RESET_RIGHT)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def alive(self):
        """Request an 'alive' signal from the microcontroller."""
        self._serial.write(ALIVE)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def set_motors(self, left, right):
        """
        Set the speed of both motors.

        Values can be in the range [-127, 127]. Speeds higher than that will be
        set to their respective extreme. Negative values turn the wheel
        backwards, positive values turn it forwards. Zero stops the motor.
        Higher absolute values mean higher speed.
        """
        left = _clamp(left, MOTOR_MIN, MOTOR_MAX)
        right = _clamp(right, MOTOR_MIN, MOTOR_MAX)
        left_bytes = left.to_bytes(1, 'big', signed=True)
        right_bytes = right.to_bytes(1, 'big', signed=True)

        self._serial.write(SET_BOTH_MOTORS + left_bytes + right_bytes)

        response = self._serial.read(1)
        if response == ACK:
            return True
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def set_left_motor(self, speed):
        """
        Set the speed of the left motor.

        Values can be in the range [-127, 127]. Speeds higher than that will be
        set to their respective extreme. Negative values turn the wheel
        backwards, positive values turn it forwards. Zero stops the motor.
        Higher absolute values mean higher speed.
        """
        speed = _clamp(speed, MOTOR_MIN, MOTOR_MAX)
        speed_bytes = speed.to_bytes(1, 'big', signed=True)

        self._serial.write(SET_LEFT_MOTOR + speed_bytes)

        response = self._serial.read(1)
        if response == ACK:
            return True
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def set_right_motor(self, speed):
        """
        Set the speed of the right motor.

        Values can be in the range [-127, 127]. Speeds higher than that will be
        set to their respective extreme. Negative values turn the wheel
        backwards, positive values turn it forwards. Zero stops the motor.
        Higher absolute values mean higher speed.
        """
        speed = _clamp(speed, MOTOR_MIN, MOTOR_MAX)
        speed_bytes = speed.to_bytes(1, 'big', signed=True)

        self._serial.write(SET_RIGHT_MOTOR + speed_bytes)

        response = self._serial.read(1)
        if response == ACK:
            return True
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()
<commit_msg>implement serial command: stop motors<commit_after>"""Implements the serial interface protocol of RaspiBot's Attiny firmware."""

from collections import namedtuple

EncoderValues = namedtuple('EncoderValues', 'left right')

# Named byte values for the protocol commands

# Requests
ALIVE = b'\x01'

ENCODERS_RIGHT = b'\x02'
ENCODERS_LEFT = b'\x03'
ENCODERS_BOTH = b'\x04'

ENCODERS_RESET_RIGHT = b'\x05'
ENCODERS_RESET_LEFT = b'\x06'
ENCODERS_RESET_BOTH = b'\x07'

STOP_MOTORS = b'\x21'
SET_LEFT_MOTOR = b'\x29'
SET_RIGHT_MOTOR = b'\x25'
SET_BOTH_MOTORS = b'\x2D'

# Responses
ACK = b'\x10'
NAK = b'\x14'

MOTOR_MIN = -127
MOTOR_MAX = 127

def _clamp(value, minimum, maximum):
    return min(maximum, max(minimum, value))

class InvalidResponseException(Exception):
    """
    Raised when the protocol implementation reads an unexpected byte.

    This is typically something that is neither an ACK nor a NAK.
    """

    pass

class AttinyProtocol(object):
    """Provides methods for protocol transactions."""

    def __init__(self, serial):
        """Create a protocol instance on a serial interface."""
        super(AttinyProtocol, self).__init__()
        self._serial = serial

    def get_encoders(self):
        """Request both left and right encoder values."""
        self._serial.write(ENCODERS_BOTH)
        response = self._serial.read(4)
        left = int.from_bytes(response[:2], 'big')
        right = int.from_bytes(response[2:], 'big')
        return EncoderValues(left, right)

    def get_left_encoder(self):
        """Request the left encoder value."""
        self._serial.write(ENCODERS_LEFT)
        response = self._serial.read(2)
        value = int.from_bytes(response, 'big')
        return value

    def get_right_encoder(self):
        """Request the right encoder value."""
        self._serial.write(ENCODERS_RIGHT)
        response = self._serial.read(2)
        value = int.from_bytes(response, 'big')
        return value

    def reset_encoders(self):
        """Reset both left and right encoder counters to zero."""
        self._serial.write(ENCODERS_RESET_BOTH)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def reset_left_encoder(self):
        """Reset the left encoder counter to zero."""
        self._serial.write(ENCODERS_RESET_LEFT)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def reset_right_encoder(self):
        """Reset the right encoder counter to zero."""
        self._serial.write(ENCODERS_RESET_RIGHT)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def alive(self):
        """Request an 'alive' signal from the microcontroller."""
        self._serial.write(ALIVE)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def stop_motors(self):
        """Immediately stops both motors."""
        self._serial.write(STOP_MOTORS)
        response = self._serial.read(1)
        if response == ACK:
            return True
        # empty response can happen on a timeout, which we interpret as
        # "not alive"
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def set_motors(self, left, right):
        """
        Set the speed of both motors.

        Values can be in the range [-127, 127]. Speeds higher than that will be
        set to their respective extreme. Negative values turn the wheel
        backwards, positive values turn it forwards. Zero stops the motor.
        Higher absolute values mean higher speed.
        """
        left = _clamp(left, MOTOR_MIN, MOTOR_MAX)
        right = _clamp(right, MOTOR_MIN, MOTOR_MAX)
        left_bytes = left.to_bytes(1, 'big', signed=True)
        right_bytes = right.to_bytes(1, 'big', signed=True)

        self._serial.write(SET_BOTH_MOTORS + left_bytes + right_bytes)

        response = self._serial.read(1)
        if response == ACK:
            return True
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def set_left_motor(self, speed):
        """
        Set the speed of the left motor.

        Values can be in the range [-127, 127]. Speeds higher than that will be
        set to their respective extreme. Negative values turn the wheel
        backwards, positive values turn it forwards. Zero stops the motor.
        Higher absolute values mean higher speed.
        """
        speed = _clamp(speed, MOTOR_MIN, MOTOR_MAX)
        speed_bytes = speed.to_bytes(1, 'big', signed=True)

        self._serial.write(SET_LEFT_MOTOR + speed_bytes)

        response = self._serial.read(1)
        if response == ACK:
            return True
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()

    def set_right_motor(self, speed):
        """
        Set the speed of the right motor.

        Values can be in the range [-127, 127]. Speeds higher than that will be
        set to their respective extreme. Negative values turn the wheel
        backwards, positive values turn it forwards. Zero stops the motor.
        Higher absolute values mean higher speed.
        """
        speed = _clamp(speed, MOTOR_MIN, MOTOR_MAX)
        speed_bytes = speed.to_bytes(1, 'big', signed=True)

        self._serial.write(SET_RIGHT_MOTOR + speed_bytes)

        response = self._serial.read(1)
        if response == ACK:
            return True
        elif response == NAK or response == b'':
            return False
        else:
            raise InvalidResponseException()
<|endoftext|>


<commit_before>"""
Library for profiling operations in Ravel.

Ravel's profiling library uses message queues since a execution of a command
may span across multiple processes.   For example, operations for adding or
removing a flow execute in two processes: the database trigger and the OpenFlow
manager.  Results then are reported to a third process: the CLI.
"""

import pickle
import sysv_ipc
import threading
import time
from collections import OrderedDict

import ravel.messaging
from ravel.log import logger

ProfileQueueId = 99999
ProfileOff = "1"
ProfileOn = "2"

def enable_profiling():
    "Enable profiling"
    shm = sysv_ipc.SharedMemory(ProfileQueueId,
                                flags=sysv_ipc.IPC_CREAT,
                                mode=0777,
                                size=sysv_ipc.PAGE_SIZE,
                                init_character=" ")
    shm.write(str(ProfileOn))
    shm.detach()

def disable_profiling():
    "Disable profiling"
    shm = sysv_ipc.SharedMemory(ProfileQueueId,
                                flags=sysv_ipc.IPC_CREAT,
                                mode=07777,
                                size=sysv_ipc.PAGE_SIZE,
                                init_character=" ")
    shm.write(str(ProfileOff))
    shm.detach()

def is_profiled():
    "Check if profiling is enabled"
    try:
        shm = sysv_ipc.SharedMemory(ProfileQueueId)
        return shm.read().strip("\0") == ProfileOn
    except sysv_ipc.ExistentialError, e:
        logger.warning("profile queue doesn't exist: %", e)
        return False

class PerfCounter(object):
    "Store timing information for a single operation"

    def __init__(self, name, time_ms=None):
        """name: the name of the operation
           time_ms: the execution time of the operation, if already
           recorded"""
        self.name = name
        self.start_time = None
        self.time_ms = time_ms
        if self.time_ms is not None:
            self.time_ms = round(float(time_ms), 3)

    def start(self):
        "Start recording execution time of an operation"
        if is_profiled():
            self.start_time = time.time()

    def stop(self):
        "Stop recording execution time of an operation"
        if self.start_time is not None:
            self.time_ms = round((time.time() - self.start_time) * 1000, 3)
            self.report()

    def consume(self, consumer):
        """Consume the performance counter
           consumer: a ProfiledExecution instance to consume the counter"""
        consumer.handler(self)

    def report(self):
        "Report the performance counter by adding it to the message queue"
        try:
            mq = sysv_ipc.MessageQueue(ProfileQueueId, mode=0777)
            mq.send(pickle.dumps(self))
        except Exception, e:
            print e

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "{0}:{1}".format(self.name, self.time_ms)

class ProfiledExecution(object):
    "Start a new profiled execution and collect performance counters"

    def __init__(self):
        self.counters = []
        self.receiver = ravel.messaging.MsgQueueReceiver(ProfileQueueId, self)

    def print_summary(self):
        "Print results of collected performance counters"
        if len(self.counters) == 0:
            print "No performance counters found"
            return

        agg = OrderedDict()
        summ = 0
        print "-" * 40
        for counter in self.counters:
            summ += counter.time_ms

            if counter.name not in agg.keys():
                agg[counter.name] = (1, counter.time_ms)
            else:
                count,ms =  agg[counter.name]
                agg[counter.name] = (count + 1, ms + counter.time_ms)

        for counter, tup in agg.iteritems():
            print "{0}({1}): {2}ms".format(counter, tup[0], tup[1])

        print "-" * 40
        print "Total: {0}ms".format(summ)

    def start(self):
        "Enable profiling and start receiving performance counters"
        enable_profiling()
        self.receiver.start()

    def stop(self):
        "Disable profiling and stop receiving performance counters"
        self.receiver.stop()
        disable_profiling()

    def handler(self, obj):
        """Callback for consuming performance counters
           obj: a PerfCounter object"""
        if obj is not None:
            self.counters.append(obj)
<commit_msg>Fix bug in reporting times when profiling not enabled<commit_after>"""
Library for profiling operations in Ravel.

Ravel's profiling library uses message queues since a execution of a command
may span across multiple processes.   For example, operations for adding or
removing a flow execute in two processes: the database trigger and the OpenFlow
manager.  Results then are reported to a third process: the CLI.
"""

import pickle
import sysv_ipc
import threading
import time
from collections import OrderedDict

import ravel.messaging
from ravel.log import logger

ProfileQueueId = 99999
ProfileOff = "1"
ProfileOn = "2"

def enable_profiling():
    "Enable profiling"
    shm = sysv_ipc.SharedMemory(ProfileQueueId,
                                flags=sysv_ipc.IPC_CREAT,
                                mode=0777,
                                size=sysv_ipc.PAGE_SIZE,
                                init_character=" ")
    shm.write(str(ProfileOn))
    shm.detach()

def disable_profiling():
    "Disable profiling"
    shm = sysv_ipc.SharedMemory(ProfileQueueId,
                                flags=sysv_ipc.IPC_CREAT,
                                mode=07777,
                                size=sysv_ipc.PAGE_SIZE,
                                init_character=" ")
    shm.write(str(ProfileOff))
    shm.detach()

def is_profiled():
    "Check if profiling is enabled"
    try:
        shm = sysv_ipc.SharedMemory(ProfileQueueId)
        return shm.read().strip("\0") == ProfileOn
    except sysv_ipc.ExistentialError, e:
        logger.warning("profile queue doesn't exist: %", e)
        return False

class PerfCounter(object):
    "Store timing information for a single operation"

    def __init__(self, name, time_ms=None):
        """name: the name of the operation
           time_ms: the execution time of the operation, if already
           recorded"""
        self.name = name
        self.start_time = None
        self.time_ms = time_ms
        if self.time_ms is not None:
            self.time_ms = round(float(time_ms), 3)

    def start(self):
        "Start recording execution time of an operation"
        if is_profiled():
            self.start_time = time.time()

    def stop(self):
        "Stop recording execution time of an operation"
        if self.start_time is not None:
            self.time_ms = round((time.time() - self.start_time) * 1000, 3)
            self.report()

    def consume(self, consumer):
        """Consume the performance counter
           consumer: a ProfiledExecution instance to consume the counter"""
        consumer.handler(self)

    def report(self):
        "Report the performance counter by adding it to the message queue"
        try:
            if is_profiled():
                mq = sysv_ipc.MessageQueue(ProfileQueueId, mode=0777)
                mq.send(pickle.dumps(self))
        except Exception, e:
            print e

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "{0}:{1}".format(self.name, self.time_ms)

class ProfiledExecution(object):
    "Start a new profiled execution and collect performance counters"

    def __init__(self):
        self.counters = []
        self.receiver = ravel.messaging.MsgQueueReceiver(ProfileQueueId, self)

    def print_summary(self):
        "Print results of collected performance counters"
        if len(self.counters) == 0:
            print "No performance counters found"
            return

        agg = OrderedDict()
        summ = 0
        print "-" * 40
        for counter in self.counters:
            summ += counter.time_ms

            if counter.name not in agg.keys():
                agg[counter.name] = (1, counter.time_ms)
            else:
                count,ms =  agg[counter.name]
                agg[counter.name] = (count + 1, ms + counter.time_ms)

        for counter, tup in agg.iteritems():
            print "{0}({1}): {2}ms".format(counter, tup[0], tup[1])

        print "-" * 40
        print "Total: {0}ms".format(summ)

    def start(self):
        "Enable profiling and start receiving performance counters"
        enable_profiling()
        self.receiver.start()

    def stop(self):
        "Disable profiling and stop receiving performance counters"
        self.receiver.stop()
        disable_profiling()

    def handler(self, obj):
        """Callback for consuming performance counters
           obj: a PerfCounter object"""
        if obj is not None:
            self.counters.append(obj)
<|endoftext|>


<commit_before>"""\
A pure Python package providing the core RDF constructs.

The packages is intended to provide the core RDF types and interfaces
for working with RDF. The package defines a plugin interface for
parsers, stores, and serializers that other packages can use to
implement parsers, stores, and serializers that will plug into the
rdflib package.

The primary interface `rdflib` exposes to work with RDF is
`rdflib.graph.Graph`.

A tiny example:

    >>> import rdflib

    >>> g = rdflib.Graph()
    >>> result = g.parse("http://eikeon.com/foaf.rdf")

    >>> print "graph has %s statements." % len(g)
    graph has 34 statements.
    >>>
    >>> for s, p, o in g:
    ...     if (s, p, o) not in g:
    ...         raise Exception("It better be!")

    >>> s = g.serialize(format='n3')

"""
__docformat__ = "restructuredtext en"

__version__ = "3.1.0"
__date__ = "2011/03/17"

__all__ = [
    'URIRef',
    'BNode',
    'Literal',
    'Variable',

    'Namespace',

    'Graph',
    'ConjunctiveGraph',

    'RDF',
    'RDFS',
    'OWL',
    'XSD',

    'util',
    ]

import sys
# generator expressions require 2.4
assert sys.version_info >= (2, 4, 0), "rdflib requires Python 2.4 or higher"
del sys

import logging
_LOGGER = logging.getLogger("rdflib")
_LOGGER.info("version: %s" % __version__)

from rdflib.term import URIRef, BNode, Literal, Variable

from rdflib.namespace import Namespace

from rdflib.graph import Graph, ConjunctiveGraph

from rdflib.namespace import RDF, RDFS, OWL, XSD

from rdflib import plugin
from rdflib import query

from rdflib import util

<commit_msg>set dev version<commit_after>"""\
A pure Python package providing the core RDF constructs.

The packages is intended to provide the core RDF types and interfaces
for working with RDF. The package defines a plugin interface for
parsers, stores, and serializers that other packages can use to
implement parsers, stores, and serializers that will plug into the
rdflib package.

The primary interface `rdflib` exposes to work with RDF is
`rdflib.graph.Graph`.

A tiny example:

    >>> import rdflib

    >>> g = rdflib.Graph()
    >>> result = g.parse("http://eikeon.com/foaf.rdf")

    >>> print "graph has %s statements." % len(g)
    graph has 34 statements.
    >>>
    >>> for s, p, o in g:
    ...     if (s, p, o) not in g:
    ...         raise Exception("It better be!")

    >>> s = g.serialize(format='n3')

"""
__docformat__ = "restructuredtext en"

__version__ = "3.2.0-dev"
__date__ = "2011/03/17"

__all__ = [
    'URIRef',
    'BNode',
    'Literal',
    'Variable',

    'Namespace',

    'Graph',
    'ConjunctiveGraph',

    'RDF',
    'RDFS',
    'OWL',
    'XSD',

    'util',
    ]

import sys
# generator expressions require 2.4
assert sys.version_info >= (2, 4, 0), "rdflib requires Python 2.4 or higher"
del sys

import logging
_LOGGER = logging.getLogger("rdflib")
_LOGGER.info("version: %s" % __version__)

from rdflib.term import URIRef, BNode, Literal, Variable

from rdflib.namespace import Namespace

from rdflib.graph import Graph, ConjunctiveGraph

from rdflib.namespace import RDF, RDFS, OWL, XSD

from rdflib import plugin
from rdflib import query

from rdflib import util

<|endoftext|>


<commit_before>import hexchat

__module_name__ = 'Twitch'
__module_author__ = 'TingPing'
__module_version__ = '2'
__module_description__ = 'Better integration with Twitch.tv'
# Very much a work in progress...

# Commands from http://help.twitch.tv/customer/portal/articles/659095-chat-moderation-commands
# /ban may conflict with other scripts nothing we can do about that
# /clear is an existing command, just override it
commands = ('timeout', 'slow', 'slowoff', 'subscribers', 'subscribersoff',
			'mod', 'unmod', 'mods', 'clear', 'ban', 'unban', 'commercial',
			'r9kbeta', 'r9kbetaoff')

aliases = {'op':'mod', 'deop':'unmod'}

def twitchOnly(func):
	def is_twitch(*args, **kwargs):
		server = hexchat.get_info('server')
		if 'twitch.tv' in server or 'justin.tv' in server:
			return func(*args, **kwargs)
		else:
			return hexchat.EAT_NONE
	return is_twitch

# Twitch returns a lot of 'unknown command' errors, ignore them.
@twitchOnly
def servererr_cb(word, word_eol, userdata):
	return hexchat.EAT_ALL

# Print jtv messages in server tab.
@twitchOnly
def privmsg_cb(word, word_eol, userdata):
	if word[0][1:4] == 'jtv':
		hexchat.find_context(channel=hexchat.get_info('network')).set()
		hexchat.emit_print('Server Text', word_eol[3][1:])
		return hexchat.EAT_ALL

# Eat any message starting with a '.', twitch eats all of them too.
@twitchOnly
def yourmsg_cb(word, word_eol, userdata):
	if word[1][0] == '.':
		return hexchat.EAT_ALL

# Just prefix with a '.'.
@twitchOnly
def command_cb(word, word_eol, alias):
	if alias:
		if len(word_eol) > 1:
			hexchat.command('say .{} {}'.format(alias, word_eol[1]))
		else:
			hexchat.command('say .{}'.format(alias))
	else:
		hexchat.command('say .{}'.format(word_eol[0]))
	return hexchat.EAT_ALL

for command in commands:
	hexchat.hook_command(command, command_cb)
for command, alias in aliases.items():
	hexchat.hook_command(command, command_cb, alias)
hexchat.hook_print('Your Message', yourmsg_cb)
hexchat.hook_server('421', servererr_cb)
hexchat.hook_server('PRIVMSG', privmsg_cb)
<commit_msg>Update twitch.py<commit_after>import hexchat

__module_name__ = 'Twitch'
__module_author__ = 'TingPing'
__module_version__ = '2'
__module_description__ = 'Better integration with Twitch.tv'
# Very much a work in progress...

# Commands from http://help.twitch.tv/customer/portal/articles/659095-chat-moderation-commands
# /ban may conflict with other scripts nothing we can do about that
# /clear is an existing command, just override it
commands = ('timeout', 'slow', 'slowoff', 'subscribers', 'subscribersoff',
			'mod', 'unmod', 'mods', 'clear', 'ban', 'unban', 'commercial',
			'r9kbeta', 'r9kbetaoff')

aliases = {'op':'mod', 'deop':'unmod'}

def twitchOnly(func):
	def if_twitch(*args, **kwargs):
		server = hexchat.get_info('server')
		if server and ('twitch.tv' in server or 'justin.tv' in server):
			return func(*args, **kwargs)
		else:
			return hexchat.EAT_NONE
	return if_twitch

# Twitch returns a lot of 'unknown command' errors, ignore them.
@twitchOnly
def servererr_cb(word, word_eol, userdata):
	return hexchat.EAT_ALL

# Print jtv messages in server tab.
@twitchOnly
def privmsg_cb(word, word_eol, userdata):
	if word[0][1:4] == 'jtv':
		hexchat.find_context(channel=hexchat.get_info('network')).set()
		hexchat.emit_print('Server Text', word_eol[3][1:])
		return hexchat.EAT_ALL

# Eat any message starting with a '.', twitch eats all of them too.
@twitchOnly
def yourmsg_cb(word, word_eol, userdata):
	if word[1][0] == '.':
		return hexchat.EAT_ALL

# Just prefix with a '.'.
@twitchOnly
def command_cb(word, word_eol, alias):
	if alias:
		if len(word_eol) > 1:
			hexchat.command('say .{} {}'.format(alias, word_eol[1]))
		else:
			hexchat.command('say .{}'.format(alias))
	else:
		hexchat.command('say .{}'.format(word_eol[0]))
	return hexchat.EAT_ALL

for command in commands:
	hexchat.hook_command(command, command_cb)
for command, alias in aliases.items():
	hexchat.hook_command(command, command_cb, alias)
hexchat.hook_print('Your Message', yourmsg_cb)
hexchat.hook_server('421', servererr_cb)
hexchat.hook_server('PRIVMSG', privmsg_cb)
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
HiveAggregator
Developed by Trevor Stanhope

HiveAggregator is a minimal CherryPy instance

TODO:
- Scatter plot, not line graph

"""

# Libraries
import json
import ast
import cherrypy
import os
import urllib2
import sys
import numpy
from datetime import datetime, timedelta
from cherrypy.process.plugins import Monitor
from cherrypy import tools
from pymongo import MongoClient
import zmq

# Constants
try:
    CONFIG_FILE = sys.argv[1]
except Exception as err:
    CONFIG_FILE = 'settings.json'

# HiveAggregator CherryPy server
class HiveAggregator:

    ## Initialize
    def __init__(self):
        ### Load Configuration
        print('[Loading Config File]')
        with open(CONFIG_FILE) as config:
            settings = json.loads(config.read())
            for key in settings:
                try:
                    getattr(self, key)
                except AttributeError as error:
                    print('\t' + key + ' : ' + str(settings[key]))
                    setattr(self, key, settings[key])
        ### ZMQ
        print('[Initializing ZMQ]')
        try:
            self.context = zmq.Context()
            self.socket = self.context.socket(zmq.REP)
            self.socket.bind(self.ZMQ_SERVER)
            print('\tOKAY')
        except Exception as error:
            print('\tERROR: ' + str(error))
        ### CherryPy Monitors
        print('[Enabling Monitors]')
        try:
            Monitor(cherrypy.engine, self.listen, frequency=self.CHERRYPY_INTERVAL).subscribe()
            print('\tOKAY')
        except Exception as error:
            print('\tERROR: ' + str(error))
        ### MongoDB
        print('[Initializing Mongo]')
        try:
            self.mongo_client = MongoClient(self.MONGO_ADDR, self.MONGO_PORT)
            self.mongo_db = self.mongo_client[self.MONGO_DB]
            print('\tOKAY')
        except Exception as error:
            print('\tERROR: ' + str(error))

    ## Train with User Log
    def train(self, log):
        hive_id = log['hive_id']
        collection = self.mongo_db[hive_id]
        period = datetime.now()
        event = {'type':'event'}
        for sample in collection.find({'time':{'$lt':period}, 'type':'sample'}).sort('time'):
            for param in params:
                event[param] = sample[param]
        return event

    ## Classify Sample
    def classify(self, sample):
        hive_id = sample['hive_id']
        collection = self.mongo_db[hive_id]
        period = datetime.now()
        for event in collection.find({'time':{'$lt':period}, 'type':'event'}).sort('time'):
            pass
        return {'none'}

    ## Query Last 24 hours to CSV
    def query_range(self, param1, param2, hours, filename):
        print('[Querying Last 24 Hours]')
        with open('data/' + filename + '.csv', 'w') as datafile:
            datafile.write(','.join(['hive_id','time',param1, param2,'\n']))
            one_day_ago = datetime.today() - timedelta(hours = hours) # get datetime of 1 day ago
            for name in self.mongo_db.collection_names():
                if name == 'system.indexes':
                    pass
                else:
                    hive = self.mongo_db[name]
                    for sample in hive.find({'time':{'$gt':one_day_ago}}):
                        try:
                            hive_id = str(sample['hive_id'])
                            val1 = str(sample[param1])
                            val2 = str(sample[param2])
                            time = sample['time'].strftime('%H:%M')
                            datafile.write(','.join([hive_id,time,val1,val2,'\n']))
                        except Exception:
                            pass
    ## Store to Mongo
    def store(self, doc):
        print('[Storing to Mongo]')
        try:
            doc['time'] = datetime.now()
            hive = self.mongo_db[doc['hive_id']]
            doc_id = hive.insert(doc)
            print('\tOKAY: ' + str(doc_id))
            return doc_id
        except Exception as error:
            print('--> ERROR: ' + str(error))

    ## Receive Sample
    def receive(self):
        print('[Receiving Sample from Hive]')
        try:
            packet = self.socket.recv()
            sample = json.loads(packet)
            print('\tOKAY: ' + str(sample))
            return sample
        except Exception as error:
            print('\tERROR: ' + str(error))

    ### Send Response
    def send(self):
        print('[Sending Response to Hive]')
        try:
            response = {'status':'okay'}
            dump = json.dumps(response)
            self.socket.send(dump)
            print('\tOKAY: ' + str(response))
        except Exception as error:
            print('\tERROR: ' + str(error))

    ## Listen for Next Sample
    def listen(self):
        print('\n')
        sample = self.receive()
        self.send()
        state = self.classify(sample)
        mongo_id = self.store(sample)

    ## Render Index
    @cherrypy.expose
    def index(self):
        self.query_range('int_t', 'ext_t', 24, 'temp')
        html = open('static/index.html').read()
        return html

# Main
if __name__ == '__main__':
    aggregator = HiveAggregator()
    cherrypy.server.socket_host = aggregator.CHERRYPY_ADDR
    cherrypy.server.socket_port = aggregator.CHERRYPY_PORT
    currdir = os.path.dirname(os.path.abspath(__file__))
    conf = {
        '/': {'tools.staticdir.on':True, 'tools.staticdir.dir':os.path.join(currdir,'static')},
        '/data': {'tools.staticdir.on':True, 'tools.staticdir.dir':os.path.join(currdir,'data')}, # NEED the '/' before the folder name
    }
    cherrypy.quickstart(aggregator, '/', config=conf)
<commit_msg>added post handler for logs and graph posts from jquery, modded query_range to take hours and output to single json file<commit_after>#!/usr/bin/env python
"""
HiveAggregator
Developed by Trevor Stanhope

HiveAggregator is a minimal CherryPy instance

TODO:
- Log post --> train learners
"""

# Libraries
import json
import ast
import cherrypy
import os
import sys
import numpy
from datetime import datetime, timedelta
from cherrypy.process.plugins import Monitor
from cherrypy import tools
from pymongo import MongoClient
from bson import json_util
import zmq
from sklearn import svm

# Constants
try:
    CONFIG_FILE = sys.argv[1]
except Exception as err:
    CONFIG_FILE = 'settings.json'

# HiveAggregator CherryPy server
class HiveAggregator:

    ## Initialize
    def __init__(self):
        ### Load Configuration
        print('[Loading Config File]')
        with open(CONFIG_FILE) as config:
            settings = json.loads(config.read())
            for key in settings:
                try:
                    getattr(self, key)
                except AttributeError as error:
                    print('\t' + key + ' : ' + str(settings[key]))
                    setattr(self, key, settings[key])
        ### ZMQ
        print('[Initializing ZMQ]')
        try:
            self.context = zmq.Context()
            self.socket = self.context.socket(zmq.REP)
            self.socket.bind(self.ZMQ_SERVER)
            print('\tOKAY')
        except Exception as error:
            print('\tERROR: ' + str(error))
        ### CherryPy Monitors
        print('[Enabling Monitors]')
        try:
            Monitor(cherrypy.engine, self.listen, frequency=self.CHERRYPY_INTERVAL).subscribe()
            print('\tOKAY')
        except Exception as error:
            print('\tERROR: ' + str(error))
        ### MongoDB
        print('[Initializing Mongo]')
        try:
            self.mongo_client = MongoClient(self.MONGO_ADDR, self.MONGO_PORT)
            self.mongo_db = self.mongo_client[self.MONGO_DB]
            print('\tOKAY')
        except Exception as error:
            print('\tERROR: ' + str(error))
        ### SKLearn
        print('[Initializing SKlearn]')
        try:
            self.svc_health = svm.SVC(kernel='rbf')
            print('\tOKAY')
        except Exception as error:
            print('\tERROR: ' + str(error))

    ## Train
    def train(self, log):
        pass

    ## Classify
    def classify(self, sample):
        prediction = 1
        return prediction

    ## Query Param in Range to JSON-file
    def query_range(self, start_hours, end_hours):
        print('[Querying Data Range]')
        print start_hours
        print end_hours
        with open('data/samples.json', 'w') as jsonfile:
            result = []
            start = datetime.now() - timedelta(hours = start_hours) # get datetime
            end = datetime.now() - timedelta(hours = end_hours) # get datetime
            for name in self.mongo_db.collection_names():
                if not name == 'system.indexes':
                    for sample in self.mongo_db[name].find({'time':{'$gt': end, '$lt':start}}):
                        sample['time'] = datetime.strftime(sample['time'], self.TIME_FORMAT)
                        result.append(sample)
            dump = json_util.dumps(result, indent=4)
            jsonfile.write(dump)

    ## Store to Mongo
    def store(self, doc):
        print('[Storing to Mongo]')
        try:
            doc['time'] = datetime.now()
            hive = self.mongo_db[doc['hive_id']]
            doc_id = hive.insert(doc)
            print('\tOKAY: ' + str(doc_id))
            return doc_id
        except Exception as error:
            print('--> ERROR: ' + str(error))

    ## Receive Sample
    def receive(self):
        print('[Receiving Sample from Hive]')
        try:
            packet = self.socket.recv()
            sample = json.loads(packet)
            print('\tOKAY: ' + str(sample))
            return sample
        except Exception as error:
            print('\tERROR: ' + str(error))

    ### Send Response
    def send(self):
        print('[Sending Response to Hive]')
        try:
            response = {'status':'okay'}
            dump = json.dumps(response)
            self.socket.send(dump)
            print('\tOKAY: ' + str(response))
        except Exception as error:
            print('\tERROR: ' + str(error))

    ## Listen for Next Sample
    def listen(self):
        print('\n')
        sample = self.receive()
        response = self.classify(sample)
        self.send()
        mongo_id = self.store(sample)

    ## Render Index
    @cherrypy.expose
    def index(self):
        html = open('static/index.html').read()
        return html

    ## Handle Posts
    @cherrypy.expose
    def default(self,*args,**kwargs):
        print kwargs
        if kwargs['type'] == 'log':
            print 'log'
        elif kwargs['type'] == 'graph':
            if kwargs['range_select'] == 'hour':
                self.query_range(0, 1)
            elif kwargs['range_select'] == 'day':
                self.query_range(0, 24)
            elif kwargs['range_select'] == 'week':
                self.query_range(0, 168)
            elif kwargs['range_select'] == 'month':
                self.query_range(0, 744)
        else:
            pass
        return 't'

# Main
if __name__ == '__main__':
    aggregator = HiveAggregator()
    cherrypy.server.socket_host = aggregator.CHERRYPY_ADDR
    cherrypy.server.socket_port = aggregator.CHERRYPY_PORT
    currdir = os.path.dirname(os.path.abspath(__file__))
    conf = {
        '/': {'tools.staticdir.on':True, 'tools.staticdir.dir':os.path.join(currdir,'static')},
        '/data': {'tools.staticdir.on':True, 'tools.staticdir.dir':os.path.join(currdir,'data')}, # NEED the '/' before the folder name
    }
    cherrypy.quickstart(aggregator, '/', config=conf)
<|endoftext|>