<commit_before># Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""Base classes for our unit tests.

Allows overriding of flags for use of fakes, and some black magic for
inline callbacks.

"""

import eventlet
eventlet.monkey_patch(os=False)

import copy
import inspect
import mock
import logging
import os

import fixtures
from oslo.config import cfg
from oslo.config import fixture as config_fixture
from oslo.utils import timeutils
from oslo_concurrency import lockutils
from oslotest import moxstubout
import six
import testtools

from nova import context
from nova import db
from nova.network import manager as network_manager
from nova import objects
from nova.objects import base as objects_base
from nova.openstack.common.fixture import logging as log_fixture
from nova.openstack.common import log as nova_logging
from nova.tests import fixtures as nova_fixtures
from nova.tests.unit import conf_fixture
from nova.tests.unit import policy_fixture
from nova import utils

CONF = cfg.CONF
CONF.import_opt('enabled', 'nova.api.openstack', group='osapi_v3')
CONF.set_override('use_stderr', False)

nova_logging.setup('nova')

# NOTE(comstud): Make sure we have all of the objects loaded. We do this
# at module import time, because we may be using mock decorators in our
# tests that run at import time.
objects.register_all()

_TRUE_VALUES = ('True', 'true', '1', 'yes')

class SampleNetworks(fixtures.Fixture):

    """Create sample networks in the database."""

    def __init__(self, host=None):
        self.host = host

    def setUp(self):
        super(SampleNetworks, self).setUp()
        ctxt = context.get_admin_context()
        network = network_manager.VlanManager(host=self.host)
        bridge_interface = CONF.flat_interface or CONF.vlan_interface
        network.create_networks(ctxt,
                                label='test',
                                cidr='10.0.0.0/8',
                                multi_host=CONF.multi_host,
                                num_networks=CONF.num_networks,
                                network_size=CONF.network_size,
                                cidr_v6=CONF.fixed_range_v6,
                                gateway=CONF.gateway,
                                gateway_v6=CONF.gateway_v6,
                                bridge=CONF.flat_network_bridge,
                                bridge_interface=bridge_interface,
                                vpn_start=CONF.vpn_start,
                                vlan_start=CONF.vlan_start,
                                dns1=CONF.flat_network_dns)
        for net in db.network_get_all(ctxt):
            network.set_network_host(ctxt, net)

class TestingException(Exception):
    pass

class NullHandler(logging.Handler):
    """custom default NullHandler to attempt to format the record.

    Used in conjunction with
    log_fixture.get_logging_handle_error_fixture to detect formatting errors in
    debug level logs without saving the logs.
    """
    def handle(self, record):
        self.format(record)

    def emit(self, record):
        pass

    def createLock(self):
        self.lock = None

class skipIf(object):
    def __init__(self, condition, reason):
        self.condition = condition
        self.reason = reason

    def __call__(self, func_or_cls):
        condition = self.condition
        reason = self.reason
        if inspect.isfunction(func_or_cls):
            @six.wraps(func_or_cls)
            def wrapped(*args, **kwargs):
                if condition:
                    raise testtools.TestCase.skipException(reason)
                return func_or_cls(*args, **kwargs)

            return wrapped
        elif inspect.isclass(func_or_cls):
            orig_func = getattr(func_or_cls, 'setUp')

            @six.wraps(orig_func)
            def new_func(self, *args, **kwargs):
                if condition:
                    raise testtools.TestCase.skipException(reason)
                orig_func(self, *args, **kwargs)

            func_or_cls.setUp = new_func
            return func_or_cls
        else:
            raise TypeError('skipUnless can be used only with functions or '
                            'classes')

def _patch_mock_to_raise_for_invalid_assert_calls():
    def raise_for_invalid_assert_calls(wrapped):
        def wrapper(_self, name):
            valid_asserts = [
                'assert_called_with',
                'assert_called_once_with',
                'assert_has_calls',
                'assert_any_calls']

            if name.startswith('assert') and name not in valid_asserts:
                raise AttributeError('%s is not a valid mock assert method'
                                     % name)

            return wrapped(_self, name)
        return wrapper
    mock.Mock.__getattr__ = raise_for_invalid_assert_calls(
        mock.Mock.__getattr__)

# NOTE(gibi): needs to be called only once at import time
# to patch the mock lib
_patch_mock_to_raise_for_invalid_assert_calls()

class TestCase(testtools.TestCase):
    """Test case base class for all unit tests.

    Due to the slowness of DB access, please consider deriving from
    `NoDBTestCase` first.
    """
    USES_DB = True
    REQUIRES_LOCKING = False

    TIMEOUT_SCALING_FACTOR = 1

    def setUp(self):
        """Run before each test method to initialize test environment."""
        super(TestCase, self).setUp()
        self.useFixture(nova_fixtures.Timeout(
            os.environ.get('OS_TEST_TIMEOUT', 0),
            self.TIMEOUT_SCALING_FACTOR))

        self.useFixture(fixtures.NestedTempfile())
        self.useFixture(fixtures.TempHomeDir())
        self.useFixture(nova_fixtures.TranslationFixture())
        self.useFixture(log_fixture.get_logging_handle_error_fixture())

        self.useFixture(nova_fixtures.OutputStreamCapture())

        self.useFixture(nova_fixtures.StandardLogging())
        self.useFixture(nova_fixtures.WarningsFixture())

        # NOTE(sdague): because of the way we were using the lock
        # wrapper we eneded up with a lot of tests that started
        # relying on global external locking being set up for them. We
        # consider all of these to be *bugs*. Tests should not require
        # global external locking, or if they do, they should
        # explicitly set it up themselves.
        #
        # The following REQUIRES_LOCKING class parameter is provided
        # as a bridge to get us there. No new tests should be added
        # that require it, and existing classes and tests should be
        # fixed to not need it.
        if self.REQUIRES_LOCKING:
            lock_path = self.useFixture(fixtures.TempDir()).path
            self.fixture = self.useFixture(
                config_fixture.Config(lockutils.CONF))
            self.fixture.config(lock_path=lock_path,
                                group='oslo_concurrency')

        self.useFixture(conf_fixture.ConfFixture(CONF))
        self.useFixture(nova_fixtures.RPCFixture('nova.test'))

        if self.USES_DB:
            self.useFixture(nova_fixtures.Database())

        # NOTE(danms): Make sure to reset us back to non-remote objects
        # for each test to avoid interactions. Also, backup the object
        # registry.
        objects_base.NovaObject.indirection_api = None
        self._base_test_obj_backup = copy.copy(
            objects_base.NovaObject._obj_classes)
        self.addCleanup(self._restore_obj_registry)

        # NOTE(mnaser): All calls to utils.is_neutron() are cached in
        # nova.utils._IS_NEUTRON.  We set it to None to avoid any
        # caching of that value.
        utils._IS_NEUTRON = None

        mox_fixture = self.useFixture(moxstubout.MoxStubout())
        self.mox = mox_fixture.mox
        self.stubs = mox_fixture.stubs
        self.addCleanup(self._clear_attrs)
        self.useFixture(fixtures.EnvironmentVariable('http_proxy'))
        self.policy = self.useFixture(policy_fixture.PolicyFixture())

    def _restore_obj_registry(self):
        objects_base.NovaObject._obj_classes = self._base_test_obj_backup

    def _clear_attrs(self):
        # Delete attributes that don't start with _ so they don't pin
        # memory around unnecessarily for the duration of the test
        # suite
        for key in [k for k in self.__dict__.keys() if k[0] != '_']:
            del self.__dict__[key]

    def flags(self, **kw):
        """Override flag variables for a test."""
        group = kw.pop('group', None)
        for k, v in kw.iteritems():
            CONF.set_override(k, v, group)

    def start_service(self, name, host=None, **kwargs):
        svc = self.useFixture(
            nova_fixtures.ServiceFixture(name, host, **kwargs))
        return svc.service

    def assertPublicAPISignatures(self, baseinst, inst):
        def get_public_apis(inst):
            methods = {}
            for (name, value) in inspect.getmembers(inst, inspect.ismethod):
                if name.startswith("_"):
                    continue
                methods[name] = value
            return methods

        baseclass = baseinst.__class__.__name__
        basemethods = get_public_apis(baseinst)
        implmethods = get_public_apis(inst)

        extranames = []
        for name in sorted(implmethods.keys()):
            if name not in basemethods:
                extranames.append(name)

        self.assertEqual([], extranames,
                         "public APIs not listed in base class %s" %
                         baseclass)

        for name in sorted(implmethods.keys()):
            baseargs = inspect.getargspec(basemethods[name])
            implargs = inspect.getargspec(implmethods[name])

            self.assertEqual(baseargs, implargs,
                             "%s args don't match base class %s" %
                             (name, baseclass))

class APICoverage(object):

    cover_api = None

    def test_api_methods(self):
        self.assertTrue(self.cover_api is not None)
        api_methods = [x for x in dir(self.cover_api)
                       if not x.startswith('_')]
        test_methods = [x[5:] for x in dir(self)
                        if x.startswith('test_')]
        self.assertThat(
            test_methods,
            testtools.matchers.ContainsAll(api_methods))

class TimeOverride(fixtures.Fixture):
    """Fixture to start and remove time override."""

    def setUp(self):
        super(TimeOverride, self).setUp()
        timeutils.set_time_override()
        self.addCleanup(timeutils.clear_time_override)

class NoDBTestCase(TestCase):
    """`NoDBTestCase` differs from TestCase in that DB access is not supported.
    This makes tests run significantly faster. If possible, all new tests
    should derive from this class.
    """
    USES_DB = False

class BaseHookTestCase(NoDBTestCase):
    def assert_has_hook(self, expected_name, func):
        self.assertTrue(hasattr(func, '__hook_name__'))
        self.assertEqual(expected_name, func.__hook_name__)
<commit_msg>Move WarningsFixture after DatabaseFixture so emit once<commit_after># Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""Base classes for our unit tests.

Allows overriding of flags for use of fakes, and some black magic for
inline callbacks.

"""

import eventlet
eventlet.monkey_patch(os=False)

import copy
import inspect
import mock
import logging
import os

import fixtures
from oslo.config import cfg
from oslo.config import fixture as config_fixture
from oslo.utils import timeutils
from oslo_concurrency import lockutils
from oslotest import moxstubout
import six
import testtools

from nova import context
from nova import db
from nova.network import manager as network_manager
from nova import objects
from nova.objects import base as objects_base
from nova.openstack.common.fixture import logging as log_fixture
from nova.openstack.common import log as nova_logging
from nova.tests import fixtures as nova_fixtures
from nova.tests.unit import conf_fixture
from nova.tests.unit import policy_fixture
from nova import utils

CONF = cfg.CONF
CONF.import_opt('enabled', 'nova.api.openstack', group='osapi_v3')
CONF.set_override('use_stderr', False)

nova_logging.setup('nova')

# NOTE(comstud): Make sure we have all of the objects loaded. We do this
# at module import time, because we may be using mock decorators in our
# tests that run at import time.
objects.register_all()

_TRUE_VALUES = ('True', 'true', '1', 'yes')

class SampleNetworks(fixtures.Fixture):

    """Create sample networks in the database."""

    def __init__(self, host=None):
        self.host = host

    def setUp(self):
        super(SampleNetworks, self).setUp()
        ctxt = context.get_admin_context()
        network = network_manager.VlanManager(host=self.host)
        bridge_interface = CONF.flat_interface or CONF.vlan_interface
        network.create_networks(ctxt,
                                label='test',
                                cidr='10.0.0.0/8',
                                multi_host=CONF.multi_host,
                                num_networks=CONF.num_networks,
                                network_size=CONF.network_size,
                                cidr_v6=CONF.fixed_range_v6,
                                gateway=CONF.gateway,
                                gateway_v6=CONF.gateway_v6,
                                bridge=CONF.flat_network_bridge,
                                bridge_interface=bridge_interface,
                                vpn_start=CONF.vpn_start,
                                vlan_start=CONF.vlan_start,
                                dns1=CONF.flat_network_dns)
        for net in db.network_get_all(ctxt):
            network.set_network_host(ctxt, net)

class TestingException(Exception):
    pass

class NullHandler(logging.Handler):
    """custom default NullHandler to attempt to format the record.

    Used in conjunction with
    log_fixture.get_logging_handle_error_fixture to detect formatting errors in
    debug level logs without saving the logs.
    """
    def handle(self, record):
        self.format(record)

    def emit(self, record):
        pass

    def createLock(self):
        self.lock = None

class skipIf(object):
    def __init__(self, condition, reason):
        self.condition = condition
        self.reason = reason

    def __call__(self, func_or_cls):
        condition = self.condition
        reason = self.reason
        if inspect.isfunction(func_or_cls):
            @six.wraps(func_or_cls)
            def wrapped(*args, **kwargs):
                if condition:
                    raise testtools.TestCase.skipException(reason)
                return func_or_cls(*args, **kwargs)

            return wrapped
        elif inspect.isclass(func_or_cls):
            orig_func = getattr(func_or_cls, 'setUp')

            @six.wraps(orig_func)
            def new_func(self, *args, **kwargs):
                if condition:
                    raise testtools.TestCase.skipException(reason)
                orig_func(self, *args, **kwargs)

            func_or_cls.setUp = new_func
            return func_or_cls
        else:
            raise TypeError('skipUnless can be used only with functions or '
                            'classes')

def _patch_mock_to_raise_for_invalid_assert_calls():
    def raise_for_invalid_assert_calls(wrapped):
        def wrapper(_self, name):
            valid_asserts = [
                'assert_called_with',
                'assert_called_once_with',
                'assert_has_calls',
                'assert_any_calls']

            if name.startswith('assert') and name not in valid_asserts:
                raise AttributeError('%s is not a valid mock assert method'
                                     % name)

            return wrapped(_self, name)
        return wrapper
    mock.Mock.__getattr__ = raise_for_invalid_assert_calls(
        mock.Mock.__getattr__)

# NOTE(gibi): needs to be called only once at import time
# to patch the mock lib
_patch_mock_to_raise_for_invalid_assert_calls()

class TestCase(testtools.TestCase):
    """Test case base class for all unit tests.

    Due to the slowness of DB access, please consider deriving from
    `NoDBTestCase` first.
    """
    USES_DB = True
    REQUIRES_LOCKING = False

    TIMEOUT_SCALING_FACTOR = 1

    def setUp(self):
        """Run before each test method to initialize test environment."""
        super(TestCase, self).setUp()
        self.useFixture(nova_fixtures.Timeout(
            os.environ.get('OS_TEST_TIMEOUT', 0),
            self.TIMEOUT_SCALING_FACTOR))

        self.useFixture(fixtures.NestedTempfile())
        self.useFixture(fixtures.TempHomeDir())
        self.useFixture(nova_fixtures.TranslationFixture())
        self.useFixture(log_fixture.get_logging_handle_error_fixture())

        self.useFixture(nova_fixtures.OutputStreamCapture())

        self.useFixture(nova_fixtures.StandardLogging())

        # NOTE(sdague): because of the way we were using the lock
        # wrapper we eneded up with a lot of tests that started
        # relying on global external locking being set up for them. We
        # consider all of these to be *bugs*. Tests should not require
        # global external locking, or if they do, they should
        # explicitly set it up themselves.
        #
        # The following REQUIRES_LOCKING class parameter is provided
        # as a bridge to get us there. No new tests should be added
        # that require it, and existing classes and tests should be
        # fixed to not need it.
        if self.REQUIRES_LOCKING:
            lock_path = self.useFixture(fixtures.TempDir()).path
            self.fixture = self.useFixture(
                config_fixture.Config(lockutils.CONF))
            self.fixture.config(lock_path=lock_path,
                                group='oslo_concurrency')

        self.useFixture(conf_fixture.ConfFixture(CONF))
        self.useFixture(nova_fixtures.RPCFixture('nova.test'))

        if self.USES_DB:
            self.useFixture(nova_fixtures.Database())

        # NOTE(blk-u): WarningsFixture must be after the Database fixture
        # because sqlalchemy-migrate messes with the warnings filters.
        self.useFixture(nova_fixtures.WarningsFixture())

        # NOTE(danms): Make sure to reset us back to non-remote objects
        # for each test to avoid interactions. Also, backup the object
        # registry.
        objects_base.NovaObject.indirection_api = None
        self._base_test_obj_backup = copy.copy(
            objects_base.NovaObject._obj_classes)
        self.addCleanup(self._restore_obj_registry)

        # NOTE(mnaser): All calls to utils.is_neutron() are cached in
        # nova.utils._IS_NEUTRON.  We set it to None to avoid any
        # caching of that value.
        utils._IS_NEUTRON = None

        mox_fixture = self.useFixture(moxstubout.MoxStubout())
        self.mox = mox_fixture.mox
        self.stubs = mox_fixture.stubs
        self.addCleanup(self._clear_attrs)
        self.useFixture(fixtures.EnvironmentVariable('http_proxy'))
        self.policy = self.useFixture(policy_fixture.PolicyFixture())

    def _restore_obj_registry(self):
        objects_base.NovaObject._obj_classes = self._base_test_obj_backup

    def _clear_attrs(self):
        # Delete attributes that don't start with _ so they don't pin
        # memory around unnecessarily for the duration of the test
        # suite
        for key in [k for k in self.__dict__.keys() if k[0] != '_']:
            del self.__dict__[key]

    def flags(self, **kw):
        """Override flag variables for a test."""
        group = kw.pop('group', None)
        for k, v in kw.iteritems():
            CONF.set_override(k, v, group)

    def start_service(self, name, host=None, **kwargs):
        svc = self.useFixture(
            nova_fixtures.ServiceFixture(name, host, **kwargs))
        return svc.service

    def assertPublicAPISignatures(self, baseinst, inst):
        def get_public_apis(inst):
            methods = {}
            for (name, value) in inspect.getmembers(inst, inspect.ismethod):
                if name.startswith("_"):
                    continue
                methods[name] = value
            return methods

        baseclass = baseinst.__class__.__name__
        basemethods = get_public_apis(baseinst)
        implmethods = get_public_apis(inst)

        extranames = []
        for name in sorted(implmethods.keys()):
            if name not in basemethods:
                extranames.append(name)

        self.assertEqual([], extranames,
                         "public APIs not listed in base class %s" %
                         baseclass)

        for name in sorted(implmethods.keys()):
            baseargs = inspect.getargspec(basemethods[name])
            implargs = inspect.getargspec(implmethods[name])

            self.assertEqual(baseargs, implargs,
                             "%s args don't match base class %s" %
                             (name, baseclass))

class APICoverage(object):

    cover_api = None

    def test_api_methods(self):
        self.assertTrue(self.cover_api is not None)
        api_methods = [x for x in dir(self.cover_api)
                       if not x.startswith('_')]
        test_methods = [x[5:] for x in dir(self)
                        if x.startswith('test_')]
        self.assertThat(
            test_methods,
            testtools.matchers.ContainsAll(api_methods))

class TimeOverride(fixtures.Fixture):
    """Fixture to start and remove time override."""

    def setUp(self):
        super(TimeOverride, self).setUp()
        timeutils.set_time_override()
        self.addCleanup(timeutils.clear_time_override)

class NoDBTestCase(TestCase):
    """`NoDBTestCase` differs from TestCase in that DB access is not supported.
    This makes tests run significantly faster. If possible, all new tests
    should derive from this class.
    """
    USES_DB = False

class BaseHookTestCase(NoDBTestCase):
    def assert_has_hook(self, expected_name, func):
        self.assertTrue(hasattr(func, '__hook_name__'))
        self.assertEqual(expected_name, func.__hook_name__)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Implements the ZMQ Dispatcher responder worker pool.
"""

from .common import zmq_get_address, check_zmq, zmq_connect_socket, zmq_check_nonlocal_address
from .microservice import ZMQMicroservice, ZMQThread
from .protocol import ZMQCauldronMessage, FRAMEFAIL, FRAMEBLANK
from .broker import ZMQBroker
from ..exc import DispatcherError, WrongDispatcher, TimeoutError
from ..config import get_timeout

import json
import collections
import threading
import logging
import weakref
import six
import time
import sys, traceback
import binascii

__all__ = ['ZMQResponder', 'ZMQPooler', 'ZMQDispatcherError']

class ZMQDispatcherError(DispatcherError):
    """Dispatcher error specific to the ZMQ backend."""

def register_dispatcher(service, socket, poller=None, log=None, timeout=None, address=None):
    """Register a dispatcher, and possibly start an automatic broker."""
    zmq = check_zmq()
    timeout = get_timeout(timeout) or 5.0
    b = None
    if not _register_dispatcher(service, socket, poller=poller, log=log, timeout=timeout):
       if service._config.getboolean("zmq", "autobroker"):
           b = _auto_dispatcher(service, socket, poller=poller, log=log, timeout=timeout)
       else:
           raise ZMQDispatcherError("Can't locate a suitable dispatcher.")
    if log is None:
        log = logging.getLogger(__name__ + ".register_dispatcher")
    # Send a start of work message.
    ready = ZMQCauldronMessage(command="ready", direction="DBQ",
        service=service.name, dispatcher=service.dispatcher)
    socket.send(b"", flags=zmq.SNDMORE)
    socket.send_multipart(ready.data)
    log.log(5, "Sent broker a ready message: {0!s}.".format(ready))
    return b

def _auto_dispatcher(service, socket, poller=None, log=None, timeout=None):
    """Use an automatic dispatcher."""
    b = ZMQBroker.sub(config = service._config)
    time.sleep(1.0)
    ZMQBroker.check(config = service._config)
    if not _check_for_registration(service, socket, poller=poller, log=log, timeout=timeout):
        if address is None:
            address = zmq_get_address(service._config, "broker", bind=False)
        socket.disconnect(address)
        socket.connect(address)
        if not _register_dispatcher(service, socket, poller=poller, log=log, timeout=timeout):
            raise TimeoutError("Can't connect to broker in subprocess. timeout={0}".format(timeout))
    return b

def _register_dispatcher(service, socket, poller=None, log=None, timeout=None):
    """Check broker"""
    zmq = check_zmq()

    if log is None:
        log = logging.getLogger(__name__ + "._register_dispatcher")

    # Send a welcome message to register this dispatcher.
    welcome = ZMQCauldronMessage(command="welcome", direction="DBQ",
        service=service.name, dispatcher=service.dispatcher)

    socket.send(b"", flags=zmq.SNDMORE)
    socket.send_multipart(welcome.data)
    log.log(5, "register.send({0!s})".format(welcome))
    return _check_for_registration(service, socket, poller=poller, log=log, timeout=timeout)

def _check_for_registration(service, socket, poller=None, log=None, timeout=None):
    """Check for a ZMQ Registration"""
    zmq = check_zmq()
    if poller is None:
        poller = zmq.Poller()
    poller.register(socket, zmq.POLLIN)

    # Check that we got the welcome message.
    ready = dict(poller.poll(timeout=timeout * 1e3))
    log.log(5, repr(ready) + repr(socket) + repr(zmq.POLLIN))
    if ready.get(socket) == zmq.POLLIN:
        message = ZMQCauldronMessage.parse(socket.recv_multipart())
        if message.payload != "confirmed":
            raise DispatcherError("Message confirming welcome was malformed! {0!s}".format(message))
        return True
    else:
        log.log(5, "register.timeout after {0} seconds.".format(timeout))
        return False

class ZMQPooler(ZMQThread):
    """A thread object for handling pools of ZMQ workers."""
    def __init__(self, service, frontend_address, pool_size=None, timeout=1):
        super(ZMQPooler, self).__init__(name="DFW.Service.{0}.Pool".format(service.name), context=service.ctx)
        self.service = weakref.proxy(service)
        self._backend_address = "inproc://{0}-backend".format(hex(id(self)))
        self._frontend_address = frontend_address
        self._internal_address = "inproc://{0}-internal".format(hex(id(self)))
        self._worker_queue = collections.deque()
        self._worker_timeout = 1.0
        self._active_workers = dict()
        self._directory = dict()
        self._workers = set()
        if pool_size is None:
            pool_size = self.service._config.getint("zmq", "pool")
        self._pool_size = pool_size
        self.timeout = timeout

    @property
    def internal_address(self):
        """Return the internal address for the pooler."""
        return self._internal_address

    def _handle_backend(self, frontend, internal, backend):
        """Handle a backend request."""
        zmq = check_zmq()
        identifier = backend.recv()
        _ = backend.recv()
        if _ != b"":
            raise ValueError("Expected buffer frame, got {!r}".format(binascii.hexlify(_)))
        if len(identifier) == 0:
            raise ValueError("Expected nonzero identity!")
        msg = backend.recv_multipart()
        self._active_workers.pop(identifier, None)
        fori = self._directory.pop(identifier, None)
        if len(msg) == 1 and msg[0] == b"ready":
            self.log.trace("{0}.recv() worker {1} ready".format(self, binascii.hexlify(identifier)))
        elif fori == "F":
            self.log.trace("{0}.broker() B2F {1}".format(self, binascii.hexlify(identifier)))
            frontend.send(b"", flags=zmq.SNDMORE|zmq.NOBLOCK)
            frontend.send_multipart(msg, flags=zmq.NOBLOCK)
        elif fori == "I":
            self.log.trace("{0}.broker() B2I {1}".format(self, binascii.hexlify(identifier)))
            internal.send(b"", flags=zmq.SNDMORE|zmq.NOBLOCK)
            internal.send_multipart(msg, flags=zmq.NOBLOCK)
        self._worker_queue.append(identifier)

    def _handle_frontend(self, frontend, backend, code="F"):
        """Handle a frontend request."""
        zmq = check_zmq()
        _ = frontend.recv()
        msg = frontend.recv_multipart()
        if self.running.isSet():
            worker = self._worker_queue.popleft()
            self.log.trace("{0}.broker() {2}2B {1}".format(self, binascii.hexlify(worker), code))
            backend.send(worker, flags=zmq.SNDMORE)
            backend.send(b"", flags=zmq.SNDMORE)
            backend.send_multipart(msg)
            self._active_workers[worker] = time.time() + self._worker_timeout
            self._directory[worker] = code
        else:
            try:
                response = ZMQCauldronMessage.parse(msg).error_response("Dispatcher shutdown.")
            except Exception:
                pass
            else:
                frontend.send(b"", flags=zmq.SNDMORE)
                frontend.send_multipart(response.data)

    def _poll_and_respond(self, poller, frontend, internal, backend, signal):
        """Poll for messages, handle them."""
        zmq = check_zmq()
        ready = dict(poller.poll(timeout=self.timeout*1e3))
        if not (self.running.isSet() or len(ready)):
            return False
        if signal in ready:
            _ = signal.recv()
            self.log.trace("Got a signal: .running = {0}".format(self.running.is_set()))
            return True
        if backend in ready:
            self._handle_backend(frontend, internal, backend)
        if internal in ready and len(self._worker_queue):
            self._handle_frontend(internal, backend, code='I')
        if frontend in ready and len(self._worker_queue):
            self._handle_frontend(frontend, backend, code='F')
        return True

    def _shutdown_workers(self, frontend, internal, backend):
        """Shut down workers."""

        try:
            # Drain the task queue from workers.
            while len(self._active_workers):
                if backend.poll(timeout=min([self.timeout, self._worker_timeout])*1e3):
                    self._handle_backend(frontend, internal, backend)
                now = time.time()
                for worker in list(self._active_workers.keys()):
                    if now > (self._active_workers[worker]):
                        self._active_workers.pop(worker)
        finally:
            for worker in self._workers:
                worker.signal_stop()
            for worker in self._workers:
                worker.stop(self._worker_timeout)
            self.log.debug("Done with workers.")

    def thread_target(self):
        """Run the thread worker"""
        zmq = check_zmq()
        signal = self.get_signal_socket()

        frontend = self.ctx.socket(zmq.DEALER)
        self.connect(frontend, self._frontend_address)
        internal = self.ctx.socket(zmq.DEALER)
        self.connect(internal, self._internal_address, 'bind')
        backend = self.ctx.socket(zmq.ROUTER)
        self.connect(backend, self._backend_address, 'bind')

        poller = zmq.Poller()
        poller.register(frontend, zmq.POLLIN)
        poller.register(backend, zmq.POLLIN)
        poller.register(internal, zmq.POLLIN)
        poller.register(signal, zmq.POLLIN)

        r_poller = zmq.Poller()
        r_poller.register(frontend, zmq.POLLIN)
        r_poller.register(signal, zmq.POLLIN)

        self.log.debug("Registering dispatcher {0} with broker at {1}".format(self.service.dispatcher, self._frontend_address))
        self.__broker = register_dispatcher(self.service, frontend, r_poller, self.log, address=self._frontend_address)

        self.log.debug("{0} starting workers".format(self))
        for i in range(self._pool_size):
            worker = ZMQWorker(self.service, self._backend_address, n=i)
            self._workers.add(worker)
            worker.start()

        self.log.debug("{0}.running".format(self))
        self.started.set()
        try:
            while self.running.is_set():
                if not self._poll_and_respond(poller, frontend, internal, backend, signal):
                    break
        finally:
            try:
                self._shutdown_workers(frontend, internal, backend)
            finally:
                backend.close(linger=0)
                internal.close(linger=0)
                frontend.close(linger=self.timeout*1e3)
                signal.close(linger=0)

class ZMQWorker(ZMQMicroservice):
    """A ZMQ-based worker"""

    def __init__(self, service, address=None, n=0):
        self.service = service
        if address is None:
            address = zmq_get_address(self.service._config, "broker", bind=False)
        super(ZMQWorker, self).__init__(address=address,
            context=self.service.ctx, name="DFW.Service.{0:s}.Responder.{1:d}".format(self.service.name,n))
        self._broadcaster = None

    def handle_modify(self, message):
        """Handle a modify command."""
        message.verify(self.service)
        keyword = self.service[message.keyword]
        with keyword._lock:
            keyword.modify(message.payload)
        return keyword.value

    def handle_update(self, message):
        """Handle an update command."""
        message.verify(self.service)
        keyword = self.service[message.keyword]
        with keyword._lock:
            value = keyword.update()
        return value

    def handle_identify(self, message):
        """Handle an identify command."""
        message.verify(self.service)
        if message.payload not in self.service:
            self.log.msg("Not identifying b/c not in service.")
            return FRAMEBLANK
        # This seems harsh, not using "CONTAINS", etc,
        # but it handles dispatchers correctly.
        try:
            kwd = self.service[message.payload]
        except WrongDispatcher:
            self.log.msg("Not identifying b/c wrong dispatcher.")
            return FRAMEBLANK
        else:
            ktl_type = kwd.KTL_TYPE
            if ktl_type is None:
                ktl_type = "basic"
            return ktl_type

    def handle_enumerate(self, message):
        """Handle enumerate command."""
        message.verify(self.service)
        return ":".join(self.service.keywords())

    def handle_units(self, message):
        """Handle the units command."""
        message.verify(self.service)
        keyword = self.service[message.keyword]
        #TODO: Not sure if we need the lock here?
        # Probably not, getting units should be *pretty* thread-safe.
        return json.dumps(keyword._get_units())

    def handle_broadcast(self, message):
        """Handle the broadcast command."""
        message.verify(self.service)
        message = ZMQCauldronMessage(command="broadcast", service=self.service.name, dispatcher=self.service.dispatcher, keyword=message.keyword, payload=message.payload, direction="CDB")
        self.log.trace("{0!r}.broadcast({1!s})".format(self, message))
        self._broadcaster.send_multipart(message.data)
        return "success"

    def handle_heartbeat(self, message):
        """Heartbeat command does pretty much nothing."""
        self.log.trace("{0!r}.beat({1!s})".format(self, message))
        return "{0:.1f}".format(time.time())

    def respond(self):
        """Call the responder loop, the main function for this thread."""
        zmq = check_zmq()
        signal = self.get_signal_socket()

        backend = self.ctx.socket(zmq.DEALER)
        self.connect(backend, self.address)

        broadcaster = self.ctx.socket(zmq.PUB)
        self.connect(broadcaster, zmq_get_address(self.service._config, "publish", bind=False))

        self._broadcaster = broadcaster

        poller = zmq.Poller()
        poller.register(backend, zmq.POLLIN)
        poller.register(signal, zmq.POLLIN)

        backend.send_multipart([b"", b"ready"])

        self.started.set()
        self.log.log(5, "Starting responder loop.")
        while self.running.is_set():
            ready = dict(poller.poll(timeout=self.timeout*1e3))
            if not self.running.is_set():
                continue
            if signal in ready:
                _ = signal.recv()
                self.log.log(5, "Got a signal: .running = {0}".format(self.running.is_set()))
                continue
            if backend in ready:
                message = ZMQCauldronMessage.parse(backend.recv_multipart())
                self.log.log(5, "{0!r}.recv({1})".format(self, message))
                response = self.handle(message)
                if self.running.is_set():
                    self.log.log(5, "{0!r}.send({1})".format(self, response))
                    backend.send_multipart(response.data)
                else:
                    self.log.log(5, "{0!r}.drop({1})".format(self, response))

        backend.close(linger=0)
        signal.close(linger=0)
        broadcaster.close(linger=0)

<commit_msg>Log potential keyword deadlocks.<commit_after># -*- coding: utf-8 -*-
"""
Implements the ZMQ Dispatcher responder worker pool.
"""

from .common import zmq_get_address, check_zmq, zmq_connect_socket, zmq_check_nonlocal_address
from .microservice import ZMQMicroservice, ZMQThread
from .protocol import ZMQCauldronMessage, FRAMEFAIL, FRAMEBLANK
from .broker import ZMQBroker
from ..exc import DispatcherError, WrongDispatcher, TimeoutError
from ..config import get_timeout

import json
import collections
import contextlib
import threading
import logging
import weakref
import six
import time
import sys, traceback
import binascii

__all__ = ['ZMQResponder', 'ZMQPooler', 'ZMQDispatcherError']

class ZMQDispatcherError(DispatcherError):
    """Dispatcher error specific to the ZMQ backend."""

def register_dispatcher(service, socket, poller=None, log=None, timeout=None, address=None):
    """Register a dispatcher, and possibly start an automatic broker."""
    zmq = check_zmq()
    timeout = get_timeout(timeout) or 5.0
    b = None
    if not _register_dispatcher(service, socket, poller=poller, log=log, timeout=timeout):
       if service._config.getboolean("zmq", "autobroker"):
           b = _auto_dispatcher(service, socket, poller=poller, log=log, timeout=timeout)
       else:
           raise ZMQDispatcherError("Can't locate a suitable dispatcher.")
    if log is None:
        log = logging.getLogger(__name__ + ".register_dispatcher")
    # Send a start of work message.
    ready = ZMQCauldronMessage(command="ready", direction="DBQ",
        service=service.name, dispatcher=service.dispatcher)
    socket.send(b"", flags=zmq.SNDMORE)
    socket.send_multipart(ready.data)
    log.log(5, "Sent broker a ready message: {0!s}.".format(ready))
    return b

def _auto_dispatcher(service, socket, poller=None, log=None, timeout=None):
    """Use an automatic dispatcher."""
    b = ZMQBroker.sub(config = service._config)
    time.sleep(1.0)
    ZMQBroker.check(config = service._config)
    if not _check_for_registration(service, socket, poller=poller, log=log, timeout=timeout):
        if address is None:
            address = zmq_get_address(service._config, "broker", bind=False)
        socket.disconnect(address)
        socket.connect(address)
        if not _register_dispatcher(service, socket, poller=poller, log=log, timeout=timeout):
            raise TimeoutError("Can't connect to broker in subprocess. timeout={0}".format(timeout))
    return b

def _register_dispatcher(service, socket, poller=None, log=None, timeout=None):
    """Check broker"""
    zmq = check_zmq()

    if log is None:
        log = logging.getLogger(__name__ + "._register_dispatcher")

    # Send a welcome message to register this dispatcher.
    welcome = ZMQCauldronMessage(command="welcome", direction="DBQ",
        service=service.name, dispatcher=service.dispatcher)

    socket.send(b"", flags=zmq.SNDMORE)
    socket.send_multipart(welcome.data)
    log.log(5, "register.send({0!s})".format(welcome))
    return _check_for_registration(service, socket, poller=poller, log=log, timeout=timeout)

def _check_for_registration(service, socket, poller=None, log=None, timeout=None):
    """Check for a ZMQ Registration"""
    zmq = check_zmq()
    if poller is None:
        poller = zmq.Poller()
    poller.register(socket, zmq.POLLIN)

    # Check that we got the welcome message.
    ready = dict(poller.poll(timeout=timeout * 1e3))
    log.log(5, repr(ready) + repr(socket) + repr(zmq.POLLIN))
    if ready.get(socket) == zmq.POLLIN:
        message = ZMQCauldronMessage.parse(socket.recv_multipart())
        if message.payload != "confirmed":
            raise DispatcherError("Message confirming welcome was malformed! {0!s}".format(message))
        return True
    else:
        log.log(5, "register.timeout after {0} seconds.".format(timeout))
        return False

class ZMQPooler(ZMQThread):
    """A thread object for handling pools of ZMQ workers."""
    def __init__(self, service, frontend_address, pool_size=None, timeout=1):
        super(ZMQPooler, self).__init__(name="DFW.Service.{0}.Pool".format(service.name), context=service.ctx)
        self.service = weakref.proxy(service)
        self._backend_address = "inproc://{0}-backend".format(hex(id(self)))
        self._frontend_address = frontend_address
        self._internal_address = "inproc://{0}-internal".format(hex(id(self)))
        self._worker_queue = collections.deque()
        self._worker_timeout = 1.0
        self._active_workers = dict()
        self._directory = dict()
        self._workers = set()
        if pool_size is None:
            pool_size = self.service._config.getint("zmq", "pool")
        self._pool_size = pool_size
        self.timeout = timeout

    @property
    def internal_address(self):
        """Return the internal address for the pooler."""
        return self._internal_address

    def _handle_backend(self, frontend, internal, backend):
        """Handle a backend request."""
        zmq = check_zmq()
        identifier = backend.recv()
        _ = backend.recv()
        if _ != b"":
            raise ValueError("Expected buffer frame, got {!r}".format(binascii.hexlify(_)))
        if len(identifier) == 0:
            raise ValueError("Expected nonzero identity!")
        msg = backend.recv_multipart()
        self._active_workers.pop(identifier, None)
        fori = self._directory.pop(identifier, None)
        if len(msg) == 1 and msg[0] == b"ready":
            self.log.trace("{0}.recv() worker {1} ready".format(self, binascii.hexlify(identifier)))
        elif fori == "F":
            self.log.trace("{0}.broker() B2F {1}".format(self, binascii.hexlify(identifier)))
            frontend.send(b"", flags=zmq.SNDMORE|zmq.NOBLOCK)
            frontend.send_multipart(msg, flags=zmq.NOBLOCK)
        elif fori == "I":
            self.log.trace("{0}.broker() B2I {1}".format(self, binascii.hexlify(identifier)))
            internal.send(b"", flags=zmq.SNDMORE|zmq.NOBLOCK)
            internal.send_multipart(msg, flags=zmq.NOBLOCK)
        self._worker_queue.append(identifier)

    def _handle_frontend(self, frontend, backend, code="F"):
        """Handle a frontend request."""
        zmq = check_zmq()
        _ = frontend.recv()
        msg = frontend.recv_multipart()
        if self.running.isSet():
            worker = self._worker_queue.popleft()
            self.log.trace("{0}.broker() {2}2B {1}".format(self, binascii.hexlify(worker), code))
            backend.send(worker, flags=zmq.SNDMORE)
            backend.send(b"", flags=zmq.SNDMORE)
            backend.send_multipart(msg)
            self._active_workers[worker] = time.time() + self._worker_timeout
            self._directory[worker] = code
        else:
            try:
                response = ZMQCauldronMessage.parse(msg).error_response("Dispatcher shutdown.")
            except Exception:
                pass
            else:
                frontend.send(b"", flags=zmq.SNDMORE)
                frontend.send_multipart(response.data)

    def _poll_and_respond(self, poller, frontend, internal, backend, signal):
        """Poll for messages, handle them."""
        zmq = check_zmq()
        ready = dict(poller.poll(timeout=self.timeout*1e3))
        if not (self.running.isSet() or len(ready)):
            return False
        if signal in ready:
            _ = signal.recv()
            self.log.trace("Got a signal: .running = {0}".format(self.running.is_set()))
            return True
        if backend in ready:
            self._handle_backend(frontend, internal, backend)
        if internal in ready and len(self._worker_queue):
            self._handle_frontend(internal, backend, code='I')
        if frontend in ready and len(self._worker_queue):
            self._handle_frontend(frontend, backend, code='F')
        return True

    def _shutdown_workers(self, frontend, internal, backend):
        """Shut down workers."""

        try:
            # Drain the task queue from workers.
            while len(self._active_workers):
                if backend.poll(timeout=min([self.timeout, self._worker_timeout])*1e3):
                    self._handle_backend(frontend, internal, backend)
                now = time.time()
                for worker in list(self._active_workers.keys()):
                    if now > (self._active_workers[worker]):
                        self._active_workers.pop(worker)
        finally:
            for worker in self._workers:
                worker.signal_stop()
            for worker in self._workers:
                worker.stop(self._worker_timeout)
            self.log.debug("Done with workers.")

    def thread_target(self):
        """Run the thread worker"""
        zmq = check_zmq()
        signal = self.get_signal_socket()

        frontend = self.ctx.socket(zmq.DEALER)
        self.connect(frontend, self._frontend_address)
        internal = self.ctx.socket(zmq.DEALER)
        self.connect(internal, self._internal_address, 'bind')
        backend = self.ctx.socket(zmq.ROUTER)
        self.connect(backend, self._backend_address, 'bind')

        poller = zmq.Poller()
        poller.register(frontend, zmq.POLLIN)
        poller.register(backend, zmq.POLLIN)
        poller.register(internal, zmq.POLLIN)
        poller.register(signal, zmq.POLLIN)

        r_poller = zmq.Poller()
        r_poller.register(frontend, zmq.POLLIN)
        r_poller.register(signal, zmq.POLLIN)

        self.log.debug("Registering dispatcher {0} with broker at {1}".format(self.service.dispatcher, self._frontend_address))
        self.__broker = register_dispatcher(self.service, frontend, r_poller, self.log, address=self._frontend_address)

        self.log.debug("{0} starting workers".format(self))
        for i in range(self._pool_size):
            worker = ZMQWorker(self.service, self._backend_address, n=i)
            self._workers.add(worker)
            worker.start()

        self.log.debug("{0}.running".format(self))
        self.started.set()
        try:
            while self.running.is_set():
                if not self._poll_and_respond(poller, frontend, internal, backend, signal):
                    break
        finally:
            try:
                self._shutdown_workers(frontend, internal, backend)
            finally:
                backend.close(linger=0)
                internal.close(linger=0)
                frontend.close(linger=self.timeout*1e3)
                signal.close(linger=0)

@contextlib.contextmanager
def deadlock_context(lock, log, name):
    """Attempt to detect and warn about deadlocks."""
    locked = lock.acquire(False)
    if not locked:
        log.warning("Deadlock warning for lock {0}".format(name))
        lock.acquire()
    else:
        log.trace("Acquired lock {0}".format(name))
    try:
        yield lock
    finally:
        lock.release()
        log.trace("Released lock {0}".format(name))

class ZMQWorker(ZMQMicroservice):
    """A ZMQ-based worker"""

    def __init__(self, service, address=None, n=0):
        self.service = service
        if address is None:
            address = zmq_get_address(self.service._config, "broker", bind=False)
        super(ZMQWorker, self).__init__(address=address,
            context=self.service.ctx, name="DFW.Service.{0:s}.Responder.{1:d}".format(self.service.name,n))
        self._broadcaster = None

    def handle_modify(self, message):
        """Handle a modify command."""
        message.verify(self.service)
        keyword = self.service[message.keyword]
        with deadlock_context(keyword._lock, self.log, keyword.full_name):
            keyword.modify(message.payload)
        return keyword.value

    def handle_update(self, message):
        """Handle an update command."""
        message.verify(self.service)
        keyword = self.service[message.keyword]
        with deadlock_context(keyword._lock, self.log, keyword.full_name):
            value = keyword.update()
        return value

    def handle_identify(self, message):
        """Handle an identify command."""
        message.verify(self.service)
        if message.payload not in self.service:
            self.log.msg("Not identifying b/c not in service.")
            return FRAMEBLANK
        # This seems harsh, not using "CONTAINS", etc,
        # but it handles dispatchers correctly.
        try:
            kwd = self.service[message.payload]
        except WrongDispatcher:
            self.log.msg("Not identifying b/c wrong dispatcher.")
            return FRAMEBLANK
        else:
            ktl_type = kwd.KTL_TYPE
            if ktl_type is None:
                ktl_type = "basic"
            return ktl_type

    def handle_enumerate(self, message):
        """Handle enumerate command."""
        message.verify(self.service)
        return ":".join(self.service.keywords())

    def handle_units(self, message):
        """Handle the units command."""
        message.verify(self.service)
        keyword = self.service[message.keyword]
        #TODO: Not sure if we need the lock here?
        # Probably not, getting units should be *pretty* thread-safe.
        return json.dumps(keyword._get_units())

    def handle_broadcast(self, message):
        """Handle the broadcast command."""
        message.verify(self.service)
        message = ZMQCauldronMessage(command="broadcast", service=self.service.name, dispatcher=self.service.dispatcher, keyword=message.keyword, payload=message.payload, direction="CDB")
        self.log.trace("{0!r}.broadcast({1!s})".format(self, message))
        self._broadcaster.send_multipart(message.data)
        return "success"

    def handle_heartbeat(self, message):
        """Heartbeat command does pretty much nothing."""
        self.log.trace("{0!r}.beat({1!s})".format(self, message))
        return "{0:.1f}".format(time.time())

    def respond(self):
        """Call the responder loop, the main function for this thread."""
        zmq = check_zmq()
        signal = self.get_signal_socket()

        backend = self.ctx.socket(zmq.DEALER)
        self.connect(backend, self.address)

        broadcaster = self.ctx.socket(zmq.PUB)
        self.connect(broadcaster, zmq_get_address(self.service._config, "publish", bind=False))

        self._broadcaster = broadcaster

        poller = zmq.Poller()
        poller.register(backend, zmq.POLLIN)
        poller.register(signal, zmq.POLLIN)

        backend.send_multipart([b"", b"ready"])

        self.started.set()
        self.log.log(5, "Starting responder loop.")
        while self.running.is_set():
            ready = dict(poller.poll(timeout=self.timeout*1e3))
            if not self.running.is_set():
                continue
            if signal in ready:
                _ = signal.recv()
                self.log.log(5, "Got a signal: .running = {0}".format(self.running.is_set()))
                continue
            if backend in ready:
                message = ZMQCauldronMessage.parse(backend.recv_multipart())
                self.log.log(5, "{0!r}.recv({1})".format(self, message))
                response = self.handle(message)
                if self.running.is_set():
                    self.log.log(5, "{0!r}.send({1})".format(self, response))
                    backend.send_multipart(response.data)
                else:
                    self.log.log(5, "{0!r}.drop({1})".format(self, response))

        backend.close(linger=0)
        signal.close(linger=0)
        broadcaster.close(linger=0)

<|endoftext|>


<commit_before># Version 1.0

from dronekit import connect, VehicleMode
#from droneapi import connect
import time
import string
import cherrypy
import usb

# Check for APM over usb port, if not present then wait for it to connection...
APM_usb_VendorID=0x2341
APM_usb_ProductID=0x0010
APM_found = False

while (APM_found==False):
	busses = usb.busses()
	for bus in busses:
		devices = bus.devices
		for dev in devices:
			if ((dev.idVendor==APM_usb_VendorID)and(dev.idProduct==APM_usb_ProductID)):
				APM_found = True
				print "APM Found!"
				break
	if (APM_found==False):
		print " APM connection failure: Is the the APM USB connected to Raspberry Pi?"
	time.sleep(5)

print "Connecting to APM module..."
# Now that we found it, connect to it
vehicle = connect('/dev/ttyACM0',wait_ready=True)
speed=0.5;

# Enable web server to be availble on all interfaces
cherrypy.config.update({'server.socket_host': '0.0.0.0'})
#move port to 9000 so it doesnt conflict with the video stream (UV4l)
cherrypy.config.update({'server.socket_port': 9000})

# Don't try anything until apm is ready
#vehicle.armed = True
while not vehicle.armed:
        print " Waiting for vehicle to initialise..."
        time.sleep(1)

### Callbacks ###
#def groundspeed_callback(self, attr_name,value):
	#print "Ground Speed: %s" % self.groundspeed;
#vehicle.add_attribute_listener('groundspeed',groundspeed_callback);

#def location_callback(self, attr_name, value):
#	print "Location: %s" % self.location.global_frame;
#vehicle.add_attribute_listener('location.global_frame',location_callback);

# Battery Monitoring ....
# Allow both voltage only battery monitoring
vehicle.parameters['BATT_MONITOR']=4;

# add callback to see if the BATT_MONITOR changes# add callback to see if the BATT_MONITOR changes
#@vehicle.parameters.on_attribute('BATT_MONITOR')
#def Battert_param_callback(slef, attr_name, value):
#    print " Parameter BATT_MONITOR changed to : %s" % (attr_name,value)

#def wildcard_callback(self, attr_name, value):
#    print "Attribute  %s = %s" % (attr_name, value)
#    vehicle = self; # not needed, just wanted to see if there was a difference
#vehicle.add_attribute_listener('*',wildcard_callback);

#def battery_callback(self, attr_name, value):
#       if self.battery.level < 33:
#			vehicle.mode = VehicleMode("RTL");
#			print "Battery Level Alert: Less than 33%, returning to launch";

#vehicle.add_attribute_listener('battery',battery_callback);

#	def groundspeed_callback(self, attr_name,value):
#        	print "Ground Speed: %d" % value;
#
#	vehicle.add_attribute_listener('groundspeed',groundspeed_callback);

class DroneControl(object):
    # Create a top level html page and supply function buttons
	@cherrypy.expose
	def index(self):
         return """

Rover Sentry Control Page:

            <form action="status">
              <button type="submit">Status</button>
            </form>
            <form action="halt">
              <button type="submit">Halt</button>
            </form>
            <form action="resume">
              <button type="submit">Resume</button>
            </form>
            <form action="home">
              <button type="submit">Home</button>
            </form>
	    <form action="waypoints">
	      <button type="submit">Waypoints</button>
	    </form>
            <form action="exit">
              <button type="submit">Exit</button>
            </form>

        """

	@cherrypy.expose
	def halt(self):
		vehicle.mode = VehicleMode("HOLD");
		vehicle.armed = False;
		vehicle.groundspeed = 0;
		vehicle.airspeed = 0;
		#    while vehicle.groundspeed > 0.1:
		#	vehicle.groundspeed = 0;
		#        	print "Waiting for groundspeed change"
		#        	time.sleep(1)
		return "Vehicle Halted"
	@cherrypy.expose
	def resume(self):
		vehicle.armed = True;
		vehicle.mode = VehicleMode("AUTO");
		vehicle.groundspeed = speed;
		while vehicle.groundspeed < speed:
			vehicle.groundspeed = speed;
			print "Resuming...";
		return "Resume"

	@cherrypy.expose
	def waypoints(self):
		cmds = vehicle.commands;
		cmds.download();
		cmds.wait_ready() # wait until download is complete.
		wp_count = vehicle.commands.count;
		status= " WayPoint Count: %s
" % wp_count
		for waypnt in cmds:
		   status+= "%s
" % waypnt;
		status+= " Home Location: %s" % vehicle.home_location
		return status

	@cherrypy.expose
	def home(self):
		vehicle.armed = True;
		vehicle.mode = VehicleMode("RTL");
		vehicle.groundspeed = speed;
		while vehicle.groundspeed < speed:
			vehicle.groundspeed = speed;
		return "Going Home....";

	@cherrypy.expose
	def exit(self):
		vehicle.close();
		return "Closing the vehicle object"

	@cherrypy.expose
	def status(self):
		cmds = vehicle.commands;
		cmds.download();
		cmds.wait_ready() # wait until download is complete.
		wp_count = vehicle.commands.count;

		#return "Armed: %s \nBattery: %s \nWaypoints: %d \nStatus: %s" % (vehicle.armed,vehicle.battery, wp_count, vehicle.system_status)
		#return "Armed: %s \nWaypoints: %d" % (vehicle.armed, wp_count)
		#return "Status: %s" %(vehicle.system_status)
		status= ""
		status+= "
Rover Sentry Status
"
		status+= "
Dronekit Attributes

"
		status+= " Battery volatge: %s
" % vehicle.battery.voltage
 		status+= "    Bateery current (millamps): %s
" % vehicle.battery.current
		status+= "    Battery level: %s
" % vehicle.battery.level
		status+= " Global Location: %s
" % vehicle.location.global_frame
		status+= " Global Location (relative altitude): %s
" % vehicle.location.global_relative_frame
		status+= " Local Location: %s
" % vehicle.location.local_frame
		status+= " Attitude: %s
" % vehicle.attitude
		status+= " Velocity: %s
" % vehicle.velocity
		status+= " GPS: %s
" % vehicle.gps_0
		status+= " Gimbal status: %s
" % vehicle.gimbal
		status+= " Last Heartbeat: %s
" % vehicle.last_heartbeat
		status+= " Rangefinder: %s
" % vehicle.rangefinder
		status+= " Rangefinder distance: %s
" % vehicle.rangefinder.distance
		status+= " Rangefinder voltage: %s
" % vehicle.rangefinder.voltage
		status+= " Heading: %s
" % vehicle.heading
		status+= " Is Armable?: %s
" % vehicle.is_armable
		status+= " System status: %s
" % vehicle.system_status.state
		status+= " Groundspeed: %s
" % vehicle.groundspeed    # settable
		status+= " Airspeed: %s
" % vehicle.airspeed    # settable
		status+= " Mode: %s
" % vehicle.mode.name    # settable
		status+= " Armed: %s
" % vehicle.armed    # settable
		status+= " WayPoint Count: %s
" % wp_count
		for waypnt in cmds:
		   status+= "%s
" % waypnt;
		status+= " Home Location: %s" % vehicle.home_location
		status+= " Autopilot Firmware version: %s
" % vehicle.version
		status+= "   Major version number: %s
 " % vehicle.version.major
		status+= "   Minor version number: %s
" % vehicle.version.minor
		status+= "   Patch version number: %s
" % vehicle.version.patch
		status+= "   Release type: %s
" % vehicle.version.release
		status+= "   Release version: %s
" % vehicle.version.release_version()
		status+= "   Stable release?: %s
" % vehicle.version.is_stable()
		status+= " Autopilot capabilities
"
		status+= "   Supports MISSION_FLOAT message type: %s
" % vehicle.capabilities.mission_float
		status+= "   Supports PARAM_FLOAT message type: %s
" % vehicle.capabilities.param_float
		status+= "   Supports MISSION_INT message type: %s
" % vehicle.capabilities.mission_int
		status+= "   Supports COMMAND_INT message type: %s
" % vehicle.capabilities.command_int
		status+= "   Supports PARAM_UNION message type: %s
" % vehicle.capabilities.param_union
		status+= "   Supports ftp for file transfers: %s
" % vehicle.capabilities.ftp
		status+= "   Supports commanding attitude offboard: %s
" % vehicle.capabilities.set_attitude_target
		status+= "   Supports commanding position and velocity targets in local NED frame: %s
" % vehicle.capabilities.set_attitude_target_local_ned
		status+= "   Supports set position + velocity targets in global scaled integers: %s
" % vehicle.capabilities.set_altitude_target_global_int
		status+= "   Supports terrain protocol / data handling: %s
" % vehicle.capabilities.terrain
		status+= "   Supports direct actuator control: %s
" % vehicle.capabilities.set_actuator_target
		status+= "   Supports the flight termination command: %s
" % vehicle.capabilities.flight_termination
		status+= "   Supports mission_float message type: %s
" % vehicle.capabilities.mission_float
		status+= "   Supports onboard compass calibration: %s
" % vehicle.capabilities.compass_calibration
		status+= " EKF OK?: %s
" % vehicle.ekf_ok
 		# prints out  parameters found here: http://ardupilot.org/rover/docs/parameters.html
		status+= "
 Dronekit Parameters

"
		for key, value in vehicle.parameters.iteritems():
			status+= "\n\r * Key:%s Value:%s
" % (key,value)
		status+= ""
		return status

if __name__ == '__main__':
    cherrypy.quickstart(DroneControl())
<commit_msg>added class for APM 2.6<commit_after># Version 1.0

from dronekit import connect, VehicleMode, LocationGlobal
import time, string, cherrypy, usb, socket, sys

# Enable web server to be availble on all interfaces
cherrypy.config.update({'server.socket_host': '0.0.0.0'})
#move port to 9000 so it doesnt conflict with the video stream (UV4l)
cherrypy.config.update({'server.socket_port': 9000})

###############################################################################
# APM26
# Control class for interacting with the APM26 module on the Rover Sentry
# Requirements
# * Detects connection with APM26 over USB
# * Supports use of the Dronekit SITL for development (optional)
# * Creates a Dronekit vehicle object
# * Provides Status on the APM and Dronekit connections
# * Provides a vehicle object for the RoverSentry
###############################################################################
class APM26(object):
# Check for APM over usb port.
	APM_usb_VendorID=0x2341 #use specific ID for the curren APM (May change with other APM modules)
	APM_usb_ProductID=0x0010
	connected = False
	found = False
	status = "APM Not Started"
	# Use the test SITL vehicle so we can get a verhicle refernce bdfore attempting to connect
	# Note SITL must be started previously using dronekit-sitl rover-2.50
	print "Looking to see if the Dronekit vehicle simulator is running (SITL) ...."
	try:
		vehicle = connect('tcp:127.0.0.1:5760', wait_ready=True)
	except:
		print "SITL not present, looking for APM"
	# Check the APM module connection by seeing if the USB id of the APM shows up in the USB device list
	# If it is connected then try to connect to the device using dronekit.connect()
	def check(self):
		#vehicle = APM26.vehicle
		APM26.found = False # reset check for APM each time
		#APM_conn = APM26.APM_conn
		VendorID = APM26.APM_usb_VendorID
		ProductID = APM26.APM_usb_ProductID
		#Status=APM26.Status
		busses = usb.busses()
		for bus in busses:
			devices = bus.devices
			for dev in devices:
				if ((dev.idVendor==VendorID)and(dev.idProduct==ProductID)):
					APM26.found = True
					print "APM Found!"
			if(APM26.found == False):
				APM26.status="APM module not found: Is the APM connected via USB?"
				APM26.connected = False   #Set the APM connnection to flase so it get started next time
				print "%s" % APM26.status
				return False
			if(APM26.connected == False):
				try:
					print "Connecting to APM ..."
					APM26.vehicle = connect('/dev/ttyACM0',wait_ready=True)
					APM26.connected = True
					APM26.status="APM Found and connected!"
					print "Connetion Status = %s" % APM26.status
					print "APM connected = %s" % APM26.connected
					# Wait for vehicle to finish setup and get a GPS lock so we can set a new home location
					if APM26.vehicle.mode.name == "INITIALISING":
						print "Waiting for vehicle to initialise"
						time.sleep(1)
					#while APM26.vehicle.gps_0.fix_type < 2:
					#	print "Waiting for GPS...:", APM26.vehicle.gps_0.fix_type
					#	time.sleep(1)
					# modify the home location since ArduPilot sets it to the location when GPS lock is obtained.
					# We want the RoverSentry to return to the start location when it aborts the mission.
					APM26.vehicle.commands.download()
					APM26.vehicle.commands.wait_ready() # wait until download is complete.
					time.sleep(1)
					cmds=APM26.vehicle.commands
					APM26.vehicle.home_location = LocationGlobal(cmds[1].x, cmds[1].y, cmds[1].z)
					#APM26.vehicle.commands.upload()
					#APM26.vehicle.flush()
					print "Initializing Home Waypoint to latitude = %s longitude = %s altitude = %s" % (cmds[1].x, cmds[1].y, cmds[1].z)
					return True
				except Exception as e:
					APM26.status="APM found, but error connecting to APM: Specific Error: %s" %e.message
					print "Error with APM connection: %s" % APM26.status
					APM26.connected = False
					return False

#def wildcard_callback(self, attr_name, value):
#    print "Attribute  %s = %s" % (attr_name, value)
#    vehicle = self; # not needed, just wanted to see if there was a difference
#vehicle.add_attribute_listener('*',wildcard_callback);

#def battery_callback(self, attr_name, value):
#       if self.battery.level < 33:
#			vehicle.mode = VehicleMode("RTL");
#			print "Battery Level Alert: Less than 33%, returning to launch";

#vehicle.add_attribute_listener('battery',battery_callback);

#	def groundspeed_callback(self, attr_name,value):
#        	print "Ground Speed: %d" % value;
#
#	vehicle.add_attribute_listener('groundspeed',groundspeed_callback);

#
#	vehicle.add_attribute_listener('groundspeed',groundspeed_callback);
#APM26.vehicle.add_attribute_listener('gps_0',gps_callback);

#def gps_callback(self, attr_name,value):
# 	print "GPS stuff: %s" % value;

###############################################################################
# DroneControl
# This class is used as the main service on the RaspberryPi for the RoverSentry
# Requirements
# * Provide a basic web page for control: availble at the URL:
#    <raspberrypiaddress>:9000 on your web browser
# * Detect connection for APM module and provide status on webpage if
#    theres a problem with the connection
# * Provide status and diagnotic info during feild tests
# * Provide basic RoverSentry control (Start , Halt, continue)
###############################################################################
class DroneControl(object):
	apm_module=APM26()
	speed = 0.5
	# Create APM connection on CherryPy startup...
	apm_module.check()
	# Create a top level html page and supply function buttons
	@cherrypy.expose
	def index(self):
		DroneControl.apm_module.check()
		print"module = %s and connection = %s " % (DroneControl.apm_module.found,DroneControl.apm_module.connected)
		print"APM Status %s" % DroneControl.apm_module.status
		if ((DroneControl.apm_module.connected == False)or(DroneControl.apm_module.found == False)):
			msg="
Error connecting to APM module!
"
			msg+="Error: %s" % APM26.status
			msg+="<form action=\"connect\"> <button type=\"submit\"> Retry</button></form>"
			return msg
		else:
			return """

Rover Sentry Control Page:

<form action="status">
              <button type="submit">Status</button>
            </form>

<form action="halt">
              <button type="submit">Halt</button>
            </form>

<form action="resume">
              <button type="submit">Resume</button>
            </form>

<form action="home">
              <button type="submit">Home</button>
            </form>

<form action="waypoints">
			  <button type="submit">Waypoints</button>
			</form>

<form action="exit">
              <button type="submit">Exit</button>
            </form>

        """
	###########################################################################
	# Check to see if APM module is there and refresh the page right after
	###########################################################################
	@cherrypy.expose
	def connect(self):
		DroneControl.apm_module.check()
		ip = socket.gethostname()
		msg = "  " % ip
		print "url=%s" % msg
		return msg
	###########################################################################
	# Stop the Rover wherever it is
	###########################################################################
	@cherrypy.expose
	def halt(self):
		DroneControl.apm_module.vehicle.mode = VehicleMode("HOLD");
		DroneControl.apm_module.vehicle.armed = False;
		DroneControl.apm_module.vehicle.groundspeed = 0;
		DroneControl.apm_module.vehicle.airspeed = 0;
		#    while vehicle.groundspeed > 0.1:
		#	vehicle.groundspeed = 0;
		#        	print "Waiting for groundspeed change"
		#        	time.sleep(1)
		return "Vehicle Halted"
	############################################################################
	# Start or Continue the mission (after a Halt)
	############################################################################
	@cherrypy.expose
	def resume(self):
		DroneControl.apm_module.vehicle.armed = True;
		DroneControl.apm_module.vehicle.mode = VehicleMode("AUTO");
		DroneControl.apm_module.vehicle.groundspeed = DroneControl.speed;
		while DroneControl.apm_module.vehicle.groundspeed < DroneControl.speed:
			DroneControl.apm_module.vehicle.groundspeed = DroneControl.speed;
			time.sleep(1)
			print "Resuming...";
		return "Resume"
	###########################################################################
	# Reteive Mission (waypoints) from APM module and list on the webpage
	###########################################################################
	@cherrypy.expose
	def waypoints(self):
		vehicle = APM26.vehicle
		DroneControl.apm_module.vehicle.commands.download()
		DroneControl.apm_module.vehicle.commands.wait_ready()
		cmds = DroneControl.apm_module.vehicle.commands
		wp_count = vehicle.commands.count;
		msg= "
Rover Sentry Mission (Waypoints)
"
		msg+= " WayPoint Count: %s
" % wp_count
		counter=0;
		for waypnt in cmds:
			msg+= "    Waypoint %s:" % counter;
			msg+= " : %s ," % waypnt.x;
			msg+= " longitude: %s " % waypnt.y;
			msg+= " altitude: %s
" % waypnt.z;
			counter += 1
		#APM26.vehicle.home_location = LocationGlobal(cmds[1].x, cmds[1].y, cmds[1].z)
		msg+= " Home Location: %s
" % vehicle.home_location
		msg+= "Current Location: %s
" % vehicle.location.global_frame
		msg+= "Next Waypoint location is Waypoint %s located at lat=%s lon=%s, Alt=%s
" % (cmds.next , cmds[cmds.next-1].x, cmds[cmds.next-1].y, cmds[cmds.next-1].z)
		return msg
	###########################################################################
	# Return to home (Set at Waypint 1 in APM26)
	###########################################################################
	@cherrypy.expose
	def home(self):
		DroneControl.apm_module.vehicle.armed = True;
		DroneControl.apm_module.vehicle.mode = VehicleMode("RTL");
		DroneControl.apm_module.vehicle.groundspeed = DroneControl.speed;
		while DroneControl.apm_module.vehicle.groundspeed < DroneControl.speed:
			DroneControl.apm_module.vehicle.groundspeed = DroneControl.speed;
		return "Going Home....";
	###########################################################################
	# Shutdown the Dronekit Vehicle (Saves power when waiting for use)
	# Use Resume to start up again (will take 15 seconds or more)
	###########################################################################
	@cherrypy.expose
	def exit(self):
		DroneControl.apm_module.vehicle.close();
		APM26.connected = False
		return "Closing the vehicle object"
	###########################################################################
	# List every last bit of status from Dronelit or other sources.
	# Useful for debugging in the feild
	###########################################################################
	@cherrypy.expose
	def status(self):
		vehicle = DroneControl.apm_module.vehicle
		DroneControl.setwaypoint(self)
		cmds = vehicle.commands;
		cmds.download();
		cmds.wait_ready() # wait until download is complete.
		wp_count = vehicle.commands.count;
		#return "Armed: %s \nBattery: %s \nWaypoints: %d \nStatus: %s" % (vehicle.armed,vehicle.battery, wp_count, vehicle.system_status)
		#return "Armed: %s \nWaypoints: %d" % (vehicle.armed, wp_count)
		#return "Status: %s" %(vehicle.system_status)
		status= ""
		status+= "
Rover Sentry Status
"
		status+= "
Dronekit Attributes

"
		status+= " Battery volatge: %s
" % vehicle.battery.voltage
 		status+= "    Bateery current (millamps): %s
" % vehicle.battery.current
		status+= "    Battery level: %s
" % vehicle.battery.level
		status+= " Global Location: %s
" % vehicle.location.global_frame
		status+= " Global Location (relative altitude): %s
" % vehicle.location.global_relative_frame
		status+= " Local Location: %s
" % vehicle.location.local_frame
		status+= " Attitude: %s
" % vehicle.attitude
		status+= " Velocity: %s
" % vehicle.velocity
		status+= " GPS: %s
" % vehicle.gps_0
		status+= " Gimbal status: %s
" % vehicle.gimbal
		status+= " Last Heartbeat: %s
" % vehicle.last_heartbeat
		status+= " Rangefinder: %s
" % vehicle.rangefinder
		status+= " Rangefinder distance: %s
" % vehicle.rangefinder.distance
		status+= " Rangefinder voltage: %s
" % vehicle.rangefinder.voltage
		status+= " Heading: %s
" % vehicle.heading
		status+= " Is Armable?: %s
" % vehicle.is_armable
		status+= " System status: %s
" % vehicle.system_status.state
		status+= " Groundspeed: %s
" % vehicle.groundspeed    # settable
		status+= " Airspeed: %s
" % vehicle.airspeed    # settable
		status+= " Mode: %s
" % vehicle.mode.name    # settable
		status+= " Armed: %s
" % vehicle.armed    # settable
		status+= " WayPoint Count: %s
" % wp_count
		for waypnt in cmds:
		   status+= "%s
" % waypnt;
		status+= " Home Location: %s" % vehicle.home_location
		status+= " Autopilot Firmware version: %s
" % vehicle.version
		status+= "   Major version number: %s
 " % vehicle.version.major
		status+= "   Minor version number: %s
" % vehicle.version.minor
		status+= "   Patch version number: %s
" % vehicle.version.patch
		status+= "   Release type: %s
" % vehicle.version.release
		status+= "   Release version: %s
" % vehicle.version.release_version()
		status+= "   Stable release?: %s
" % vehicle.version.is_stable()
		status+= " Autopilot capabilities
"
		status+= "   Supports MISSION_FLOAT message type: %s
" % vehicle.capabilities.mission_float
		status+= "   Supports PARAM_FLOAT message type: %s
" % vehicle.capabilities.param_float
		status+= "   Supports MISSION_INT message type: %s
" % vehicle.capabilities.mission_int
		status+= "   Supports COMMAND_INT message type: %s
" % vehicle.capabilities.command_int
		status+= "   Supports PARAM_UNION message type: %s
" % vehicle.capabilities.param_union
		status+= "   Supports ftp for file transfers: %s
" % vehicle.capabilities.ftp
		status+= "   Supports commanding attitude offboard: %s
" % vehicle.capabilities.set_attitude_target
		status+= "   Supports commanding position and velocity targets in local NED frame: %s
" % vehicle.capabilities.set_attitude_target_local_ned
		status+= "   Supports set position + velocity targets in global scaled integers: %s
" % vehicle.capabilities.set_altitude_target_global_int
		status+= "   Supports terrain protocol / data handling: %s
" % vehicle.capabilities.terrain
		status+= "   Supports direct actuator control: %s
" % vehicle.capabilities.set_actuator_target
		status+= "   Supports the flight termination command: %s
" % vehicle.capabilities.flight_termination
		status+= "   Supports mission_float message type: %s
" % vehicle.capabilities.mission_float
		status+= "   Supports onboard compass calibration: %s
" % vehicle.capabilities.compass_calibration
		status+= " EKF OK?: %s
" % vehicle.ekf_ok
 		# prints out  parameters found here: http://ardupilot.org/rover/docs/parameters.html
		status+= "
 Dronekit Parameters

"
		for key, value in vehicle.parameters.iteritems():
			status+= "\n\r * Key:%s Value:%s
" % (key,value)
		status+= ""
		return status

	def setwaypoint(self):
		APM26.vehicle.commands.download()
		APM26.vehicle.commands.wait_ready() # wait until download is complete.
		cmds=APM26.vehicle.commands
		APM26.vehicle.home_location = LocationGlobal(cmds[1].x, cmds[1].y, cmds[1].z)
		APM26.vehicle.commands.upload()
		print "Initializing Home Waypoint to latitude = %s longitude = %s altitude = %s" % (cmds[1].x, cmds[1].y, cmds[1].z)

# Start the RoverSentry DronConrol CherryPy Web application
if __name__ == '__main__':
    cherrypy.quickstart(DroneControl())

<|endoftext|>


<commit_before># third party
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import String

# relative
from . import Base

class SetupConfig(Base):
    __tablename__ = "setup"

    id = Column(Integer(), primary_key=True, autoincrement=True)
    domain_name = Column(String(255), default="")
    description = Column(String(255), default="")
    contact = Column(String(255), default="")
    daa = Column(Boolean(), default=False)
    node_id = Column(String(32), default="")
    daa_document = Column(String(255), default="")

    def __str__(self) -> str:
        return f"<Domain Name: {self.domain_name}>"

def create_setup(id: int, domain_name: str, node_id: str) -> SetupConfig:
    return SetupConfig(id=id, domain_name=domain_name, node_id=node_id)
<commit_msg>ADD tags/deployed_on columns at setup table<commit_after># third party
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import Integer
from sqlalchemy import String

# relative
from . import Base

class SetupConfig(Base):
    __tablename__ = "setup"

    id = Column(Integer(), primary_key=True, autoincrement=True)
    domain_name = Column(String(255), default="")
    description = Column(String(255), default="")
    contact = Column(String(255), default="")
    daa = Column(Boolean(), default=False)
    node_id = Column(String(32), default="")
    daa_document = Column(String(255), default="")
    tags = Column(String(255), default="[]")
    deployed_on = Column(DateTime())

    def __str__(self) -> str:
        return f"<Domain Name: {self.domain_name}>"

def create_setup(id: int, domain_name: str, node_id: str) -> SetupConfig:
    return SetupConfig(id=id, domain_name=domain_name, node_id=node_id)
<|endoftext|>


<commit_before>"""The application's Globals object"""

from app_factory import AppFactoryDict

class Globals(object):
    """Globals acts as a container for objects available throughout the
    life of the application
    """

    def __init__(self):
        """One instance of Globals is created during application
        initialization and is available during requests via the 'g'
        variable
        """
        self.widgets = {'home': {}, 'canvas': {}, 'profile': {}, 'preview': {}, 'config':{}} # {viewtype: {name: Widget instance}}
        self.resourceviews = AppFactoryDict() # {name: ResourceView instance}
        self.apps =  AppFactoryDict() # {name: App instance}

        # Our comet data streamer, responsible for polling the data
        # streams, and providing data to the widgets
        #from myfedora.streams import DataStreamer
        #self.datastreamer = DataStreamer()

        FEED_CACHE = "/tmp/moksha-feeds"

        from shove import Shove
        from feedcache.cache import Cache
        self.feed_storage = Shove('file://' + FEED_CACHE)
        self.feed_cache = Cache(self.feed_storage)
<commit_msg>Comment out the Shove object, as we are not using it yet<commit_after>"""The application's Globals object"""

from app_factory import AppFactoryDict

class Globals(object):
    """Globals acts as a container for objects available throughout the
    life of the application
    """

    def __init__(self):
        """One instance of Globals is created during application
        initialization and is available during requests via the 'g'
        variable
        """
        self.widgets = {'home': {}, 'canvas': {}, 'profile': {}, 'preview': {}, 'config':{}} # {viewtype: {name: Widget instance}}
        self.resourceviews = AppFactoryDict() # {name: ResourceView instance}
        self.apps =  AppFactoryDict() # {name: App instance}

        # Our comet data streamer, responsible for polling the data
        # streams, and providing data to the widgets
        #from myfedora.streams import DataStreamer
        #self.datastreamer = DataStreamer()

        #FEED_CACHE = "/tmp/moksha-feeds"

        #from shove import Shove
        #from feedcache.cache import Cache
        #self.feed_storage = Shove('file://' + FEED_CACHE)
        #self.feed_cache = Cache(self.feed_storage)
<|endoftext|>