<commit_before># Copyright (c) 2016 Mirantis, Inc.
# 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.

import requests
import socket
import time

from tempest.clients import Manager as services_manager
from tempest.common import credentials_factory as common_creds
from tempest.common import dynamic_creds
from tempest.common import waiters
from tempest import config
from tempest.lib import base
from tempest.lib import exceptions

from murano_tempest_tests import clients
from murano_tempest_tests import utils

CONF = config.CONF

class BaseApplicationCatalogScenarioTest(base.BaseTestCase):
    """Base test class for Murano Application Catalog Scenario tests."""

    @classmethod
    def setUpClass(cls):
        super(BaseApplicationCatalogScenarioTest, cls).setUpClass()
        cls.resource_setup()

    @classmethod
    def tearDownClass(cls):
        cls.resource_cleanup()
        super(BaseApplicationCatalogScenarioTest, cls).tearDownClass()

    @classmethod
    def get_client_with_isolated_creds(cls, type_of_creds="admin"):

        creds = cls.get_configured_isolated_creds(type_of_creds=type_of_creds)

        os = clients.Manager(credentials=creds)
        client = os.application_catalog_client

        return client

    @classmethod
    def get_configured_isolated_creds(cls, type_of_creds='admin'):
        identity_version = CONF.identity.auth_version
        if identity_version == 'v3':
            cls.admin_role = CONF.identity.admin_role
        else:
            cls.admin_role = 'admin'
        if not hasattr(cls, 'dynamic_cred'):
            cls.dynamic_cred = dynamic_creds.DynamicCredentialProvider(
                identity_version=CONF.identity.auth_version,
                name=cls.__name__, admin_role=cls.admin_role,
                admin_creds=common_creds.get_configured_admin_credentials(
                    'identity_admin'))
        if type_of_creds == 'primary':
            creds = cls.dynamic_cred.get_primary_creds()
        elif type_of_creds == 'admin':
            creds = cls.dynamic_cred.get_admin_creds()
        elif type_of_creds == 'alt':
            creds = cls.dynamic_cred.get_alt_creds()
        else:
            creds = cls.dynamic_cred.get_credentials(type_of_creds)
        cls.dynamic_cred.type_of_creds = type_of_creds

        return creds.credentials

    @classmethod
    def verify_nonempty(cls, *args):
        if not all(args):
            msg = "Missing API credentials in configuration."
            raise cls.skipException(msg)

    @classmethod
    def resource_setup(cls):
        if not CONF.service_available.murano:
            skip_msg = "Murano is disabled"
            raise cls.skipException(skip_msg)
        if not hasattr(cls, "os"):
            creds = cls.get_configured_isolated_creds(type_of_creds='primary')
            cls.os = clients.Manager(credentials=creds)
            cls.services_manager = services_manager(creds)
        cls.linux_image = CONF.application_catalog.linux_image
        cls.application_catalog_client = cls.os.application_catalog_client
        cls.artifacts_client = cls.os.artifacts_client
        cls.servers_client = cls.services_manager.servers_client
        cls.orchestration_client = cls.services_manager.orchestration_client
        cls.snapshots_client = cls.services_manager.snapshots_client
        cls.volumes_client = cls.services_manager.volumes_client
        cls.backups_client = cls.services_manager.backups_client

    @classmethod
    def resource_cleanup(cls):
        cls.clear_isolated_creds()

    @classmethod
    def clear_isolated_creds(cls):
        if hasattr(cls, "dynamic_cred"):
            cls.dynamic_cred.clear_creds()

    def environment_delete(self, environment_id, timeout=180):
        self.application_catalog_client.delete_environment(environment_id)

        start_time = time.time()
        while time.time() - start_time > timeout:
            try:
                self.application_catalog_client.get_environment(environment_id)
            except exceptions.NotFound:
                return

    @classmethod
    def purge_stacks(cls):
        stacks = cls.orchestration_client.list_stacks()['stacks']
        for stack in stacks:
            cls.orchestration_client.delete_stack(stack['id'])
            cls.orchestration_client.wait_for_stack_status(stack['id'],
                                                           'DELETE_COMPLETE')

    def get_service(self, environment, session, service_name):
        for service in self.application_catalog_client.get_services_list(
                environment, session):
            if service['name'] == service_name:
                return service

    def get_stack_id(self, environment_id):
        stacks = self.orchestration_client.list_stacks()['stacks']
        for stack in stacks:
            if environment_id in self.orchestration_client.show_stack(
                    stack['id'])['stack']['description']:
                return stack['id']

    def get_stack_template(self, stack):
        return self.orchestration_client.show_template(stack)

    def get_instance_id(self, name):
        instance_list = self.servers_client.list_servers()['servers']
        for instance in instance_list:
            if name in instance['name']:
                return instance['id']

    def apache_cinder(
            self, attributes=None, userName=None, flavor='m1.medium'):
        post_body = {
            "instance": {
                "flavor": flavor,
                "image": self.linux_image,
                "assignFloatingIp": True,
                "availabilityZone": "nova",
                "volumes": attributes,
                "?": {
                    "type": "io.murano.resources.LinuxMuranoInstance",
                    "id": utils.generate_uuid()
                },
                "name": utils.generate_name("testMurano")
            },
            "name": utils.generate_name("ApacheHTTPServer"),
            "userName": userName,
            "?": {
                "_{id}".format(id=utils.generate_uuid()): {
                    "name": "ApacheHTTPServer"
                },
                "type": "io.murano.apps.test.ApacheHttpServerCustom",
                "id": utils.generate_uuid()
            }
        }
        return post_body

    def update_executor(self, flavor='m1.medium'):
        post_body = {
            "instance": {
                "flavor": flavor,
                "image": self.linux_image,
                "assignFloatingIp": True,
                "?": {
                    "type": "io.murano.resources.LinuxMuranoInstance",
                    "id": utils.generate_uuid()
                },
                "name": utils.generate_name('testMurano')
            },
            "name": utils.generate_name('dummy'),
            "?": {
                "type": "io.murano.apps.test.UpdateExecutor",
                "id": utils.generate_uuid()
            }
        }
        return post_body

    def deploy_environment(self, environment, session):
        self.application_catalog_client.deploy_session(environment['id'],
                                                       session['id'])
        return self.wait_for_environment_deploy(environment)

    def wait_for_environment_deploy(self, environment):
        start_time = time.time()
        status = self.application_catalog_client.\
            get_environment(environment['id'])['status']
        while status != 'ready':
            status = self.application_catalog_client.\
                get_environment(environment['id'])['status']
            if time.time() - start_time > 1800:
                time.sleep(60)
                self.fail(
                    'Environment deployment is not finished in 1200 seconds')
            elif status == 'deploy failure':
                time.sleep(60)
                self.fail('Environment has incorrect status {0}'.
                          format(status))
            time.sleep(5)
        return self.application_catalog_client.\
            get_environment(environment['id'])

    def status_check(self, environment_id, configurations):
        for configuration in configurations:
            inst_name = configuration[0]
            ports = configuration[1:]
            ip = self.get_ip_by_instance_name(environment_id, inst_name)
            if ip and ports:
                for port in ports:
                    self.check_port_access(ip, port)
            else:
                self.fail('Instance does not have floating IP')

    def check_path(self, environment_id, path, inst_name=None):
        environment = self.application_catalog_client.\
            get_environment(environment_id)
        if inst_name:
            ip = self.get_ip_by_instance_name(environment_id, inst_name)
        else:
            ip = environment.services[0]['instance']['floatingIpAddress']
        resp = requests.get('http://{0}/{1}'.format(ip, path))
        if resp.status_code == 200:
            return resp
        else:
            self.fail("Service path unavailable")

    def get_ip_by_instance_name(self, environment_id, inst_name):
        for service in self.application_catalog_client.\
                get_services_list(environment_id):
            if inst_name in service['instance']['name']:
                return service['instance']['floatingIpAddress']

    def check_port_access(self, ip, port):
        result = 1
        start_time = time.time()
        while time.time() - start_time < 600:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            result = sock.connect_ex((str(ip), port))
            sock.close()
            if result == 0:
                break
            time.sleep(5)
        self.assertEqual(0, result, '%s port is closed on instance' % port)

    @classmethod
    def create_volume(cls):
        volume = cls.volumes_client.create_volume()['volume']
        waiters.wait_for_volume_status(cls.volumes_client,
                                       volume['id'], 'available')
        return volume['id']

    @classmethod
    def delete_volume(cls, volume_id):
        cls.volumes_client.delete_volume(volume_id)
        is_volume_deleted = False
        while not is_volume_deleted:
            is_volume_deleted = cls.volumes_client.\
                is_resource_deleted(volume_id)
            time.sleep(1)

    def create_snapshot(self, volume_id):
        snapshot = self.snapshots_client.\
            create_snapshot(volume_id=volume_id)['snapshot']
        waiters.wait_for_snapshot_status(self.snapshots_client,
                                         snapshot['id'], 'available')
        return snapshot['id']

    def delete_snapshot(self, snapshot_id):
        self.snapshots_client.delete_snapshot(snapshot_id)
        is_snapshot_deleted = False
        while not is_snapshot_deleted:
            is_snapshot_deleted = self.snapshots_client.\
                is_resource_deleted(snapshot_id)
            time.sleep(1)

    def create_backup(self, volume_id):
        backup = self.backups_client.create_backup(
            volume_id=volume_id,
            force=True)['backup']
        self.backups_client.wait_for_backup_status(backup['id'], 'available')
        return backup['id']

    def delete_backup(self, backup_id):
        self.backups_client.delete_backup(backup_id)
        return self.backups_client.wait_for_backup_deletion(backup_id)

    def get_volume(self, environment_id):
        stack = self.get_stack_id(environment_id)
        stack_outputs = self.orchestration_client.\
            show_stack(stack)['stack']['outputs']
        for output in stack_outputs:
            if 'vol' in output['output_key']:
                volume_id = output['output_value']
                return self.volumes_client.show_volume(volume_id)['volume']

    def check_volume_attached(self, name, volume_id):
        instance_id = self.get_instance_id(name)
        attached_volumes = self.servers_client.\
            list_volume_attachments(instance_id)['volumeAttachments']
        assert attached_volumes[0]['id'] == volume_id

class BaseApplicationCatalogScenarioIsolatedAdminTest(
        BaseApplicationCatalogScenarioTest):

    @classmethod
    def resource_setup(cls):
        creds = cls.get_configured_isolated_creds(type_of_creds='admin')
        cls.os = clients.Manager(credentials=creds)
        cls.services_manager = services_manager(creds)
        super(BaseApplicationCatalogScenarioIsolatedAdminTest, cls).\
            resource_setup()
<commit_msg>Refactor 'wait_for_environment_deploy' function<commit_after># Copyright (c) 2016 Mirantis, Inc.
# 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.

import requests
import socket
import time

from tempest.clients import Manager as services_manager
from tempest.common import credentials_factory as common_creds
from tempest.common import dynamic_creds
from tempest.common import waiters
from tempest import config
from tempest.lib import base
from tempest.lib import exceptions

from murano_tempest_tests import clients
from murano_tempest_tests import utils

CONF = config.CONF

class BaseApplicationCatalogScenarioTest(base.BaseTestCase):
    """Base test class for Murano Application Catalog Scenario tests."""

    @classmethod
    def setUpClass(cls):
        super(BaseApplicationCatalogScenarioTest, cls).setUpClass()
        cls.resource_setup()

    @classmethod
    def tearDownClass(cls):
        cls.resource_cleanup()
        super(BaseApplicationCatalogScenarioTest, cls).tearDownClass()

    @classmethod
    def get_client_with_isolated_creds(cls, type_of_creds="admin"):

        creds = cls.get_configured_isolated_creds(type_of_creds=type_of_creds)

        os = clients.Manager(credentials=creds)
        client = os.application_catalog_client

        return client

    @classmethod
    def get_configured_isolated_creds(cls, type_of_creds='admin'):
        identity_version = CONF.identity.auth_version
        if identity_version == 'v3':
            cls.admin_role = CONF.identity.admin_role
        else:
            cls.admin_role = 'admin'
        if not hasattr(cls, 'dynamic_cred'):
            cls.dynamic_cred = dynamic_creds.DynamicCredentialProvider(
                identity_version=CONF.identity.auth_version,
                name=cls.__name__, admin_role=cls.admin_role,
                admin_creds=common_creds.get_configured_admin_credentials(
                    'identity_admin'))
        if type_of_creds == 'primary':
            creds = cls.dynamic_cred.get_primary_creds()
        elif type_of_creds == 'admin':
            creds = cls.dynamic_cred.get_admin_creds()
        elif type_of_creds == 'alt':
            creds = cls.dynamic_cred.get_alt_creds()
        else:
            creds = cls.dynamic_cred.get_credentials(type_of_creds)
        cls.dynamic_cred.type_of_creds = type_of_creds

        return creds.credentials

    @classmethod
    def verify_nonempty(cls, *args):
        if not all(args):
            msg = "Missing API credentials in configuration."
            raise cls.skipException(msg)

    @classmethod
    def resource_setup(cls):
        if not CONF.service_available.murano:
            skip_msg = "Murano is disabled"
            raise cls.skipException(skip_msg)
        if not hasattr(cls, "os"):
            creds = cls.get_configured_isolated_creds(type_of_creds='primary')
            cls.os = clients.Manager(credentials=creds)
            cls.services_manager = services_manager(creds)
        cls.linux_image = CONF.application_catalog.linux_image
        cls.application_catalog_client = cls.os.application_catalog_client
        cls.artifacts_client = cls.os.artifacts_client
        cls.servers_client = cls.services_manager.servers_client
        cls.orchestration_client = cls.services_manager.orchestration_client
        cls.snapshots_client = cls.services_manager.snapshots_client
        cls.volumes_client = cls.services_manager.volumes_client
        cls.backups_client = cls.services_manager.backups_client

    @classmethod
    def resource_cleanup(cls):
        cls.clear_isolated_creds()

    @classmethod
    def clear_isolated_creds(cls):
        if hasattr(cls, "dynamic_cred"):
            cls.dynamic_cred.clear_creds()

    def environment_delete(self, environment_id, timeout=180):
        self.application_catalog_client.delete_environment(environment_id)

        start_time = time.time()
        while time.time() - start_time > timeout:
            try:
                self.application_catalog_client.get_environment(environment_id)
            except exceptions.NotFound:
                return

    @classmethod
    def purge_stacks(cls):
        stacks = cls.orchestration_client.list_stacks()['stacks']
        for stack in stacks:
            cls.orchestration_client.delete_stack(stack['id'])
            cls.orchestration_client.wait_for_stack_status(stack['id'],
                                                           'DELETE_COMPLETE')

    def get_service(self, environment, session, service_name):
        for service in self.application_catalog_client.get_services_list(
                environment, session):
            if service['name'] == service_name:
                return service

    def get_stack_id(self, environment_id):
        stacks = self.orchestration_client.list_stacks()['stacks']
        for stack in stacks:
            if environment_id in self.orchestration_client.show_stack(
                    stack['id'])['stack']['description']:
                return stack['id']

    def get_stack_template(self, stack):
        return self.orchestration_client.show_template(stack)

    def get_instance_id(self, name):
        instance_list = self.servers_client.list_servers()['servers']
        for instance in instance_list:
            if name in instance['name']:
                return instance['id']

    def apache_cinder(
            self, attributes=None, userName=None, flavor='m1.medium'):
        post_body = {
            "instance": {
                "flavor": flavor,
                "image": self.linux_image,
                "assignFloatingIp": True,
                "availabilityZone": "nova",
                "volumes": attributes,
                "?": {
                    "type": "io.murano.resources.LinuxMuranoInstance",
                    "id": utils.generate_uuid()
                },
                "name": utils.generate_name("testMurano")
            },
            "name": utils.generate_name("ApacheHTTPServer"),
            "userName": userName,
            "?": {
                "_{id}".format(id=utils.generate_uuid()): {
                    "name": "ApacheHTTPServer"
                },
                "type": "io.murano.apps.test.ApacheHttpServerCustom",
                "id": utils.generate_uuid()
            }
        }
        return post_body

    def update_executor(self, flavor='m1.medium'):
        post_body = {
            "instance": {
                "flavor": flavor,
                "image": self.linux_image,
                "assignFloatingIp": True,
                "?": {
                    "type": "io.murano.resources.LinuxMuranoInstance",
                    "id": utils.generate_uuid()
                },
                "name": utils.generate_name('testMurano')
            },
            "name": utils.generate_name('dummy'),
            "?": {
                "type": "io.murano.apps.test.UpdateExecutor",
                "id": utils.generate_uuid()
            }
        }
        return post_body

    def deploy_environment(self, environment, session):
        self.application_catalog_client.deploy_session(environment['id'],
                                                       session['id'])
        timeout = 1800
        deployed_env = utils.wait_for_environment_deploy(environment,
                                                         timeout=timeout)
        if deployed_env['status'] == 'ready':
            return deployed_env
        elif deployed_env['status'] == 'deploying':
            self.fail('Environment deployment is not finished in {} seconds'.
                      format(timeout))
        else:
            self.fail('Environment has status {}'.format(
                deployed_env['status']))

    def status_check(self, environment_id, configurations):
        for configuration in configurations:
            inst_name = configuration[0]
            ports = configuration[1:]
            ip = self.get_ip_by_instance_name(environment_id, inst_name)
            if ip and ports:
                for port in ports:
                    self.check_port_access(ip, port)
            else:
                self.fail('Instance does not have floating IP')

    def check_path(self, environment_id, path, inst_name=None):
        environment = self.application_catalog_client.\
            get_environment(environment_id)
        if inst_name:
            ip = self.get_ip_by_instance_name(environment_id, inst_name)
        else:
            ip = environment.services[0]['instance']['floatingIpAddress']
        resp = requests.get('http://{0}/{1}'.format(ip, path))
        if resp.status_code == 200:
            return resp
        else:
            self.fail("Service path unavailable")

    def get_ip_by_instance_name(self, environment_id, inst_name):
        for service in self.application_catalog_client.\
                get_services_list(environment_id):
            if inst_name in service['instance']['name']:
                return service['instance']['floatingIpAddress']

    def check_port_access(self, ip, port):
        result = 1
        start_time = time.time()
        while time.time() - start_time < 600:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            result = sock.connect_ex((str(ip), port))
            sock.close()
            if result == 0:
                break
            time.sleep(5)
        self.assertEqual(0, result, '%s port is closed on instance' % port)

    @classmethod
    def create_volume(cls):
        volume = cls.volumes_client.create_volume()['volume']
        waiters.wait_for_volume_status(cls.volumes_client,
                                       volume['id'], 'available')
        return volume['id']

    @classmethod
    def delete_volume(cls, volume_id):
        cls.volumes_client.delete_volume(volume_id)
        is_volume_deleted = False
        while not is_volume_deleted:
            is_volume_deleted = cls.volumes_client.\
                is_resource_deleted(volume_id)
            time.sleep(1)

    def create_snapshot(self, volume_id):
        snapshot = self.snapshots_client.\
            create_snapshot(volume_id=volume_id)['snapshot']
        waiters.wait_for_snapshot_status(self.snapshots_client,
                                         snapshot['id'], 'available')
        return snapshot['id']

    def delete_snapshot(self, snapshot_id):
        self.snapshots_client.delete_snapshot(snapshot_id)
        is_snapshot_deleted = False
        while not is_snapshot_deleted:
            is_snapshot_deleted = self.snapshots_client.\
                is_resource_deleted(snapshot_id)
            time.sleep(1)

    def create_backup(self, volume_id):
        backup = self.backups_client.create_backup(
            volume_id=volume_id,
            force=True)['backup']
        self.backups_client.wait_for_backup_status(backup['id'], 'available')
        return backup['id']

    def delete_backup(self, backup_id):
        self.backups_client.delete_backup(backup_id)
        return self.backups_client.wait_for_backup_deletion(backup_id)

    def get_volume(self, environment_id):
        stack = self.get_stack_id(environment_id)
        stack_outputs = self.orchestration_client.\
            show_stack(stack)['stack']['outputs']
        for output in stack_outputs:
            if 'vol' in output['output_key']:
                volume_id = output['output_value']
                return self.volumes_client.show_volume(volume_id)['volume']

    def check_volume_attached(self, name, volume_id):
        instance_id = self.get_instance_id(name)
        attached_volumes = self.servers_client.\
            list_volume_attachments(instance_id)['volumeAttachments']
        assert attached_volumes[0]['id'] == volume_id

class BaseApplicationCatalogScenarioIsolatedAdminTest(
        BaseApplicationCatalogScenarioTest):

    @classmethod
    def resource_setup(cls):
        creds = cls.get_configured_isolated_creds(type_of_creds='admin')
        cls.os = clients.Manager(credentials=creds)
        cls.services_manager = services_manager(creds)
        super(BaseApplicationCatalogScenarioIsolatedAdminTest, cls).\
            resource_setup()
<|endoftext|>


<commit_before>import gzip
from pathlib import Path
from typing import Mapping, Sequence
from urllib.request import urlretrieve

import os

from declarative_parser.parser import Argument, Parser, action
from models import Gene
from utils import jit

REMOTE = 'https://github.com/kn-bibs/pathways-data/raw/master/gsea/msigdb/'
DATA_DIR = Path('data')

def gzip_open_text(path, mode='r'):
    return gzip.open(path, mode + 't')

class GeneSet:

    def __init__(self, name, genes, url=None):
        self.name = name
        self.genes = {Gene(name) for name in genes}
        self.url = url
        self.enrichment = None

        # Following is meant to enable fast __contains__ test:
        # granted, one might want to simply use memory address
        # retrieved with id(gene) but it is not guaranteed to
        # (and will not) work with multiprocessing.
        # On the other hand a set of integers is easily pick-able,
        # as is the integer-holding 'id' attribute of Gene(s).
        # Trivia: set(list-comprehension) is faster than set(generator).
        self.gene_ids = set([gene.id for gene in self.genes])

    def restrict_to_genes(self, genes: Sequence[Gene]):
        """Clear itself of genes which are not in the the provided list.

        Returns: set of genes removed from the dataset
        """
        excessive_genes = self.genes.difference(genes)

        for gene in excessive_genes:
            self.genes.discard(gene)
            self.gene_ids.discard(gene.id)

        return excessive_genes

    def __contains__(self, gene: Gene):
        return gene.id in self.gene_ids

    def __len__(self):
        return len(self.genes)

    def __lt__(self, other):
        return self.enrichment < other.enrichment

    def __repr__(self):
        return f'<GeneSet: {self.name} with {len(self.genes)} genes>'

class MolecularSignatureDatabase:

    def __init__(self, gene_sets: Mapping[str, GeneSet], label=None):
        self.label = label
        self.gene_sets = gene_sets

class GMTSignatureDatabase(MolecularSignatureDatabase):

    def __init__(self, path, label=None):
        self.path = DATA_DIR / path
        gene_sets = self.load()
        super().__init__(gene_sets, label)

    def load(self, opener=open):

        if self.path.suffix.endswith('.gz'):
            opener = gzip_open_text

        gene_sets = {}

        with opener(self.path) as f:
            for line in f:
                name, url, *genes = line.strip().split('\t')
                gene_sets[name] = GeneSet(name, genes, url)

        return gene_sets

class RemoteDatabase(GMTSignatureDatabase):

    def __init__(self, set_name, identifiers='symbols', version=6.1, remote=REMOTE, label=None):
        path = f'{version}/{set_name}.v{version}.{identifiers}.gmt.gz'
        self.raw_path = path
        self.remote = remote
        GMTSignatureDatabase.__init__(self, path, label)

    def fetch(self):
        url = self.remote + str(self.raw_path)
        os.makedirs(self.path.parent, exist_ok=True)
        urlretrieve(url, self.path)

    def load(self, opener=open):
        if not self.path.exists():
            self.fetch()
        return super().load(opener)

DATABASE_PRESETS = {
    'H': (
        'h.all',
        'hallmark gene sets'
    )
}

class DatabaseParser(Parser):
    """Help"""

    __skip_if_absent__ = False

    name_or_path = Argument(
        default='H',
        help='Name of Molecular Signature Database to use. '
             'By default hallmark genes will be used. '
             f'Use one of following: {", ".join(DATABASE_PRESETS)} '
             'or provide a path to custom database (.gmt file). '
             # http://software.broadinstitute.org/gsea/msigdb_license_terms.jsp
             'Please note that due to licencing restrictions data '
             'from following sources: '
             'KEGG, BioCarta and AAAS/STKE Cell Signaling Database '
             'are currently unavailable.'
        ,
    )
    version = Argument(
        default=6.1
    )
    identifiers = Argument(
        choices=['symbols', 'entrez'],
        default='symbols'
    )
    remote = Argument(
        # we may want to create a mirror when things go serious to
        # do not overuse BI and to gain independence
        default=REMOTE
    )

    @action
    def show_gene_sets(namespace):
        try:
            parser = DatabaseParser(**vars(namespace))
            db = parser.produce(None).database
        except Exception as e:
            print(e)
            raise
        for name, gene_set in db.gene_sets.items():
            print(name, gene_set.url)

    def produce(self, unknown_args):
        n = self.namespace
        name = n.name_or_path

        # try to get one of pre-defined database by name
        if name in DATABASE_PRESETS:
            set_name, label = DATABASE_PRESETS[name]

            n.database = RemoteDatabase(
                set_name, label=label,
                version=n.version,
                identifiers=n.identifiers,
                remote=n.remote
            )
        else:
            # or to load a database from path
            n.database = GMTSignatureDatabase(name)
        return n
<commit_msg>Minor parsing edge-case fix<commit_after>import gzip
from pathlib import Path
from typing import Mapping, Sequence
from urllib.request import urlretrieve

import os

from declarative_parser.parser import Argument, Parser, action
from models import Gene
from utils import jit

REMOTE = 'https://github.com/kn-bibs/pathways-data/raw/master/gsea/msigdb/'
DATA_DIR = Path('data')

def gzip_open_text(path, mode='r'):
    return gzip.open(path, mode + 't')

class GeneSet:

    def __init__(self, name, genes, url=None):
        self.name = name
        self.genes = {Gene(name) for name in genes}
        self.url = url
        self.enrichment = None

        # Following is meant to enable fast __contains__ test:
        # granted, one might want to simply use memory address
        # retrieved with id(gene) but it is not guaranteed to
        # (and will not) work with multiprocessing.
        # On the other hand a set of integers is easily pick-able,
        # as is the integer-holding 'id' attribute of Gene(s).
        # Trivia: set(list-comprehension) is faster than set(generator).
        self.gene_ids = set([gene.id for gene in self.genes])

    def restrict_to_genes(self, genes: Sequence[Gene]):
        """Clear itself of genes which are not in the the provided list.

        Returns: set of genes removed from the dataset
        """
        excessive_genes = self.genes.difference(genes)

        for gene in excessive_genes:
            self.genes.discard(gene)
            self.gene_ids.discard(gene.id)

        return excessive_genes

    def __contains__(self, gene: Gene):
        return gene.id in self.gene_ids

    def __len__(self):
        return len(self.genes)

    def __lt__(self, other):
        return self.enrichment < other.enrichment

    def __repr__(self):
        return f'<GeneSet: {self.name} with {len(self.genes)} genes>'

class MolecularSignatureDatabase:

    def __init__(self, gene_sets: Mapping[str, GeneSet], label=None):
        self.label = label
        self.gene_sets = gene_sets

class GMTSignatureDatabase(MolecularSignatureDatabase):

    def __init__(self, path, label=None):
        self.path = DATA_DIR / path
        gene_sets = self.load()
        super().__init__(gene_sets, label)

    def load(self, opener=open):

        if self.path.suffix.endswith('.gz'):
            opener = gzip_open_text

        gene_sets = {}

        with opener(self.path) as f:
            for line in f:
                name, url, *genes = line.strip().split('\t')
                gene_sets[name] = GeneSet(name, genes, url)

        return gene_sets

class RemoteDatabase(GMTSignatureDatabase):

    def __init__(self, set_name, identifiers='symbols', version=6.1, remote=REMOTE, label=None):
        path = f'{version}/{set_name}.v{version}.{identifiers}.gmt.gz'
        self.raw_path = path
        self.remote = remote
        GMTSignatureDatabase.__init__(self, path, label)

    def fetch(self):
        url = self.remote + str(self.raw_path)
        os.makedirs(self.path.parent, exist_ok=True)
        urlretrieve(url, self.path)

    def load(self, opener=open):
        if not self.path.exists():
            self.fetch()
        return super().load(opener)

DATABASE_PRESETS = {
    'H': (
        'h.all',
        'hallmark gene sets'
    )
}

class DatabaseParser(Parser):
    """Help"""

    __skip_if_absent__ = False

    name_or_path = Argument(
        default='H',
        help='Name of Molecular Signature Database to use. '
             'By default hallmark genes will be used. '
             f'Use one of following: {", ".join(DATABASE_PRESETS)} '
             'or provide a path to custom database (.gmt file). '
             # http://software.broadinstitute.org/gsea/msigdb_license_terms.jsp
             'Please note that due to licencing restrictions data '
             'from following sources: '
             'KEGG, BioCarta and AAAS/STKE Cell Signaling Database '
             'are currently unavailable.'
        ,
    )
    version = Argument(
        default=6.1
    )
    identifiers = Argument(
        choices=['symbols', 'entrez'],
        default='symbols'
    )
    remote = Argument(
        # we may want to create a mirror when things go serious to
        # do not overuse BI and to gain independence
        default=REMOTE
    )

    @action
    def show_gene_sets(namespace):
        try:
            parser = DatabaseParser(**vars(namespace))
            db = parser.produce(None).database
        except Exception as e:
            print(e)
            raise
        for name, gene_set in db.gene_sets.items():
            print(name, gene_set.url)

    def produce(self, unknown_args):
        n = self.namespace

        # handle nested case
        if hasattr(n, 'database'):
            n = n.database

        name = n.name_or_path

        # try to get one of pre-defined database by name
        if name in DATABASE_PRESETS:
            set_name, label = DATABASE_PRESETS[name]

            n.database = RemoteDatabase(
                set_name, label=label,
                version=n.version,
                identifiers=n.identifiers,
                remote=n.remote
            )
        else:
            # or to load a database from path
            n.database = GMTSignatureDatabase(name)
        return n
<|endoftext|>


<commit_before>from django.db import models

class Suggestion(models.Model):
	YES = 'Y'
	NO = 'N'
	MAYBE = 'M'
	NONE = 'O'
	RESPONSE_CHOICES = (
		(YES, 'Yes'),
		(NO, 'No'),
		(MAYBE, 'Maybe'),
		(NONE, 'No vote'),
	)

	#user=
	response = models.CharField(
		max_length=1,
		choices=RESPONSE_CHOICES,
		default=NONE)
	#suggestion_type=
	time = models.DateTime(
		null=True,
		blank=True
	)
	#location=
	#group=
	#activity=

class Event(models.Model):
	#owner=
	#invites=
	description = models.TextField()
	#location=
	start_time = models.DateTime()
	end_time = models.DateTime(
		null=True,
		blank=True
	)

class Invite(models.Model):
	YES = 'Y'
	NO = 'N'
	MAYBE_YES = 'MY'
	MAYBE_NO = 'MN'
	NONE = 'O'
	RSVP_CHOICES = (
		(YES, 'Yes'),
		(NO, 'No'),
		(MAYBE_YES, 'Maybe Yes'),
		(MAYBE_NO, 'Maybe No'),
		(NONE, 'No response'),
	)
	#event
	#user
	rsvp = models.CharField(
		max_length=2,
		choices=RSVP_CHOICESm
		default=NONE)

<commit_msg>Add location to models<commit_after>from django.db import models

class Suggestion(models.Model):
	YES = 'Y'
	NO = 'N'
	MAYBE = 'M'
	NONE = 'O'
	RESPONSE_CHOICES = (
		(YES, 'Yes'),
		(NO, 'No'),
		(MAYBE, 'Maybe'),
		(NONE, 'No vote'),
	)

	#user=
	response = models.CharField(
		max_length=1,
		choices=RESPONSE_CHOICES,
		default=NONE)
	#suggestion_type=
	time = models.DateTime(
		null=True,
		blank=True
	)
	#location=
	#group=
	#activity=

class Location(models.Model):
	x = models.DecimalField(
		max_digits=10,
		decimal_digits=5
	)
	y = models.DecimalField(
		max_digits=10,
		decimal_digits=5
	)

class Event(models.Model):
	#owner=
	#invites=
	description = models.TextField()
	#location=
	start_time = models.DateTime()
	end_time = models.DateTime(
		null=True,
		blank=True
	)

class Invite(models.Model):
	YES = 'Y'
	NO = 'N'
	MAYBE_YES = 'MY'
	MAYBE_NO = 'MN'
	NONE = 'O'
	RSVP_CHOICES = (
		(YES, 'Yes'),
		(NO, 'No'),
		(MAYBE_YES, 'Maybe Yes'),
		(MAYBE_NO, 'Maybe No'),
		(NONE, 'No response'),
	)
	#event
	#user
	rsvp = models.CharField(
		max_length=2,
		choices=RSVP_CHOICESm
		default=NONE)

<|endoftext|>


<commit_before>from numbers import Number
from list import list_to_str, str_to_list
from sys import stdout
from function import function
from nil import nil, nil_instance
import math
from operator import sub, div
from boolean import boolean
import evaluate_list
import require

def neg(a):
    if not isinstance(a, Number):
        raise TypeError(
            "unsupported operand type(s) for #: '{:s}'".format(
                type(a).__name__
            )
        )

    return -a

def add(a, b):
    if not isinstance(a, Number) or not isinstance(b, Number):
        raise TypeError(
            "unsupported operand type(s) for +: '{:s}' and '{:s}'".format(
                type(a).__name__,
                type(b).__name__
            )
        )

    return a + b

def mul(a, b):
    if not isinstance(a, Number) or not isinstance(b, Number):
        raise TypeError(
            "unsupported operand type(s) for *: '{:s}' and '{:s}'".format(
                type(a).__name__,
                type(b).__name__
            )
        )

    return a * b

def modulo(a, b):
    if (
        not isinstance(a, Number)
        or not float(a).is_integer()
        or not isinstance(b, Number)
        or not float(b).is_integer()
    ):
        raise TypeError(
            "unsupported operand type(s) for %: '{:s}' and '{:s}'".format(
                type(a).__name__,
                type(b).__name__
            )
        )

    return a % b

def print_function(str):
    if not isinstance(str, list):
        raise TypeError(
            "unsupported operand type(s) for print: '{:s}'".format(
                type(str).__name__
            )
        )

    new_str = list_to_str(str)
    stdout.write(new_str)

    return str

def to_string(value):
    return str_to_list(str(value))

def to_number(value):
    if not isinstance(value, list):
        raise TypeError(
            "unsupported operand type(s) for to_num: '{:s}'".format(
                type(value).__name__
            )
        )

    new_value = list_to_str(value)
    return float(new_value)

def while_function(condition, body):
    if not isinstance(condition, function) or not isinstance(body, function):
        raise TypeError(
            "unsupported operand type(s) for while: '{:s}' and '{:s}'".format(
                type(condition).__name__,
                type(body).__name__
            )
        )

    result = nil_instance
    while condition.handle(nil_instance):
        result = body.handle(nil_instance)

    return result

def eval_function(str):
    str = list_to_str(str)
    return evaluate_list.evaluate_string(str)

def type_function(value):
    type_name = ''
    if isinstance(value, nil):
        type_name = 'nil'
    elif isinstance(value, boolean):
        type_name = 'bool'
    elif isinstance(value, int):
        type_name = 'int'
    elif isinstance(value, float):
        type_name = 'num'
    elif isinstance(value, list):
        type_name = 'list'
    elif isinstance(value, function):
        type_name = 'function'
    else:
        raise Exception(
            "value {!s} has unknown type '{:s}'".format(
                value,
                type(value).__name__
            )
        )

    return str_to_list(type_name)

builtin_functions = {
    'nil': function(lambda: nil_instance, arity=0),
    'floor': function(math.floor, arity=1),
    'ceil': function(math.ceil, arity=1),
    'trunc': function(math.trunc, arity=1),
    '#': function(neg, arity=1),
    '+': function(add, arity=2),
    '-': function(sub, arity=2),
    '*': function(mul, arity=2),
    '/': function(div, arity=2),
    '%': function(modulo, arity=2),
    '==': function(lambda a, b: boolean(a == b), arity=2),
    '!=': function(lambda a, b: boolean(a != b), arity=2),
    '<': function(lambda a, b: boolean(float(a) < float(b)), arity=2),
    '<=': function(lambda a, b: boolean(float(a) <= float(b)), arity=2),
    '>': function(lambda a, b: boolean(float(a) > float(b)), arity=2),
    '>=': function(lambda a, b: boolean(float(a) >= float(b)), arity=2),
    'sin': function(lambda a: math.sin(float(a)), arity=1),
    'cos': function(lambda a: math.cos(float(a)), arity=1),
    'tn': function(lambda a: math.tan(float(a)), arity=1),
    'arcsin': function(lambda a: math.asin(float(a)), arity=1),
    'arccos': function(lambda a: math.acos(float(a)), arity=1),
    'arctn': function(lambda a: math.atan(float(a)), arity=1),
    'arctn2': function(lambda a, b: math.atan2(float(a), float(b)), arity=2),
    'sh': function(lambda a: math.sinh(float(a)), arity=1),
    'ch': function(lambda a: math.cosh(float(a)), arity=1),
    'th': function(lambda a: math.tanh(float(a)), arity=1),
    'sqrt': function(lambda a: math.sqrt(float(a)), arity=1),
    'pow': function(lambda a, b: math.pow(float(a), float(b)), arity=2),
    'exp': function(lambda a: math.exp(float(a)), arity=1),
    'ln': function(lambda a: math.log(float(a)), arity=1),
    'lg': function(lambda a: math.log10(float(a)), arity=1),
    'abs': function(lambda a: math.fabs(float(a)), arity=1),
    'true': function(lambda: boolean(True), arity=0),
    'false': function(lambda: boolean(False), arity=0),
    '&&': function(lambda a, b: a and b, arity=2),
    '||': function(lambda a, b: a or b, arity=2),
    '!': function(lambda a: boolean(not a), arity=1),
    'if': function(lambda condition, a, b: a if condition else b, arity=3),
    '$': function(lambda: [], arity=0),
    ':': function(lambda value, list: [value] + list, arity=2),
    'list': function(
        lambda number, value: [value for _ in xrange(number)],
        arity=2
    ),
    'append': function(lambda list, item: list + [item], arity=2),
    'concat': function(lambda list_1, list_2: list_1 + list_2, arity=2),
    'item': function(lambda list, index: list[index], arity=2),
    'len': function(lambda list: len(list), arity=1),
    'print': function(print_function, arity=1),
    'to_str': function(to_string, arity=1),
    'to_num': function(to_number, arity=1),
    'while': function(while_function, arity=2),
    'eval': function(eval_function, arity=1),
    'require': function(require.require, arity=1),
    'require_once': function(require.require_once, arity=1),
    'type': function(type_function, arity=1)
}
<commit_msg>Add exit function.<commit_after>from numbers import Number
from list import list_to_str, str_to_list
from sys import stdout
from function import function
from nil import nil, nil_instance
import math
from operator import sub, div
from boolean import boolean
import evaluate_list
import require

def neg(a):
    if not isinstance(a, Number):
        raise TypeError(
            "unsupported operand type(s) for #: '{:s}'".format(
                type(a).__name__
            )
        )

    return -a

def add(a, b):
    if not isinstance(a, Number) or not isinstance(b, Number):
        raise TypeError(
            "unsupported operand type(s) for +: '{:s}' and '{:s}'".format(
                type(a).__name__,
                type(b).__name__
            )
        )

    return a + b

def mul(a, b):
    if not isinstance(a, Number) or not isinstance(b, Number):
        raise TypeError(
            "unsupported operand type(s) for *: '{:s}' and '{:s}'".format(
                type(a).__name__,
                type(b).__name__
            )
        )

    return a * b

def modulo(a, b):
    if (
        not isinstance(a, Number)
        or not float(a).is_integer()
        or not isinstance(b, Number)
        or not float(b).is_integer()
    ):
        raise TypeError(
            "unsupported operand type(s) for %: '{:s}' and '{:s}'".format(
                type(a).__name__,
                type(b).__name__
            )
        )

    return a % b

def print_function(str):
    if not isinstance(str, list):
        raise TypeError(
            "unsupported operand type(s) for print: '{:s}'".format(
                type(str).__name__
            )
        )

    new_str = list_to_str(str)
    stdout.write(new_str)

    return str

def to_string(value):
    return str_to_list(str(value))

def to_number(value):
    if not isinstance(value, list):
        raise TypeError(
            "unsupported operand type(s) for to_num: '{:s}'".format(
                type(value).__name__
            )
        )

    new_value = list_to_str(value)
    return float(new_value)

def while_function(condition, body):
    if not isinstance(condition, function) or not isinstance(body, function):
        raise TypeError(
            "unsupported operand type(s) for while: '{:s}' and '{:s}'".format(
                type(condition).__name__,
                type(body).__name__
            )
        )

    result = nil_instance
    while condition.handle(nil_instance):
        result = body.handle(nil_instance)

    return result

def eval_function(str):
    str = list_to_str(str)
    return evaluate_list.evaluate_string(str)

def type_function(value):
    type_name = ''
    if isinstance(value, nil):
        type_name = 'nil'
    elif isinstance(value, boolean):
        type_name = 'bool'
    elif isinstance(value, int):
        type_name = 'int'
    elif isinstance(value, float):
        type_name = 'num'
    elif isinstance(value, list):
        type_name = 'list'
    elif isinstance(value, function):
        type_name = 'function'
    else:
        raise Exception(
            "value {!s} has unknown type '{:s}'".format(
                value,
                type(value).__name__
            )
        )

    return str_to_list(type_name)

def exit_function(code):
    if not isinstance(code, int):
        raise TypeError(
            "unsupported operand type(s) for exit: '{:s}'".format(
                type(code).__name__
            )
        )

    return exit(code)

builtin_functions = {
    'nil': function(lambda: nil_instance, arity=0),
    'floor': function(math.floor, arity=1),
    'ceil': function(math.ceil, arity=1),
    'trunc': function(math.trunc, arity=1),
    '#': function(neg, arity=1),
    '+': function(add, arity=2),
    '-': function(sub, arity=2),
    '*': function(mul, arity=2),
    '/': function(div, arity=2),
    '%': function(modulo, arity=2),
    '==': function(lambda a, b: boolean(a == b), arity=2),
    '!=': function(lambda a, b: boolean(a != b), arity=2),
    '<': function(lambda a, b: boolean(float(a) < float(b)), arity=2),
    '<=': function(lambda a, b: boolean(float(a) <= float(b)), arity=2),
    '>': function(lambda a, b: boolean(float(a) > float(b)), arity=2),
    '>=': function(lambda a, b: boolean(float(a) >= float(b)), arity=2),
    'sin': function(lambda a: math.sin(float(a)), arity=1),
    'cos': function(lambda a: math.cos(float(a)), arity=1),
    'tn': function(lambda a: math.tan(float(a)), arity=1),
    'arcsin': function(lambda a: math.asin(float(a)), arity=1),
    'arccos': function(lambda a: math.acos(float(a)), arity=1),
    'arctn': function(lambda a: math.atan(float(a)), arity=1),
    'arctn2': function(lambda a, b: math.atan2(float(a), float(b)), arity=2),
    'sh': function(lambda a: math.sinh(float(a)), arity=1),
    'ch': function(lambda a: math.cosh(float(a)), arity=1),
    'th': function(lambda a: math.tanh(float(a)), arity=1),
    'sqrt': function(lambda a: math.sqrt(float(a)), arity=1),
    'pow': function(lambda a, b: math.pow(float(a), float(b)), arity=2),
    'exp': function(lambda a: math.exp(float(a)), arity=1),
    'ln': function(lambda a: math.log(float(a)), arity=1),
    'lg': function(lambda a: math.log10(float(a)), arity=1),
    'abs': function(lambda a: math.fabs(float(a)), arity=1),
    'true': function(lambda: boolean(True), arity=0),
    'false': function(lambda: boolean(False), arity=0),
    '&&': function(lambda a, b: a and b, arity=2),
    '||': function(lambda a, b: a or b, arity=2),
    '!': function(lambda a: boolean(not a), arity=1),
    'if': function(lambda condition, a, b: a if condition else b, arity=3),
    '$': function(lambda: [], arity=0),
    ':': function(lambda value, list: [value] + list, arity=2),
    'list': function(
        lambda number, value: [value for _ in xrange(number)],
        arity=2
    ),
    'append': function(lambda list, item: list + [item], arity=2),
    'concat': function(lambda list_1, list_2: list_1 + list_2, arity=2),
    'item': function(lambda list, index: list[index], arity=2),
    'len': function(lambda list: len(list), arity=1),
    'print': function(print_function, arity=1),
    'to_str': function(to_string, arity=1),
    'to_num': function(to_number, arity=1),
    'while': function(while_function, arity=2),
    'eval': function(eval_function, arity=1),
    'require': function(require.require, arity=1),
    'require_once': function(require.require_once, arity=1),
    'type': function(type_function, arity=1),
    'exit': function(exit_function, arity=1)
}
<|endoftext|>


<commit_before>"""\
Examples
For the development.ini you must supply the paster app name:

    %(prog)s development.ini --app-name app --init --clear

"""
from pkg_resources import resource_filename
from pyramid.paster import get_app

import atexit
import logging
import os.path
import select
import shutil
import sys
try:
    import subprocess32 as subprocess
except ImportError:
    import subprocess

EPILOG = __doc__

logger = logging.getLogger(__name__)

def nginx_server_process(prefix='', echo=False):
    args = [
        os.path.join(prefix, 'nginx'),
        '-c', resource_filename('snovault', 'nginx-dev.conf'),
        '-g', 'daemon off;'
    ]
    process = subprocess.Popen(
        args,
        close_fds=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
    )

    if not echo:
        process.stdout.close()

    if echo:
        print('Started: http://localhost:8000')

    return process

def main():
    import argparse
    parser = argparse.ArgumentParser(
        description="Run development servers", epilog=EPILOG,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument('--app-name', help="Pyramid app name in configfile")
    parser.add_argument('config_uri', help="path to configfile")
    parser.add_argument('--clear', action="store_true", help="Clear existing data")
    parser.add_argument('--init', action="store_true", help="Init database")
    parser.add_argument('--load', action="store_true", help="Load test set")
    parser.add_argument('--datadir', default='/tmp/snovault', help="path to datadir")
    args = parser.parse_args()

    from snovault.tests import elasticsearch_fixture, postgresql_fixture
    from snovault.elasticsearch import create_mapping
    datadir = os.path.abspath(args.datadir)
    pgdata = os.path.join(datadir, 'pgdata')
    esdata = os.path.join(datadir, 'esdata')
    if args.clear:
        for dirname in [pgdata, esdata]:
            if os.path.exists(dirname):
                shutil.rmtree(dirname)
    if args.init:
        postgresql_fixture.initdb(pgdata, echo=True)

    postgres = postgresql_fixture.server_process(pgdata, echo=True)
    elasticsearch = elasticsearch_fixture.server_process(esdata, echo=True)
    nginx = nginx_server_process(echo=True)
    processes = [postgres, elasticsearch, nginx]

    @atexit.register
    def cleanup_process():
        for process in processes:
            if process.poll() is None:
                process.terminate()
        for process in processes:
            try:
                for line in process.stdout:
                    sys.stdout.write(line.decode('utf-8'))
            except IOError:
                pass
            process.wait()

    if args.init:
        app = get_app(args.config_uri, args.app_name)
        create_mapping.run(app)

    if args.load:
        from pyramid.path import DottedNameResolver
        load_test_data = app.registry.settings.get('snovault.load_test_data')
        load_test_data = DottedNameResolver().resolve(load_test_data)
        load_test_data(app)

    print('Started. ^C to exit.')

    stdouts = [p.stdout for p in processes]

    # Ugly should probably use threads instead
    while True:
        readable, writable, err = select.select(stdouts, [], stdouts, 5)
        for stdout in readable:
            for line in iter(stdout.readline, b''):
                sys.stdout.write(line.decode('utf-8'))
        if err:
            for stdout in err:
                for line in iter(stdout.readline, b''):
                    sys.stdout.write(line.decode('utf-8'))
            break

if __name__ == '__main__':
    main()
<commit_msg>change logging level<commit_after>"""\
Examples
For the development.ini you must supply the paster app name:

    %(prog)s development.ini --app-name app --init --clear

"""
from pkg_resources import resource_filename
from pyramid.paster import get_app

import atexit
import logging
import os.path
import select
import shutil
import sys
try:
    import subprocess32 as subprocess
except ImportError:
    import subprocess

EPILOG = __doc__

logger = logging.getLogger(__name__)

def nginx_server_process(prefix='', echo=False):
    args = [
        os.path.join(prefix, 'nginx'),
        '-c', resource_filename('snovault', 'nginx-dev.conf'),
        '-g', 'daemon off;'
    ]
    process = subprocess.Popen(
        args,
        close_fds=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
    )

    if not echo:
        process.stdout.close()

    if echo:
        print('Started: http://localhost:8000')

    return process

def main():
    import argparse
    parser = argparse.ArgumentParser(
        description="Run development servers", epilog=EPILOG,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    parser.add_argument('--app-name', help="Pyramid app name in configfile")
    parser.add_argument('config_uri', help="path to configfile")
    parser.add_argument('--clear', action="store_true", help="Clear existing data")
    parser.add_argument('--init', action="store_true", help="Init database")
    parser.add_argument('--load', action="store_true", help="Load test set")
    parser.add_argument('--datadir', default='/tmp/snovault', help="path to datadir")
    args = parser.parse_args()

    logging.basicConfig()
    # Loading app will have configured from config file. Reconfigure here:
    logging.getLogger('encoded').setLevel(logging.DEBUG)

    from snovault.tests import elasticsearch_fixture, postgresql_fixture
    from snovault.elasticsearch import create_mapping
    datadir = os.path.abspath(args.datadir)
    pgdata = os.path.join(datadir, 'pgdata')
    esdata = os.path.join(datadir, 'esdata')
    if args.clear:
        for dirname in [pgdata, esdata]:
            if os.path.exists(dirname):
                shutil.rmtree(dirname)
    if args.init:
        postgresql_fixture.initdb(pgdata, echo=True)

    postgres = postgresql_fixture.server_process(pgdata, echo=True)
    elasticsearch = elasticsearch_fixture.server_process(esdata, echo=True)
    nginx = nginx_server_process(echo=True)
    processes = [postgres, elasticsearch, nginx]

    @atexit.register
    def cleanup_process():
        for process in processes:
            if process.poll() is None:
                process.terminate()
        for process in processes:
            try:
                for line in process.stdout:
                    sys.stdout.write(line.decode('utf-8'))
            except IOError:
                pass
            process.wait()

    if args.init:
        app = get_app(args.config_uri, args.app_name)
        create_mapping.run(app)

    if args.load:
        from pyramid.path import DottedNameResolver
        load_test_data = app.registry.settings.get('snovault.load_test_data')
        load_test_data = DottedNameResolver().resolve(load_test_data)
        load_test_data(app)

    print('Started. ^C to exit.')

    stdouts = [p.stdout for p in processes]

    # Ugly should probably use threads instead
    while True:
        readable, writable, err = select.select(stdouts, [], stdouts, 5)
        for stdout in readable:
            for line in iter(stdout.readline, b''):
                sys.stdout.write(line.decode('utf-8'))
        if err:
            for stdout in err:
                for line in iter(stdout.readline, b''):
                    sys.stdout.write(line.decode('utf-8'))
            break

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


<commit_before>"""Stubs for aiohttp HTTP clients"""
import asyncio
import functools
import logging
import json

from aiohttp import ClientConnectionError, ClientResponse, RequestInfo, streams
from aiohttp import hdrs, CookieJar
from http.cookies import CookieError, Morsel, SimpleCookie
from aiohttp.helpers import strip_auth_from_url
from multidict import CIMultiDict, CIMultiDictProxy
from yarl import URL

from vcr.errors import CannotOverwriteExistingCassetteException
from vcr.request import Request

log = logging.getLogger(__name__)

class MockStream(asyncio.StreamReader, streams.AsyncStreamReaderMixin):
    pass

class MockClientResponse(ClientResponse):
    def __init__(self, method, url, request_info=None):
        super().__init__(
            method=method,
            url=url,
            writer=None,
            continue100=None,
            timer=None,
            request_info=request_info,
            traces=None,
            loop=asyncio.get_event_loop(),
            session=None,
        )

    async def json(self, *, encoding="utf-8", loads=json.loads, **kwargs):  # NOQA: E999
        stripped = self._body.strip()
        if not stripped:
            return None

        return loads(stripped.decode(encoding))

    async def text(self, encoding="utf-8", errors="strict"):
        return self._body.decode(encoding, errors=errors)

    async def read(self):
        return self._body

    def release(self):
        pass

    @property
    def content(self):
        s = MockStream()
        s.feed_data(self._body)
        s.feed_eof()
        return s

def build_response(vcr_request, vcr_response, history):
    request_info = RequestInfo(
        url=URL(vcr_request.url),
        method=vcr_request.method,
        headers=_deserialize_headers(vcr_request.headers),
        real_url=URL(vcr_request.url),
    )
    response = MockClientResponse(vcr_request.method, URL(vcr_response.get("url")), request_info=request_info)
    response.status = vcr_response["status"]["code"]
    response._body = vcr_response["body"].get("string", b"")
    response.reason = vcr_response["status"]["message"]
    response._headers = _deserialize_headers(vcr_response["headers"])
    response._history = tuple(history)
    # cookies
    for hdr in response.headers.getall(hdrs.SET_COOKIE, ()):
        try:
            cookies = SimpleCookie(hdr)
            for cookie_name, cookie in cookies.items():
                expires = cookie.get("expires", "").strip()
                if expires:
                    log.debug('Ignoring expiration date: %s="%s"', cookie_name, expires)
                cookie["expires"] = ""
                response.cookies.load(cookie.output(header="").strip())
        except CookieError as exc:
            log.warning("Can not load response cookies: %s", exc)

    response.close()
    return response

def _serialize_headers(headers):
    """Serialize CIMultiDictProxy to a pickle-able dict because proxy
    objects forbid pickling:

    https://github.com/aio-libs/multidict/issues/340
    """
    # Mark strings as keys so 'istr' types don't show up in
    # the cassettes as comments.
    serialized_headers = {}
    for k, v in headers.items():
        serialized_headers.setdefault(str(k), []).append(v)

    return serialized_headers

def _deserialize_headers(headers):
    deserialized_headers = CIMultiDict()
    for k, vs in headers.items():
        if isinstance(vs, list):
            for v in vs:
                deserialized_headers.add(k, v)
        else:
            deserialized_headers.add(k, vs)

    return CIMultiDictProxy(deserialized_headers)

def play_responses(cassette, vcr_request):
    history = []
    vcr_response = cassette.play_response(vcr_request)
    response = build_response(vcr_request, vcr_response, history)

    # If we're following redirects, continue playing until we reach
    # our final destination.
    while 300 <= response.status <= 399:
        if "location" not in response.headers:
            break

        next_url = URL(response.url).join(URL(response.headers["location"]))

        # Make a stub VCR request that we can then use to look up the recorded
        # VCR request saved to the cassette. This feels a little hacky and
        # may have edge cases based on the headers we're providing (e.g. if
        # there's a matcher that is used to filter by headers).
        vcr_request = Request("GET", str(next_url), None, _serialize_headers(response.request_info.headers))
        vcr_requests = cassette.find_requests_with_most_matches(vcr_request)
        for vcr_request, *_ in vcr_requests:
            if cassette.can_play_response_for(vcr_request):
                break

        # Tack on the response we saw from the redirect into the history
        # list that is added on to the final response.
        history.append(response)
        vcr_response = cassette.play_response(vcr_request)
        response = build_response(vcr_request, vcr_response, history)

    return response

async def record_response(cassette, vcr_request, response):
    """Record a VCR request-response chain to the cassette."""

    try:
        body = {"string": (await response.read())}
    # aiohttp raises a ClientConnectionError on reads when
    # there is no body. We can use this to know to not write one.
    except ClientConnectionError:
        body = {}

    vcr_response = {
        "status": {"code": response.status, "message": response.reason},
        "headers": _serialize_headers(response.headers),
        "body": body,  # NOQA: E999
        "url": str(response.url),
    }

    cassette.append(vcr_request, vcr_response)

async def record_responses(cassette, vcr_request, response):
    """Because aiohttp follows redirects by default, we must support
    them by default. This method is used to write individual
    request-response chains that were implicitly followed to get
    to the final destination.
    """

    for past_response in response.history:
        aiohttp_request = past_response.request_info

        # No data because it's following a redirect.
        past_request = Request(
            aiohttp_request.method,
            str(aiohttp_request.url),
            None,
            _serialize_headers(aiohttp_request.headers),
        )
        await record_response(cassette, past_request, past_response)

    # If we're following redirects, then the last request-response
    # we record is the one attached to the `response`.
    if response.history:
        aiohttp_request = response.request_info
        vcr_request = Request(
            aiohttp_request.method,
            str(aiohttp_request.url),
            None,
            _serialize_headers(aiohttp_request.headers),
        )

    await record_response(cassette, vcr_request, response)

def _build_cookie_header(session, cookies, cookie_header, url):
    url, _ = strip_auth_from_url(url)
    all_cookies = session._cookie_jar.filter_cookies(url)
    if cookies is not None:
        tmp_cookie_jar = CookieJar()
        tmp_cookie_jar.update_cookies(cookies)
        req_cookies = tmp_cookie_jar.filter_cookies(url)
        if req_cookies:
            all_cookies.load(req_cookies)

    if not all_cookies and not cookie_header:
        return None

    c = SimpleCookie()
    if cookie_header:
        c.load(cookie_header)
    for name, value in all_cookies.items():
        if isinstance(value, Morsel):
            mrsl_val = value.get(value.key, Morsel())
            mrsl_val.set(value.key, value.value, value.coded_value)
            c[name] = mrsl_val
        else:
            c[name] = value

    return c.output(header="", sep=";").strip()

def vcr_request(cassette, real_request):
    @functools.wraps(real_request)
    async def new_request(self, method, url, **kwargs):
        headers = kwargs.get("headers")
        auth = kwargs.get("auth")
        headers = self._prepare_headers(headers)
        data = kwargs.get("data", kwargs.get("json"))
        params = kwargs.get("params")
        cookies = kwargs.get("cookies")

        if auth is not None:
            headers["AUTHORIZATION"] = auth.encode()

        request_url = URL(url)
        if params:
            for k, v in params.items():
                params[k] = str(v)
            request_url = URL(url).with_query(params)

        c_header = headers.pop(hdrs.COOKIE, None)
        cookie_header = _build_cookie_header(self, cookies, c_header, request_url)
        if cookie_header:
            headers[hdrs.COOKIE] = cookie_header

        vcr_request = Request(method, str(request_url), data, _serialize_headers(headers))

        if cassette.can_play_response_for(vcr_request):
            log.info("Playing response for {} from cassette".format(vcr_request))
            response = play_responses(cassette, vcr_request)
            for redirect in response.history:
                self._cookie_jar.update_cookies(redirect.cookies, redirect.url)
            self._cookie_jar.update_cookies(response.cookies, response.url)
            return response

        if cassette.write_protected and cassette.filter_request(vcr_request):
            raise CannotOverwriteExistingCassetteException(cassette=cassette, failed_request=vcr_request)

        log.info("%s not in cassette, sending to real server", vcr_request)

        response = await real_request(self, method, url, **kwargs)  # NOQA: E999
        await record_responses(cassette, vcr_request, response)
        return response

    return new_request
<commit_msg>aiohttp: Add support to allow_redirects option<commit_after>"""Stubs for aiohttp HTTP clients"""
import asyncio
import functools
import logging
import json

from aiohttp import ClientConnectionError, ClientResponse, RequestInfo, streams
from aiohttp import hdrs, CookieJar
from http.cookies import CookieError, Morsel, SimpleCookie
from aiohttp.helpers import strip_auth_from_url
from multidict import CIMultiDict, CIMultiDictProxy
from yarl import URL

from vcr.errors import CannotOverwriteExistingCassetteException
from vcr.request import Request

log = logging.getLogger(__name__)

class MockStream(asyncio.StreamReader, streams.AsyncStreamReaderMixin):
    pass

class MockClientResponse(ClientResponse):
    def __init__(self, method, url, request_info=None):
        super().__init__(
            method=method,
            url=url,
            writer=None,
            continue100=None,
            timer=None,
            request_info=request_info,
            traces=None,
            loop=asyncio.get_event_loop(),
            session=None,
        )

    async def json(self, *, encoding="utf-8", loads=json.loads, **kwargs):  # NOQA: E999
        stripped = self._body.strip()
        if not stripped:
            return None

        return loads(stripped.decode(encoding))

    async def text(self, encoding="utf-8", errors="strict"):
        return self._body.decode(encoding, errors=errors)

    async def read(self):
        return self._body

    def release(self):
        pass

    @property
    def content(self):
        s = MockStream()
        s.feed_data(self._body)
        s.feed_eof()
        return s

def build_response(vcr_request, vcr_response, history):
    request_info = RequestInfo(
        url=URL(vcr_request.url),
        method=vcr_request.method,
        headers=_deserialize_headers(vcr_request.headers),
        real_url=URL(vcr_request.url),
    )
    response = MockClientResponse(vcr_request.method, URL(vcr_response.get("url")), request_info=request_info)
    response.status = vcr_response["status"]["code"]
    response._body = vcr_response["body"].get("string", b"")
    response.reason = vcr_response["status"]["message"]
    response._headers = _deserialize_headers(vcr_response["headers"])
    response._history = tuple(history)
    # cookies
    for hdr in response.headers.getall(hdrs.SET_COOKIE, ()):
        try:
            cookies = SimpleCookie(hdr)
            for cookie_name, cookie in cookies.items():
                expires = cookie.get("expires", "").strip()
                if expires:
                    log.debug('Ignoring expiration date: %s="%s"', cookie_name, expires)
                cookie["expires"] = ""
                response.cookies.load(cookie.output(header="").strip())
        except CookieError as exc:
            log.warning("Can not load response cookies: %s", exc)

    response.close()
    return response

def _serialize_headers(headers):
    """Serialize CIMultiDictProxy to a pickle-able dict because proxy
    objects forbid pickling:

    https://github.com/aio-libs/multidict/issues/340
    """
    # Mark strings as keys so 'istr' types don't show up in
    # the cassettes as comments.
    serialized_headers = {}
    for k, v in headers.items():
        serialized_headers.setdefault(str(k), []).append(v)

    return serialized_headers

def _deserialize_headers(headers):
    deserialized_headers = CIMultiDict()
    for k, vs in headers.items():
        if isinstance(vs, list):
            for v in vs:
                deserialized_headers.add(k, v)
        else:
            deserialized_headers.add(k, vs)

    return CIMultiDictProxy(deserialized_headers)

def play_responses(cassette, vcr_request, kwargs):
    history = []
    allow_redirects = kwargs.get("allow_redirects", True)
    vcr_response = cassette.play_response(vcr_request)
    response = build_response(vcr_request, vcr_response, history)

    # If we're following redirects, continue playing until we reach
    # our final destination.
    while allow_redirects and 300 <= response.status <= 399:
        if "location" not in response.headers:
            break

        next_url = URL(response.url).join(URL(response.headers["location"]))

        # Make a stub VCR request that we can then use to look up the recorded
        # VCR request saved to the cassette. This feels a little hacky and
        # may have edge cases based on the headers we're providing (e.g. if
        # there's a matcher that is used to filter by headers).
        vcr_request = Request("GET", str(next_url), None, _serialize_headers(response.request_info.headers))
        vcr_requests = cassette.find_requests_with_most_matches(vcr_request)
        for vcr_request, *_ in vcr_requests:
            if cassette.can_play_response_for(vcr_request):
                break

        # Tack on the response we saw from the redirect into the history
        # list that is added on to the final response.
        history.append(response)
        vcr_response = cassette.play_response(vcr_request)
        response = build_response(vcr_request, vcr_response, history)

    return response

async def record_response(cassette, vcr_request, response):
    """Record a VCR request-response chain to the cassette."""

    try:
        body = {"string": (await response.read())}
    # aiohttp raises a ClientConnectionError on reads when
    # there is no body. We can use this to know to not write one.
    except ClientConnectionError:
        body = {}

    vcr_response = {
        "status": {"code": response.status, "message": response.reason},
        "headers": _serialize_headers(response.headers),
        "body": body,  # NOQA: E999
        "url": str(response.url),
    }

    cassette.append(vcr_request, vcr_response)

async def record_responses(cassette, vcr_request, response):
    """Because aiohttp follows redirects by default, we must support
    them by default. This method is used to write individual
    request-response chains that were implicitly followed to get
    to the final destination.
    """

    for past_response in response.history:
        aiohttp_request = past_response.request_info

        # No data because it's following a redirect.
        past_request = Request(
            aiohttp_request.method,
            str(aiohttp_request.url),
            None,
            _serialize_headers(aiohttp_request.headers),
        )
        await record_response(cassette, past_request, past_response)

    # If we're following redirects, then the last request-response
    # we record is the one attached to the `response`.
    if response.history:
        aiohttp_request = response.request_info
        vcr_request = Request(
            aiohttp_request.method,
            str(aiohttp_request.url),
            None,
            _serialize_headers(aiohttp_request.headers),
        )

    await record_response(cassette, vcr_request, response)

def _build_cookie_header(session, cookies, cookie_header, url):
    url, _ = strip_auth_from_url(url)
    all_cookies = session._cookie_jar.filter_cookies(url)
    if cookies is not None:
        tmp_cookie_jar = CookieJar()
        tmp_cookie_jar.update_cookies(cookies)
        req_cookies = tmp_cookie_jar.filter_cookies(url)
        if req_cookies:
            all_cookies.load(req_cookies)

    if not all_cookies and not cookie_header:
        return None

    c = SimpleCookie()
    if cookie_header:
        c.load(cookie_header)
    for name, value in all_cookies.items():
        if isinstance(value, Morsel):
            mrsl_val = value.get(value.key, Morsel())
            mrsl_val.set(value.key, value.value, value.coded_value)
            c[name] = mrsl_val
        else:
            c[name] = value

    return c.output(header="", sep=";").strip()

def vcr_request(cassette, real_request):
    @functools.wraps(real_request)
    async def new_request(self, method, url, **kwargs):
        headers = kwargs.get("headers")
        auth = kwargs.get("auth")
        headers = self._prepare_headers(headers)
        data = kwargs.get("data", kwargs.get("json"))
        params = kwargs.get("params")
        cookies = kwargs.get("cookies")

        if auth is not None:
            headers["AUTHORIZATION"] = auth.encode()

        request_url = URL(url)
        if params:
            for k, v in params.items():
                params[k] = str(v)
            request_url = URL(url).with_query(params)

        c_header = headers.pop(hdrs.COOKIE, None)
        cookie_header = _build_cookie_header(self, cookies, c_header, request_url)
        if cookie_header:
            headers[hdrs.COOKIE] = cookie_header

        vcr_request = Request(method, str(request_url), data, _serialize_headers(headers))

        if cassette.can_play_response_for(vcr_request):
            log.info("Playing response for {} from cassette".format(vcr_request))
            response = play_responses(cassette, vcr_request, kwargs)
            for redirect in response.history:
                self._cookie_jar.update_cookies(redirect.cookies, redirect.url)
            self._cookie_jar.update_cookies(response.cookies, response.url)
            return response

        if cassette.write_protected and cassette.filter_request(vcr_request):
            raise CannotOverwriteExistingCassetteException(cassette=cassette, failed_request=vcr_request)

        log.info("%s not in cassette, sending to real server", vcr_request)

        response = await real_request(self, method, url, **kwargs)  # NOQA: E999
        await record_responses(cassette, vcr_request, response)
        return response

    return new_request
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Pass low-level move commands to motors with mecanum wheels."""

from math import sin, cos, pi, floor, fabs

import driver
import lib.lib as lib

class MechDriver(driver.Driver):

    """Subclass of Driver for movement with mecanum wheels.

    TODO(dfarrell07): Override Driver.move with translate + rotate combo code.

    Motor A = front left
    Motor B = front Right
    Motor C = Back Left
    Motor D = Back Right

    """

    def __init__(self):
        """Run superclass's init."""
        super(MechDriver, self).__init__()

    def iowrite(self, motor, ds, direction):
        """Write to IO pens that control the motors.

        TODO(dfarrell07): This is a stub

        :param motor: Motor to set speed of.
        :type ds: string
        :param ds: Duty cycle that motor should be set to.
        :type ds: float
        """
        self.logger.debug("IO write: motor: {}, ds: {}".format(motor, ds))

    def rotate(self,rotate_speed):
        """Pass rotation speed as -100 to 100 (positive is clockwise)

        """
        self.logger.debug("rotate speed: {}".format(rotate_speed)

        # Determine direction.
        if rotate_speed > 0:
            front_left_forward = True
            front_right_forward = False
            back_left_forward = True
            back_right_foward = False
        else:
            rotate_speed = fabs(rotate_speed)
            front_left_forward = False
            front_right_forward = True
            back_left_forward = False
            back_right_foward = True

        # Check for invalid value.
        if rotate_speed > 100:
            rotate_speed = 100

        # Set duty cycles.
        front_left_ds = fabs(floor(rotate_speed))
        front_right_ds = fabs(floor(rotate_speed))
        back_left_ds = fabs(floor(rotate_speed))
        back_right_ds = fabs(floor(rotate_speed))

        # Write to IO pins.
        # Also remember to write to direction pins.
        self.iowrite("front_left", front_left_ds, front_left_forward)
        self.iowrite("front_right", front_right_ds, front_right_forward)
        self.iowrite("back_left", back_left_ds, back_left_forward)
        self.iowrite("back_right", back_right_ds, back_right_foward)

    def basic_move(self, speed, angle):
        """Build low-level commands for holonomic translations with rotations.

        :param speed: Magnitude of robot's translation speed.
        :type speed: float
        :param angle: Angle in degrees at which robot should translate.
        :type angle: float
        :param rotate_speed: Desired rotational speed.
        :type rotate_speed: float

        """
        self.logger.debug("Speed: {}, angle {}".format(speed, angle))

        # Calculate wheel speed ratios
        # note: This is not the same as the car speed.
        front_left = speed * sin(angle * pi / 180 + pi / 4)
        front_right = speed * cos(angle * pi / 180 + pi / 4)
        back_left = speed * cos(angle * pi / 180 + pi / 4)
        back_right = speed * sin(angle * pi / 180 + pi / 4)

        # Calculate duty cycle as absolute/whole number.
        front_left_ds = fabs(floor(front_left))
        front_right_ds = fabs(floor(front_right))
        back_left_ds = fabs(floor(back_left))
        back_right_ds = fabs(floor(back_right))

        # Prevent invalid duty cycle values.
        if front_left_ds > 100:
            front_left_ds = 100
        if front_right_ds > 100:
            front_right_ds = 100
        if back_left_ds > 100:
            back_left_ds = 100
        if back_right_ds > 100:
            back_right_ds = 100

        # Prevent invalid less than zero duty cycles.
        if front_left_ds < 0:
            front_left_ds = 0
        if front_right_ds < 0:
            front_right_ds = 0
        if back_left_ds < 0:
            back_left_ds = 0
        if back_right_ds < 0:
            back_right_ds = 0

        # Determine direction of wheel.
        # Bool will determine value of direction pin.
        if front_left > 0:
            front_left_forward = True
        else:
            front_left_forward = False
        if front_right > 0:
            front_right_forward = True
        else:
            front_right_forward = False

        if back_left > 0:
            back_left_forward = True
        else:
            back_left_forward = False
        if back_right > 0:
            back_right_foward = True
        else:
            back_right_foward = False

        # Write to IO pins.
        self.iowrite("front_left", front_left_ds)
        self.iowrite("front_right", front_right_ds)
        self.iowrite("back_left", back_left_ds)
        self.iowrite("back_right", back_right_ds)
<commit_msg>Fixed minor bug and PEP8 violations<commit_after>#!/usr/bin/env python
"""Pass low-level move commands to motors with mecanum wheels."""

from math import sin, cos, pi, floor, fabs

import driver
import lib.lib as lib

class MechDriver(driver.Driver):

    """Subclass of Driver for movement with mecanum wheels.

    TODO(dfarrell07): Override Driver.move with translate + rotate combo code.

    Motor A = front left
    Motor B = front Right
    Motor C = Back Left
    Motor D = Back Right

    """

    def __init__(self):
        """Run superclass's init."""
        super(MechDriver, self).__init__()

    def iowrite(self, motor, ds, direction):
        """Write to IO pens that control the motors.

        TODO(dfarrell07): This is a stub

        :param motor: Motor to set speed of.
        :type ds: string
        :param ds: Duty cycle that motor should be set to.
        :type ds: float

        """
        self.logger.debug("IO write: motor: {}, ds: {}".format(motor, ds))

    def rotate(self, rotate_speed):
        """Pass rotation speed as -100 to 100 (positive is clockwise)."""
        self.logger.debug("rotate speed: {}".format(rotate_speed))

        # Determine direction.
        if rotate_speed > 0:
            front_left_forward = True
            front_right_forward = False
            back_left_forward = True
            back_right_foward = False
        else:
            rotate_speed = fabs(rotate_speed)
            front_left_forward = False
            front_right_forward = True
            back_left_forward = False
            back_right_foward = True

        # Check for invalid value.
        if rotate_speed > 100:
            rotate_speed = 100

        # Set duty cycles.
        front_left_ds = fabs(floor(rotate_speed))
        front_right_ds = fabs(floor(rotate_speed))
        back_left_ds = fabs(floor(rotate_speed))
        back_right_ds = fabs(floor(rotate_speed))

        # Write to IO pins.
        # Also remember to write to direction pins.
        self.iowrite("front_left", front_left_ds, front_left_forward)
        self.iowrite("front_right", front_right_ds, front_right_forward)
        self.iowrite("back_left", back_left_ds, back_left_forward)
        self.iowrite("back_right", back_right_ds, back_right_foward)

    def basic_move(self, speed, angle):
        """Build low-level commands for holonomic translations with rotations.

        :param speed: Magnitude of robot's translation speed.
        :type speed: float
        :param angle: Angle in degrees at which robot should translate.
        :type angle: float
        :param rotate_speed: Desired rotational speed.
        :type rotate_speed: float

        """
        self.logger.debug("Speed: {}, angle {}".format(speed, angle))

        # Calculate wheel speed ratios
        # note: This is not the same as the car speed.
        front_left = speed * sin(angle * pi / 180 + pi / 4)
        front_right = speed * cos(angle * pi / 180 + pi / 4)
        back_left = speed * cos(angle * pi / 180 + pi / 4)
        back_right = speed * sin(angle * pi / 180 + pi / 4)

        # Calculate duty cycle as absolute/whole number.
        front_left_ds = fabs(floor(front_left))
        front_right_ds = fabs(floor(front_right))
        back_left_ds = fabs(floor(back_left))
        back_right_ds = fabs(floor(back_right))

        # Prevent invalid duty cycle values.
        if front_left_ds > 100:
            front_left_ds = 100
        if front_right_ds > 100:
            front_right_ds = 100
        if back_left_ds > 100:
            back_left_ds = 100
        if back_right_ds > 100:
            back_right_ds = 100

        # Prevent invalid less than zero duty cycles.
        if front_left_ds < 0:
            front_left_ds = 0
        if front_right_ds < 0:
            front_right_ds = 0
        if back_left_ds < 0:
            back_left_ds = 0
        if back_right_ds < 0:
            back_right_ds = 0

        # Determine direction of wheel.
        # Bool will determine value of direction pin.
        if front_left > 0:
            front_left_forward = True
        else:
            front_left_forward = False
        if front_right > 0:
            front_right_forward = True
        else:
            front_right_forward = False

        if back_left > 0:
            back_left_forward = True
        else:
            back_left_forward = False
        if back_right > 0:
            back_right_foward = True
        else:
            back_right_foward = False

        # Write to IO pins.
        self.iowrite("front_left", front_left_ds)
        self.iowrite("front_right", front_right_ds)
        self.iowrite("back_left", back_left_ds)
        self.iowrite("back_right", back_right_ds)
<|endoftext|>