<commit_before>"""Classes to manage application state."""

import os
import abc
import platform
import functools

import psutil

from . import common

log = common.logger(__name__)

# TODO: delete this after implementing `BaseManager`
# https://github.com/jacebrowning/mine/issues/8
# https://github.com/jacebrowning/mine/issues/9
# pylint: disable=R0903,W0223,E0110

def log_running(func):
    """Decorator for methods that return application status."""
    @functools.wraps(func)
    def wrapped(self, application):
        """Wrapped method to log if an application is running."""
        log.debug("determining if %s is running...", application)
        running = func(self, application)
        if running is None:
            status = "untracked"
        elif running:
            status = "running"
        else:
            status = "not running"
        log.info("%s: %s", status, application)
        return running
    return wrapped

def log_stopping(func):
    """Decorator for methods that stop an application."""
    @functools.wraps(func)
    def wrapped(self, application):
        """Wrapped method to log that an application is being stopped."""
        log.info("stopping %s...", application)
        result = func(self, application)
        log.info("not running: %s", application)
        return result
    return wrapped

class BaseManager(metaclass=abc.ABCMeta):  # pragma: no cover (abstract)

    """Base application manager."""

    NAME = FRIENDLY = None

    def __str__(self):
        return self.FRIENDLY

    @abc.abstractmethod
    def is_running(self, application):
        """Determine if an application is currently running."""
        raise NotImplementedError

# TODO: add this method when a feature calls for it
# https://github.com/jacebrowning/mine/issues/5
#     @abc.abstractclassmethod
#     def start(self, application):
#         """Start an application on the current computer."""
#         raise NotImplementedError

    @abc.abstractmethod
    def stop(self, application):
        """Stop an application on the current computer."""
        raise NotImplementedError

class LinuxManager(BaseManager):  # pragma: no cover (manual)

    """Application manager for Linux."""

    NAME = 'Linux'
    FRIENDLY = NAME

    def is_running(self, application):
        name = application.versions.linux
        if not name:
            return None
        process = self._get_process(name)
        return process is not None

    def stop(self, application):
        name = application.versions.linux
        process = self._get_process(name)
        if process.is_running():
            process.terminate()

    @staticmethod
    def _get_process(name):
        """Get a process whose name matches."""
        for process in psutil.process_iter():
            try:
                if name == process.name():
                    path = process.exe()
                    if process.status() == psutil.STATUS_ZOMBIE:
                        log.debug("skipped zombie process: %s", path)
                    else:
                        log.debug("found matching process: %s", path)
                        return process
            except psutil.AccessDenied:
                pass  # the process is likely owned by root

class MacManager(BaseManager):  # pragma: no cover (manual)

    """Application manager for OS X."""

    NAME = 'Darwin'
    FRIENDLY = 'Mac'

    @log_running
    def is_running(self, application):
        name = application.versions.mac
        if not name:
            return None
        process = self._get_process(name)
        return process is not None

    @log_stopping
    def stop(self, application):
        name = application.versions.mac
        process = self._get_process(name)
        if process.is_running():
            process.terminate()

    @staticmethod
    def _get_process(name):
        """Get a process whose executable path contains an app name."""
        for process in psutil.process_iter():
            try:
                path = process.exe()
                if name in path.split(os.sep):
                    if process.status() == psutil.STATUS_ZOMBIE:
                        log.debug("skipped zombie process: %s", path)
                    else:
                        log.debug("found matching process: %s", path)
                        return process
            except psutil.AccessDenied:
                pass  # the process is likely owned by root

class WindowsManager(BaseManager):  # pragma: no cover (manual)

    """Application manager for Windows."""

    NAME = 'Windows'
    FRIENDLY = NAME

    def is_running(self, application):
        pass

    def stop(self, application):
        pass

def get_manager(name=None):
    """Return an application manager for the current operating system."""
    log.info("detecting the current system...")
    name = name or platform.system()
    if name == WindowsManager.NAME:
        manager = WindowsManager()
    elif name == MacManager.NAME:
        manager = MacManager()
    else:
        assert name == LinuxManager.NAME
        manager = LinuxManager()

    log.info("current system: %s", manager)
    return manager
<commit_msg>Disable coverage for tests on Travis<commit_after>"""Classes to manage application state."""

import os
import abc
import platform
import functools

import psutil

from . import common

log = common.logger(__name__)

# TODO: delete this after implementing `BaseManager`
# https://github.com/jacebrowning/mine/issues/8
# https://github.com/jacebrowning/mine/issues/9
# pylint: disable=R0903,W0223,E0110

# TODO: enable coverage when a Linux test is implemented
def log_running(func):  # pragma: no cover (manual)
    """Decorator for methods that return application status."""
    @functools.wraps(func)
    def wrapped(self, application):
        """Wrapped method to log if an application is running."""
        log.debug("determining if %s is running...", application)
        running = func(self, application)
        if running is None:
            status = "untracked"
        elif running:
            status = "running"
        else:
            status = "not running"
        log.info("%s: %s", status, application)
        return running
    return wrapped

# TODO: enable coverage when a Linux test is implemented
def log_stopping(func):  # pragma: no cover (manual)
    """Decorator for methods that stop an application."""
    @functools.wraps(func)
    def wrapped(self, application):
        """Wrapped method to log that an application is being stopped."""
        log.info("stopping %s...", application)
        result = func(self, application)
        log.info("not running: %s", application)
        return result
    return wrapped

class BaseManager(metaclass=abc.ABCMeta):  # pragma: no cover (abstract)

    """Base application manager."""

    NAME = FRIENDLY = None

    def __str__(self):
        return self.FRIENDLY

    @abc.abstractmethod
    def is_running(self, application):
        """Determine if an application is currently running."""
        raise NotImplementedError

# TODO: add this method when a feature calls for it
# https://github.com/jacebrowning/mine/issues/5
#     @abc.abstractclassmethod
#     def start(self, application):
#         """Start an application on the current computer."""
#         raise NotImplementedError

    @abc.abstractmethod
    def stop(self, application):
        """Stop an application on the current computer."""
        raise NotImplementedError

class LinuxManager(BaseManager):  # pragma: no cover (manual)

    """Application manager for Linux."""

    NAME = 'Linux'
    FRIENDLY = NAME

    def is_running(self, application):
        name = application.versions.linux
        if not name:
            return None
        process = self._get_process(name)
        return process is not None

    def stop(self, application):
        name = application.versions.linux
        process = self._get_process(name)
        if process.is_running():
            process.terminate()

    @staticmethod
    def _get_process(name):
        """Get a process whose name matches."""
        for process in psutil.process_iter():
            try:
                if name == process.name():
                    path = process.exe()
                    if process.status() == psutil.STATUS_ZOMBIE:
                        log.debug("skipped zombie process: %s", path)
                    else:
                        log.debug("found matching process: %s", path)
                        return process
            except psutil.AccessDenied:
                pass  # the process is likely owned by root

class MacManager(BaseManager):  # pragma: no cover (manual)

    """Application manager for OS X."""

    NAME = 'Darwin'
    FRIENDLY = 'Mac'

    @log_running
    def is_running(self, application):
        name = application.versions.mac
        if not name:
            return None
        process = self._get_process(name)
        return process is not None

    @log_stopping
    def stop(self, application):
        name = application.versions.mac
        process = self._get_process(name)
        if process.is_running():
            process.terminate()

    @staticmethod
    def _get_process(name):
        """Get a process whose executable path contains an app name."""
        for process in psutil.process_iter():
            try:
                path = process.exe()
                if name in path.split(os.sep):
                    if process.status() == psutil.STATUS_ZOMBIE:
                        log.debug("skipped zombie process: %s", path)
                    else:
                        log.debug("found matching process: %s", path)
                        return process
            except psutil.AccessDenied:
                pass  # the process is likely owned by root

class WindowsManager(BaseManager):  # pragma: no cover (manual)

    """Application manager for Windows."""

    NAME = 'Windows'
    FRIENDLY = NAME

    def is_running(self, application):
        pass

    def stop(self, application):
        pass

def get_manager(name=None):
    """Return an application manager for the current operating system."""
    log.info("detecting the current system...")
    name = name or platform.system()
    if name == WindowsManager.NAME:
        manager = WindowsManager()
    elif name == MacManager.NAME:
        manager = MacManager()
    else:
        assert name == LinuxManager.NAME
        manager = LinuxManager()

    log.info("current system: %s", manager)
    return manager
<|endoftext|>


<commit_before>#!/usr/bin/python
#
#  Copyright (c) 2016, The OpenThread Authors.
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#  3. Neither the name of the copyright holder nor the
#     names of its contributors may be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#  POSSIBILITY OF SUCH DAMAGE.
#

import time
import unittest

import node

PANID_INIT = 0xface

COMMISSIONER = 1
LEADER = 2
ROUTER = 3

LEADER_ACTIVE_TIMESTAMP = 10
ROUTER_ACTIVE_TIMESTAMP = 20
ROUTER_PENDING_TIMESTAMP = 30
ROUTER_PENDING_ACTIVE_TIMESTAMP = 25

COMMISSIONER_PENDING_CHANNEL = 20
COMMISSIONER_PENDING_PANID = 0xafce

class Cert_9_2_7_DelayTimer(unittest.TestCase):
    def setUp(self):
        self.nodes = {}
        for i in range(1,4):
            self.nodes[i] = node.Node(i)

        self.nodes[COMMISSIONER].set_active_dataset(LEADER_ACTIVE_TIMESTAMP)
        self.nodes[COMMISSIONER].set_mode('rsdn')
        self.nodes[COMMISSIONER].set_panid(PANID_INIT)
        self.nodes[COMMISSIONER].add_whitelist(self.nodes[LEADER].get_addr64())
        self.nodes[COMMISSIONER].enable_whitelist()
        self.nodes[COMMISSIONER].set_router_selection_jitter(1)

        self.nodes[LEADER].set_mode('rsdn')
        self.nodes[LEADER].set_panid(PANID_INIT)
        self.nodes[LEADER].set_partition_id(0xffffffff)
        self.nodes[LEADER].add_whitelist(self.nodes[COMMISSIONER].get_addr64())
        self.nodes[LEADER].enable_whitelist()
        self.nodes[LEADER].set_router_selection_jitter(1)

        self.nodes[ROUTER].set_active_dataset(ROUTER_ACTIVE_TIMESTAMP)
        self.nodes[ROUTER].set_pending_dataset(ROUTER_PENDING_TIMESTAMP, ROUTER_PENDING_ACTIVE_TIMESTAMP)
        self.nodes[ROUTER].set_mode('rsdn')
        self.nodes[ROUTER].set_panid(PANID_INIT)
        self.nodes[ROUTER].set_partition_id(0x1)
        self.nodes[ROUTER].enable_whitelist()
        self.nodes[ROUTER].set_router_selection_jitter(1)

    def tearDown(self):
        for node in list(self.nodes.values()):
            node.stop()
        del self.nodes

    def test(self):
        self.nodes[LEADER].start()
        self.nodes[LEADER].set_state('leader')
        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')

        self.nodes[COMMISSIONER].start()
        time.sleep(5)
        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
        self.nodes[COMMISSIONER].commissioner_start()
        time.sleep(20)

        self.nodes[ROUTER].start()
        time.sleep(10)
        self.assertEqual(self.nodes[ROUTER].get_state(), 'leader')

        self.nodes[LEADER].add_whitelist(self.nodes[ROUTER].get_addr64())
        self.nodes[ROUTER].add_whitelist(self.nodes[LEADER].get_addr64())

        time.sleep(30)
        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
        self.assertEqual(self.nodes[ROUTER].get_state(), 'router')

        ipaddrs = self.nodes[ROUTER].get_addrs()
        for ipaddr in ipaddrs:
            if ipaddr[0:4] != 'fe80':
                break
        self.assertTrue(self.nodes[LEADER].ping(ipaddr))

        self.nodes[COMMISSIONER].send_mgmt_pending_set(pending_timestamp=40,
                                                       active_timestamp=80,
                                                       delay_timer=10000,
                                                       channel=COMMISSIONER_PENDING_CHANNEL,
                                                       panid=COMMISSIONER_PENDING_PANID)
        time.sleep(20)
        self.assertEqual(self.nodes[LEADER].get_panid(), COMMISSIONER_PENDING_PANID)
        self.assertEqual(self.nodes[COMMISSIONER].get_panid(), COMMISSIONER_PENDING_PANID)
        self.assertEqual(self.nodes[ROUTER].get_panid(), COMMISSIONER_PENDING_PANID)

        self.assertEqual(self.nodes[LEADER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
        self.assertEqual(self.nodes[COMMISSIONER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
        self.assertEqual(self.nodes[ROUTER].get_channel(), COMMISSIONER_PENDING_CHANNEL)

        ipaddrs = self.nodes[ROUTER].get_addrs()
        for ipaddr in ipaddrs:
            if ipaddr[0:4] != 'fe80':
                break
        self.assertTrue(self.nodes[LEADER].ping(ipaddr))

if __name__ == '__main__':
    unittest.main()
<commit_msg>Update Auto Test 9.2.7 to try make Travis check more stable. (#1050)<commit_after>#!/usr/bin/python
#
#  Copyright (c) 2016, The OpenThread Authors.
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#  3. Neither the name of the copyright holder nor the
#     names of its contributors may be used to endorse or promote products
#     derived from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#  POSSIBILITY OF SUCH DAMAGE.
#

import time
import unittest

import node

PANID_INIT = 0xface

COMMISSIONER = 1
LEADER = 2
ROUTER = 3

LEADER_ACTIVE_TIMESTAMP = 10
ROUTER_ACTIVE_TIMESTAMP = 20
ROUTER_PENDING_TIMESTAMP = 30
ROUTER_PENDING_ACTIVE_TIMESTAMP = 25

COMMISSIONER_PENDING_CHANNEL = 20
COMMISSIONER_PENDING_PANID = 0xafce

class Cert_9_2_7_DelayTimer(unittest.TestCase):
    def setUp(self):
        self.nodes = {}
        for i in range(1,4):
            self.nodes[i] = node.Node(i)

        self.nodes[COMMISSIONER].set_active_dataset(LEADER_ACTIVE_TIMESTAMP)
        self.nodes[COMMISSIONER].set_mode('rsdn')
        self.nodes[COMMISSIONER].set_panid(PANID_INIT)
        self.nodes[COMMISSIONER].add_whitelist(self.nodes[LEADER].get_addr64())
        self.nodes[COMMISSIONER].enable_whitelist()
        self.nodes[COMMISSIONER].set_router_selection_jitter(1)

        self.nodes[LEADER].set_mode('rsdn')
        self.nodes[LEADER].set_panid(PANID_INIT)
        self.nodes[LEADER].set_partition_id(0xffffffff)
        self.nodes[LEADER].add_whitelist(self.nodes[COMMISSIONER].get_addr64())
        self.nodes[LEADER].enable_whitelist()
        self.nodes[LEADER].set_router_selection_jitter(1)

        self.nodes[ROUTER].set_active_dataset(ROUTER_ACTIVE_TIMESTAMP)
        self.nodes[ROUTER].set_pending_dataset(ROUTER_PENDING_TIMESTAMP, ROUTER_PENDING_ACTIVE_TIMESTAMP)
        self.nodes[ROUTER].set_mode('rsdn')
        self.nodes[ROUTER].set_panid(PANID_INIT)
        self.nodes[ROUTER].set_partition_id(0x1)
        self.nodes[ROUTER].enable_whitelist()
        self.nodes[ROUTER].set_router_selection_jitter(1)

    def tearDown(self):
        for node in list(self.nodes.values()):
            node.stop()
        del self.nodes

    def test(self):
        self.nodes[LEADER].start()
        self.nodes[LEADER].set_state('leader')
        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')

        self.nodes[COMMISSIONER].start()
        time.sleep(5)
        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')

        self.nodes[ROUTER].start()
        time.sleep(10)
        self.assertEqual(self.nodes[ROUTER].get_state(), 'leader')

        self.nodes[LEADER].add_whitelist(self.nodes[ROUTER].get_addr64())
        self.nodes[ROUTER].add_whitelist(self.nodes[LEADER].get_addr64())

        time.sleep(30)
        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
        self.assertEqual(self.nodes[ROUTER].get_state(), 'router')

        ipaddrs = self.nodes[ROUTER].get_addrs()
        for ipaddr in ipaddrs:
            if ipaddr[0:4] != 'fe80':
                break
        self.assertTrue(self.nodes[LEADER].ping(ipaddr))

        self.nodes[COMMISSIONER].send_mgmt_pending_set(pending_timestamp=40,
                                                       active_timestamp=80,
                                                       delay_timer=10000,
                                                       channel=COMMISSIONER_PENDING_CHANNEL,
                                                       panid=COMMISSIONER_PENDING_PANID)
        time.sleep(20)
        self.assertEqual(self.nodes[LEADER].get_panid(), COMMISSIONER_PENDING_PANID)
        self.assertEqual(self.nodes[COMMISSIONER].get_panid(), COMMISSIONER_PENDING_PANID)
        self.assertEqual(self.nodes[ROUTER].get_panid(), COMMISSIONER_PENDING_PANID)

        self.assertEqual(self.nodes[LEADER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
        self.assertEqual(self.nodes[COMMISSIONER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
        self.assertEqual(self.nodes[ROUTER].get_channel(), COMMISSIONER_PENDING_CHANNEL)

        ipaddrs = self.nodes[ROUTER].get_addrs()
        for ipaddr in ipaddrs:
            if ipaddr[0:4] != 'fe80':
                break
        self.assertTrue(self.nodes[LEADER].ping(ipaddr))

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


<commit_before>import numpy as np

from poliastro.core.util import norm

from ._jit import jit

@jit
def J2_perturbation(t0, state, k, J2, R):
    r"""Calculates J2_perturbation acceleration (km/s2)

    .. math::

        \vec{p} = \frac{3}{2}\frac{J_{2}\mu R^{2}}{r^{4}}\left [\frac{x}{r}\left ( 5\frac{z^{2}}{r^{2}}-1 \right )\vec{i} + \frac{y}{r}\left ( 5\frac{z^{2}}{r^{2}}-1 \right )\vec{j} + \frac{z}{r}\left ( 5\frac{z^{2}}{r^{2}}-3 \right )\vec{k}\right]

    .. versionadded:: 0.9.0

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    J2: float
        oblateness factor
    R: float
        attractor radius

    Note
    ----
    The J2 accounts for the oblateness of the attractor. The formula is given in
    Howard Curtis, (12.30)

    """
    r_vec = state[:3]
    r = norm(r_vec)

    factor = (3.0 / 2.0) * k * J2 * (R ** 2) / (r ** 5)

    a_x = 5.0 * r_vec[2] ** 2 / r ** 2 - 1
    a_y = 5.0 * r_vec[2] ** 2 / r ** 2 - 1
    a_z = 5.0 * r_vec[2] ** 2 / r ** 2 - 3
    return np.array([a_x, a_y, a_z]) * r_vec * factor

@jit
def J3_perturbation(t0, state, k, J3, R):
    r"""Calculates J3_perturbation acceleration (km/s2)

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    J3: float
        oblateness factor
    R: float
        attractor radius

    Note
    ----
    The J3 accounts for the oblateness of the attractor. The formula is given in
    Howard Curtis, problem 12.8
    This perturbation has not been fully validated, see https://github.com/poliastro/poliastro/pull/398

    """
    r_vec = state[:3]
    r = norm(r_vec)

    factor = (1.0 / 2.0) * k * J3 * (R ** 3) / (r ** 5)
    cos_phi = r_vec[2] / r

    a_x = 5.0 * r_vec[0] / r * (7.0 * cos_phi ** 3 - 3.0 * cos_phi)
    a_y = 5.0 * r_vec[1] / r * (7.0 * cos_phi ** 3 - 3.0 * cos_phi)
    a_z = 3.0 * (35.0 / 3.0 * cos_phi ** 4 - 10.0 * cos_phi ** 2 + 1)
    return np.array([a_x, a_y, a_z]) * factor

@jit
def atmospheric_drag(t0, state, k, R, C_D, A, m, H0, rho0):
    r"""Calculates atmospheric drag acceleration (km/s2)

    .. math::

        \vec{p} = -\frac{1}{2}\rho v_{rel}\left ( \frac{C_{d}A}{m} \right )\vec{v_{rel}}

    .. versionadded:: 0.9.0

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    C_D: float
        dimensionless drag coefficient ()
    A: float
        frontal area of the spacecraft (km^2)
    m: float
        mass of the spacecraft (kg)
    H0 : float
        atmospheric scale height, (km)
    rho0: float
        the exponent density pre-factor, (kg / m^3)

    Note
    ----
    This function provides the acceleration due to atmospheric drag. We follow
    Howard Curtis, section 12.4
    the atmospheric density model is rho(H) = rho0 x exp(-H / H0)

    """
    H = norm(state[:3])

    v_vec = state[3:]
    v = norm(v_vec)
    B = C_D * A / m
    rho = rho0 * np.exp(-(H - R) / H0)

    return -(1.0 / 2.0) * rho * B * v * v_vec

@jit
def shadow_function(r_sat, r_sun, R):
    r"""Determines whether the satellite is in attractor's shadow, uses algorithm 12.3 from Howard Curtis

    Parameters
    ----------
    r_sat : numpy.ndarray
        position of the satellite in the frame of attractor (km)
    r_sun : numpy.ndarray
        position of star in the frame of attractor (km)
    R : float
        radius of body (attractor) that creates shadow (km)

    """

    r_sat_norm = np.sqrt(np.sum(r_sat ** 2))
    r_sun_norm = np.sqrt(np.sum(r_sun ** 2))

    theta = np.arccos(np.dot(r_sat, r_sun) / r_sat_norm / r_sun_norm)
    theta_1 = np.arccos(R / r_sat_norm)
    theta_2 = np.arccos(R / r_sun_norm)

    return theta < theta_1 + theta_2

def third_body(t0, state, k, k_third, third_body):
    r"""Calculates 3rd body acceleration (km/s2)

    .. math::

        \vec{p} = \mu_{m}\left ( \frac{\vec{r_{m/s}}}{r_{m/s}^3} - \frac{\vec{r_{m}}}{r_{m}^3} \right )

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    third_body: a callable object returning the position of 3rd body
        third body that causes the perturbation

    Note
    ----
    This formula is taken from Howard Curtis, section 12.10. As an example, a third body could be
    the gravity from the Moon acting on a small satellite.

    """

    body_r = third_body(t0)
    delta_r = body_r - state[:3]
    return k_third * delta_r / norm(delta_r) ** 3 - k_third * body_r / norm(body_r) ** 3

def radiation_pressure(t0, state, k, R, C_R, A, m, Wdivc_s, star):
    r"""Calculates radiation pressure acceleration (km/s2)

    .. math::

        \vec{p} = -\nu \frac{S}{c} \left ( \frac{C_{r}A}{m} \right )\frac{\vec{r}}{r}

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    R : float
        radius of the attractor
    C_R: float
        dimensionless radiation pressure coefficient, 1 < C_R < 2 ()
    A: float
        effective spacecraft area (km^2)
    m: float
        mass of the spacecraft (kg)
    Wdivc_s : float
        total star emitted power divided by the speed of light (W * s / km)
    star: a callable object returning the position of star in attractor frame
        star position

    Note
    ----
    This function provides the acceleration due to star light pressure. We follow
    Howard Curtis, section 12.9

    """

    r_star = star(t0)
    r_sat = state[:3]
    P_s = Wdivc_s / (norm(r_star) ** 2)

    nu = float(shadow_function(r_sat, r_star, R))
    return -nu * P_s * (C_R * A / m) * r_star / norm(r_star)
<commit_msg>Update perturbations.py<commit_after>import numpy as np

from poliastro.core.util import norm

from ._jit import jit

@jit
def J2_perturbation(t0, state, k, J2, R):
    r"""Calculates J2_perturbation acceleration (km/s2)

    .. math::

        \vec{p} = \frac{3}{2}\frac{J_{2}\mu R^{2}}{r^{4}}\left [\frac{x}{r}\left ( 5\frac{z^{2}}{r^{2}}-1 \right )\vec{i} + \frac{y}{r}\left ( 5\frac{z^{2}}{r^{2}}-1 \right )\vec{j} + \frac{z}{r}\left ( 5\frac{z^{2}}{r^{2}}-3 \right )\vec{k}\right]

    .. versionadded:: 0.9.0

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    J2: float
        oblateness factor
    R: float
        attractor radius

    Note
    ----
    The J2 accounts for the oblateness of the attractor. The formula is given in
    Howard Curtis, (12.30)

    """
    r_vec = state[:3]
    r = norm(r_vec)

    factor = (3.0 / 2.0) * k * J2 * (R ** 2) / (r ** 5)

    a_x = 5.0 * r_vec[2] ** 2 / r ** 2 - 1
    a_y = 5.0 * r_vec[2] ** 2 / r ** 2 - 1
    a_z = 5.0 * r_vec[2] ** 2 / r ** 2 - 3
    return np.array([a_x, a_y, a_z]) * r_vec * factor

@jit
def J3_perturbation(t0, state, k, J3, R):
    r"""Calculates J3_perturbation acceleration (km/s2)

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    J3: float
        oblateness factor
    R: float
        attractor radius

    Note
    ----
    The J3 accounts for the oblateness of the attractor. The formula is given in
    Howard Curtis, problem 12.8
    This perturbation has not been fully validated, see https://github.com/poliastro/poliastro/pull/398

    """
    r_vec = state[:3]
    r = norm(r_vec)

    factor = (1.0 / 2.0) * k * J3 * (R ** 3) / (r ** 5)
    cos_phi = r_vec[2] / r

    a_x = 5.0 * r_vec[0] / r * (7.0 * cos_phi ** 3 - 3.0 * cos_phi)
    a_y = 5.0 * r_vec[1] / r * (7.0 * cos_phi ** 3 - 3.0 * cos_phi)
    a_z = 3.0 * (35.0 / 3.0 * cos_phi ** 4 - 10.0 * cos_phi ** 2 + 1)
    return np.array([a_x, a_y, a_z]) * factor

@jit
def atmospheric_drag(t0, state, k, R, C_D, A, m, H0, rho0):
    r"""Calculates atmospheric drag acceleration (km/s2)

    .. math::

        \vec{p} = -\frac{1}{2}\rho v_{rel}\left ( \frac{C_{d}A}{m} \right )\vec{v_{rel}}

    .. versionadded:: 0.9.0

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    R : float
        radius of the attractor (km)
    C_D: float
        dimensionless drag coefficient ()
    A: float
        frontal area of the spacecraft (km^2)
    m: float
        mass of the spacecraft (kg)
    H0 : float
        atmospheric scale height, (km)
    rho0: float
        the exponent density pre-factor, (kg / m^3)

    Note
    ----
    This function provides the acceleration due to atmospheric drag. We follow
    Howard Curtis, section 12.4
    the atmospheric density model is rho(H) = rho0 x exp(-H / H0)

    """
    H = norm(state[:3])

    v_vec = state[3:]
    v = norm(v_vec)
    B = C_D * A / m
    rho = rho0 * np.exp(-(H - R) / H0)

    return -(1.0 / 2.0) * rho * B * v * v_vec

@jit
def shadow_function(r_sat, r_sun, R):
    r"""Determines whether the satellite is in attractor's shadow, uses algorithm 12.3 from Howard Curtis

    Parameters
    ----------
    r_sat : numpy.ndarray
        position of the satellite in the frame of attractor (km)
    r_sun : numpy.ndarray
        position of star in the frame of attractor (km)
    R : float
        radius of body (attractor) that creates shadow (km)

    """

    r_sat_norm = np.sqrt(np.sum(r_sat ** 2))
    r_sun_norm = np.sqrt(np.sum(r_sun ** 2))

    theta = np.arccos(np.dot(r_sat, r_sun) / r_sat_norm / r_sun_norm)
    theta_1 = np.arccos(R / r_sat_norm)
    theta_2 = np.arccos(R / r_sun_norm)

    return theta < theta_1 + theta_2

def third_body(t0, state, k, k_third, third_body):
    r"""Calculates 3rd body acceleration (km/s2)

    .. math::

        \vec{p} = \mu_{m}\left ( \frac{\vec{r_{m/s}}}{r_{m/s}^3} - \frac{\vec{r_{m}}}{r_{m}^3} \right )

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    third_body: a callable object returning the position of 3rd body
        third body that causes the perturbation

    Note
    ----
    This formula is taken from Howard Curtis, section 12.10. As an example, a third body could be
    the gravity from the Moon acting on a small satellite.

    """

    body_r = third_body(t0)
    delta_r = body_r - state[:3]
    return k_third * delta_r / norm(delta_r) ** 3 - k_third * body_r / norm(body_r) ** 3

def radiation_pressure(t0, state, k, R, C_R, A, m, Wdivc_s, star):
    r"""Calculates radiation pressure acceleration (km/s2)

    .. math::

        \vec{p} = -\nu \frac{S}{c} \left ( \frac{C_{r}A}{m} \right )\frac{\vec{r}}{r}

    Parameters
    ----------
    t0 : float
        Current time (s)
    state : numpy.ndarray
        Six component state vector [x, y, z, vx, vy, vz] (km, km/s).
    k : float
        gravitational constant, (km^3/s^2)
    R : float
        radius of the attractor
    C_R: float
        dimensionless radiation pressure coefficient, 1 < C_R < 2 ()
    A: float
        effective spacecraft area (km^2)
    m: float
        mass of the spacecraft (kg)
    Wdivc_s : float
        total star emitted power divided by the speed of light (W * s / km)
    star: a callable object returning the position of star in attractor frame
        star position

    Note
    ----
    This function provides the acceleration due to star light pressure. We follow
    Howard Curtis, section 12.9

    """

    r_star = star(t0)
    r_sat = state[:3]
    P_s = Wdivc_s / (norm(r_star) ** 2)

    nu = float(shadow_function(r_sat, r_star, R))
    return -nu * P_s * (C_R * A / m) * r_star / norm(r_star)
<|endoftext|>


<commit_before>from discord.ext import commands
import discord
from cogs.utils import checks, context, db
from cogs.utils.config import Config
import datetime, re
import json, asyncio
import copy
import logging
import traceback
import aiohttp
import sys
from collections import Counter

import config
import asyncpg

description = """
Hello! I am a bot written by Danny to provide some nice utilities.
"""

log = logging.getLogger(__name__)

initial_extensions = (
    'cogs.meta',
    'cogs.splatoon',
    'cogs.rng',
    'cogs.mod',
    'cogs.profile',
    'cogs.tags',
    'cogs.lounge',
    'cogs.carbonitex',
    'cogs.api',
    'cogs.stars',
    'cogs.admin',
    'cogs.buttons',
    'cogs.reminder',
    'cogs.stats',
    'cogs.emoji',
    'cogs.tournament',
)

def _prefix_callable(bot, msg):
    user_id = bot.user.id
    base = [f'<@!{user_id}> ', f'<@{user_id}> ']
    if msg.guild is None:
        base.append('!')
        base.append('?')
    else:
        base.extend(bot.prefixes.get(msg.guild.id, ['?', '!']))
    return base

class RoboDanny(commands.AutoShardedBot):
    def __init__(self):
        super().__init__(command_prefix=_prefix_callable, description=description,
                         pm_help=None, help_attrs=dict(hidden=True))

        self.client_id = config.client_id
        self.carbon_key = config.carbon_key
        self.bots_key = config.bots_key
        self.challonge_api_key = config.challonge_api_key
        self.session = aiohttp.ClientSession(loop=self.loop)

        self.add_command(self.do)

        # guild_id: list
        self.prefixes = Config('prefixes.json')

        for extension in initial_extensions:
            try:
                self.load_extension(extension)
            except Exception as e:
                print(f'Failed to load extension {extension}.', file=sys.stderr)
                traceback.print_exc()

    async def on_command_error(self, ctx, error):
        if isinstance(error, commands.NoPrivateMessage):
            await ctx.author.send('This command cannot be used in private messages.')
        elif isinstance(error, commands.DisabledCommand):
            await ctx.author.send('Sorry. This command is disabled and cannot be used.')
        elif isinstance(error, commands.CommandInvokeError):
            print(f'In {ctx.command.qualified_name}:', file=sys.stderr)
            traceback.print_tb(error.original.__traceback__)
            print(f'{error.original.__class__.__name__}: {error.original}', file=sys.stderr)

    def get_guild_prefixes(self, guild, *, local_inject=_prefix_callable):
        proxy_msg = discord.Object(id=None)
        proxy_msg.guild = guild
        return local_inject(self, proxy_msg)

    def get_raw_guild_prefixes(self, guild_id):
        return self.prefixes.get(guild_id, ['?', '!'])

    async def set_guild_prefixes(self, guild, prefixes):
        if len(prefixes) == 0:
            await self.prefixes.put(guild.id, [])
        elif len(prefixes) > 10:
            raise RuntimeError('Cannot have more than 10 custom prefixes.')
        else:
            await self.prefixes.put(guild.id, sorted(set(prefixes), reverse=True))

    async def on_ready(self):
        if not hasattr(self, 'uptime'):
            self.uptime = datetime.datetime.utcnow()

        print(f'Ready: {self.user} (ID: {self.user.id})')

    async def on_resumed(self):
        print('resumed...')

    async def process_commands(self, message):
        ctx = await self.get_context(message, cls=context.Context)

        if ctx.command is None:
            return

        async with ctx.acquire():
            await self.invoke(ctx)

    async def on_message(self, message):
        if message.author.bot:
            return
        await self.process_commands(message)

    async def close(self):
        await super().close()
        await self.session.close()

    def run(self):
        super().run(config.token, reconnect=True)

    @property
    def config(self):
        return __import__('config')

    @commands.command(hidden=True)
    @commands.is_owner()
    async def do(self, ctx, times: int, *, command):
        """Repeats a command a specified number of times."""
        msg = copy.copy(ctx.message)
        msg.content = command
        for i in range(times):
            await self.process_commands(msg)
<commit_msg>Fix ?do to actually work.<commit_after>from discord.ext import commands
import discord
from cogs.utils import checks, context, db
from cogs.utils.config import Config
import datetime, re
import json, asyncio
import copy
import logging
import traceback
import aiohttp
import sys
from collections import Counter

import config
import asyncpg

description = """
Hello! I am a bot written by Danny to provide some nice utilities.
"""

log = logging.getLogger(__name__)

initial_extensions = (
    'cogs.meta',
    'cogs.splatoon',
    'cogs.rng',
    'cogs.mod',
    'cogs.profile',
    'cogs.tags',
    'cogs.lounge',
    'cogs.carbonitex',
    'cogs.api',
    'cogs.stars',
    'cogs.admin',
    'cogs.buttons',
    'cogs.reminder',
    'cogs.stats',
    'cogs.emoji',
    'cogs.tournament',
)

def _prefix_callable(bot, msg):
    user_id = bot.user.id
    base = [f'<@!{user_id}> ', f'<@{user_id}> ']
    if msg.guild is None:
        base.append('!')
        base.append('?')
    else:
        base.extend(bot.prefixes.get(msg.guild.id, ['?', '!']))
    return base

class RoboDanny(commands.AutoShardedBot):
    def __init__(self):
        super().__init__(command_prefix=_prefix_callable, description=description,
                         pm_help=None, help_attrs=dict(hidden=True))

        self.client_id = config.client_id
        self.carbon_key = config.carbon_key
        self.bots_key = config.bots_key
        self.challonge_api_key = config.challonge_api_key
        self.session = aiohttp.ClientSession(loop=self.loop)

        self.add_command(self.do)

        # guild_id: list
        self.prefixes = Config('prefixes.json')

        for extension in initial_extensions:
            try:
                self.load_extension(extension)
            except Exception as e:
                print(f'Failed to load extension {extension}.', file=sys.stderr)
                traceback.print_exc()

    async def on_command_error(self, ctx, error):
        if isinstance(error, commands.NoPrivateMessage):
            await ctx.author.send('This command cannot be used in private messages.')
        elif isinstance(error, commands.DisabledCommand):
            await ctx.author.send('Sorry. This command is disabled and cannot be used.')
        elif isinstance(error, commands.CommandInvokeError):
            print(f'In {ctx.command.qualified_name}:', file=sys.stderr)
            traceback.print_tb(error.original.__traceback__)
            print(f'{error.original.__class__.__name__}: {error.original}', file=sys.stderr)

    def get_guild_prefixes(self, guild, *, local_inject=_prefix_callable):
        proxy_msg = discord.Object(id=None)
        proxy_msg.guild = guild
        return local_inject(self, proxy_msg)

    def get_raw_guild_prefixes(self, guild_id):
        return self.prefixes.get(guild_id, ['?', '!'])

    async def set_guild_prefixes(self, guild, prefixes):
        if len(prefixes) == 0:
            await self.prefixes.put(guild.id, [])
        elif len(prefixes) > 10:
            raise RuntimeError('Cannot have more than 10 custom prefixes.')
        else:
            await self.prefixes.put(guild.id, sorted(set(prefixes), reverse=True))

    async def on_ready(self):
        if not hasattr(self, 'uptime'):
            self.uptime = datetime.datetime.utcnow()

        print(f'Ready: {self.user} (ID: {self.user.id})')

    async def on_resumed(self):
        print('resumed...')

    async def process_commands(self, message):
        ctx = await self.get_context(message, cls=context.Context)

        if ctx.command is None:
            return

        async with ctx.acquire():
            await self.invoke(ctx)

    async def on_message(self, message):
        if message.author.bot:
            return
        await self.process_commands(message)

    async def close(self):
        await super().close()
        await self.session.close()

    def run(self):
        super().run(config.token, reconnect=True)

    @property
    def config(self):
        return __import__('config')

    @commands.command(hidden=True)
    @commands.is_owner()
    async def do(self, ctx, times: int, *, command):
        """Repeats a command a specified number of times."""
        msg = copy.copy(ctx.message)
        msg.content = command

        new_ctx = await self.get_context(msg, cls=context.Context)
        new_ctx.db = ctx.db

        for i in range(times):
            await new_ctx.reinvoke()
<|endoftext|>


<commit_before># Copyright 2021 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import absolute_import
import logging
import socket

from telemetry.internal.backends.chrome_inspector import devtools_http
from telemetry.internal.backends.chrome_inspector import inspector_websocket

DEFAULT_UI_DEVTOOLS_PORT = 9223

# These are possible exceptions raised when the DevTools agent is not ready
# to accept incomming connections.
_DEVTOOLS_CONNECTION_ERRORS = (
    devtools_http.DevToolsClientConnectionError,
    inspector_websocket.WebSocketException,
    socket.error)

def GetUIDevtoolsBackend(port, app_backend, browser_target='/0'):
  client = UIDevToolsClientBackend(app_backend)
  try:
    client.Connect(port or DEFAULT_UI_DEVTOOLS_PORT, browser_target)
    logging.info('DevTools agent ready at %s', client)
    client.GetDocument()
  except _DEVTOOLS_CONNECTION_ERRORS as exc:
    logging.info('DevTools agent at %s not ready yet: %s', client, exc)
    client = None
  return client

class UIDevToolsClientBackend(object):
  """Backend for UIDevTools

  Protocol definition:
  https://source.chromium.org/chromium/chromium/src/+/master:components/ui_devtools/protocol.json
  """
  def __init__(self, app_backend):
    """Create an object able to connect with the DevTools agent.

    Args:
      app_backend: The app that contains the DevTools agent.
    """
    self._app_backend = app_backend
    self._browser_target = None
    self._forwarder = None
    self._devtools_http = None
    self._browser_websocket = None
    self._local_port = None
    self._remote_port = None

  def Connect(self, devtools_port, browser_target):
    try:
      self._Connect(devtools_port, browser_target)
    except:
      self.Close()  # Close any connections made if failed to connect to all.
      raise

  def _Connect(self, devtools_port, browser_target):
    self._browser_target = browser_target or '/devtools/browser'
    self._SetUpPortForwarding(devtools_port)

    # Ensure that the inspector websocket is ready. This may raise a
    # inspector_websocket.WebSocketException or socket.error if not ready.
    self._browser_websocket = inspector_websocket.InspectorWebsocket()
    self._browser_websocket.Connect(self.browser_target_url, timeout=10)

  def _SetUpPortForwarding(self, devtools_port):
    self._forwarder = self.platform_backend.forwarder_factory.Create(
        local_port=None,  # Forwarder will choose an available port.
        remote_port=devtools_port, reverse=True)
    self._local_port = self._forwarder._local_port
    self._remote_port = self._forwarder._remote_port
    self._devtools_http = devtools_http.DevToolsHttp(self.local_port)

  def Close(self):
    # Close the DevTools connections last (in case the backends above still
    # need to interact with them while closing).
    if self._browser_websocket is not None:
      self._browser_websocket.Disconnect()
      self._browser_websocket = None
    if self._devtools_http is not None:
      self._devtools_http.Disconnect()
      self._devtools_http = None
    if self._forwarder is not None:
      self._forwarder.Close()
      self._forwarder = None

  def __str__(self):
    s = self.browser_target_url
    if self.local_port != self.remote_port:
      s = '%s (remote=%s)' % (s, self.remote_port)
    return s

  @property
  def local_port(self):
    return self._local_port

  @property
  def remote_port(self):
    return self._remote_port

  @property
  def browser_target_url(self):
    return 'ws://127.0.0.1:%i%s' % (self._local_port, self._browser_target)

  @property
  def platform_backend(self):
    return self._app_backend.platform_backend

  def QueryNodes(self, query):
    response = self.PerformSearch(query)
    count = response['result']['resultCount']
    logging.info('Found %d results for %s', count, query)
    if count == 0:
      return []
    response = self.GetSearchResults(response['result']['searchId'], 0, count)
    return response['result']['nodeIds']

  def GetDocument(self):
    request = {
        'method': 'DOM.getDocument',
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  def PerformSearch(self, query):
    request = {
        'method': 'DOM.performSearch',
        'params': {
            'query': query,
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  def GetSearchResults(self, search_id, from_index, to_index):
    request = {
        'method': 'DOM.getSearchResults',
        'params': {
            'searchId': search_id,
            'fromIndex': from_index,
            'toIndex': to_index,
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  # pylint: disable=redefined-builtin
  def DispatchMouseEvent(self,
                         node_id,
                         type,
                         x,
                         y,
                         button,
                         wheel_direction):
    request = {
        'method': 'DOM.dispatchMouseEvent',
        'params': {
            'nodeId': node_id,
            'event': {
                'type': type,
                'x': x,
                'y': y,
                'button': button,
                'wheelDirection': wheel_direction,
            },
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  # pylint: disable=redefined-builtin
  def DispatchKeyEvent(self,
                       node_id,
                       type,
                       key_code,
                       code,
                       flags,
                       key,
                       is_char):
    request = {
        'method': 'DOM.dispatchKeyEvent',
        'params': {
            'nodeId': node_id,
            'event': {
                'type': type,
                'keyCode': key_code,
                'code': code,
                'flags': flags,
                'key': key,
                'isChar': is_char,
            },
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)
<commit_msg>Enable UI DevTools' agent after being connected<commit_after># Copyright 2021 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import absolute_import
import logging
import socket

from telemetry.internal.backends.chrome_inspector import devtools_http
from telemetry.internal.backends.chrome_inspector import inspector_websocket

DEFAULT_UI_DEVTOOLS_PORT = 9223

# These are possible exceptions raised when the DevTools agent is not ready
# to accept incomming connections.
_DEVTOOLS_CONNECTION_ERRORS = (
    devtools_http.DevToolsClientConnectionError,
    inspector_websocket.WebSocketException,
    socket.error)

def GetUIDevtoolsBackend(port, app_backend, browser_target='/0'):
  client = UIDevToolsClientBackend(app_backend)
  try:
    client.Connect(port or DEFAULT_UI_DEVTOOLS_PORT, browser_target)
    logging.info('DevTools agent connected at %s', client)
    # Enable UI DevTools agents. This is required on Mac so we will be
    # notified about future updates.
    client.Enable()
    client.GetDocument()
  except _DEVTOOLS_CONNECTION_ERRORS as exc:
    logging.info('DevTools agent at %s not ready yet: %s', client, exc)
    client = None
  return client

class UIDevToolsClientBackend(object):
  """Backend for UIDevTools

  Protocol definition:
  https://source.chromium.org/chromium/chromium/src/+/master:components/ui_devtools/protocol.json
  """
  def __init__(self, app_backend):
    """Create an object able to connect with the DevTools agent.

    Args:
      app_backend: The app that contains the DevTools agent.
    """
    self._app_backend = app_backend
    self._browser_target = None
    self._forwarder = None
    self._devtools_http = None
    self._browser_websocket = None
    self._local_port = None
    self._remote_port = None

  def Connect(self, devtools_port, browser_target):
    try:
      self._Connect(devtools_port, browser_target)
    except:
      self.Close()  # Close any connections made if failed to connect to all.
      raise

  def _Connect(self, devtools_port, browser_target):
    self._browser_target = browser_target or '/devtools/browser'
    self._SetUpPortForwarding(devtools_port)

    # Ensure that the inspector websocket is ready. This may raise a
    # inspector_websocket.WebSocketException or socket.error if not ready.
    self._browser_websocket = inspector_websocket.InspectorWebsocket()
    self._browser_websocket.Connect(self.browser_target_url, timeout=10)

  def _SetUpPortForwarding(self, devtools_port):
    self._forwarder = self.platform_backend.forwarder_factory.Create(
        local_port=None,  # Forwarder will choose an available port.
        remote_port=devtools_port, reverse=True)
    self._local_port = self._forwarder._local_port
    self._remote_port = self._forwarder._remote_port
    self._devtools_http = devtools_http.DevToolsHttp(self.local_port)

  def Close(self):
    # Close the DevTools connections last (in case the backends above still
    # need to interact with them while closing).
    if self._browser_websocket is not None:
      self._browser_websocket.Disconnect()
      self._browser_websocket = None
    if self._devtools_http is not None:
      self._devtools_http.Disconnect()
      self._devtools_http = None
    if self._forwarder is not None:
      self._forwarder.Close()
      self._forwarder = None

  def __str__(self):
    s = self.browser_target_url
    if self.local_port != self.remote_port:
      s = '%s (remote=%s)' % (s, self.remote_port)
    return s

  @property
  def local_port(self):
    return self._local_port

  @property
  def remote_port(self):
    return self._remote_port

  @property
  def browser_target_url(self):
    return 'ws://127.0.0.1:%i%s' % (self._local_port, self._browser_target)

  @property
  def platform_backend(self):
    return self._app_backend.platform_backend

  def QueryNodes(self, query):
    response = self.PerformSearch(query)
    count = response['result']['resultCount']
    logging.info('Found %d results for %s', count, query)
    if count == 0:
      return []
    response = self.GetSearchResults(response['result']['searchId'], 0, count)
    return response['result']['nodeIds']

  def Enable(self):
    request = {
        'method': 'DOM.enable',
    }
    return self._browser_websocket.SyncRequest(request, timeout=30)

  def GetDocument(self):
    request = {
        'method': 'DOM.getDocument',
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  def PerformSearch(self, query):
    request = {
        'method': 'DOM.performSearch',
        'params': {
            'query': query,
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  def GetSearchResults(self, search_id, from_index, to_index):
    request = {
        'method': 'DOM.getSearchResults',
        'params': {
            'searchId': search_id,
            'fromIndex': from_index,
            'toIndex': to_index,
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  # pylint: disable=redefined-builtin
  def DispatchMouseEvent(self,
                         node_id,
                         type,
                         x,
                         y,
                         button,
                         wheel_direction):
    request = {
        'method': 'DOM.dispatchMouseEvent',
        'params': {
            'nodeId': node_id,
            'event': {
                'type': type,
                'x': x,
                'y': y,
                'button': button,
                'wheelDirection': wheel_direction,
            },
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)

  # pylint: disable=redefined-builtin
  def DispatchKeyEvent(self,
                       node_id,
                       type,
                       key_code,
                       code,
                       flags,
                       key,
                       is_char):
    request = {
        'method': 'DOM.dispatchKeyEvent',
        'params': {
            'nodeId': node_id,
            'event': {
                'type': type,
                'keyCode': key_code,
                'code': code,
                'flags': flags,
                'key': key,
                'isChar': is_char,
            },
        }
    }
    return self._browser_websocket.SyncRequest(request, timeout=60)
<|endoftext|>


<commit_before>import argparse
from datetime import datetime
import os
import os.path
import re
import time

from slackclient import SlackClient

TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'

timestamp_pattern = re.compile(r'^\[(.*?)\].*?$')
chat_pattern = re.compile(r'^\[(.*?)\].*?\:\ \<(.*?)\>\ (.*?)$')
join_pattern = re.compile(r'^\[(.*?)\].*?\:\ (.*?) (joined the game)$')
left_pattern = re.compile(r'^\[(.*?)\].*?\:\ (.*?) (left the game)$')
broadcast_patterns = [
  re.compile(r'^\[(.*?)\].*?\:\ (.*?) (was|walked|drowned|experienced|blew|hit|fell|went|burned|tried|discovered|got|starved|suffocated|withered.*?)$'),
  re.compile(r'^\[(.*?)\].*?\:\ (.*?) (has just earned.*?)$')
]

class MinecraftBot:
    """ A Slack-bot for reporting on and interacting with a multiplayer Minecraft server.

        The bot will read the latest.log and report to the Slack channel player-centered events, such as:

          - Joins
          - Departs
          - Achievements
          - Deaths
          - In-game chat

        In addition, the bot will respond to commands. Currently, the commands understood are:

          - list: list the currently logged-in players

    """

    READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose

    def __init__(self, bot_id, slack_client, server_directory, channel="#general"):
        """ Create a Minecraft bot. It requires a few bits to get going:

              - bot_id: the non-human-readable id of the bot
              - slack_client: an initialized SlackClient (created with your bot's API key)
              - server_directory: the path to the Minecraft server's directory
              - channel: the name of the channel to send messages (defaults to #general)
        """

        self.bot_id = bot_id
        self.at_bot = "<@{}>".format(self.bot_id)
        self.slack_client = slack_client
        self.server_directory = server_directory
        self.latest_log = os.path.join(self.server_directory, 'logs', 'latest.log')
        self.most_recent_timestamp_file = os.path.join(self.server_directory, 'latest_timestamp.txt')
        self.channel = channel
        self.most_recent_timestamp = self.find_most_recent_timestamp()
        self.current_players = set()
        self.commands = {'list': self.list_current_players}

    def find_most_recent_timestamp(self):
        """ Set the most recent timestamp seen by the bot """
        try:
            with open(self.most_recent_timestamp_file) as f:
                timestamp_float = float(f.read().strip())
                most_recent_timestamp = datetime.fromtimestamp(timestamp_float)
        except IOError, e:
            most_recent_timestamp = datetime.min

        return most_recent_timestamp

    def post_message(self, message, channel=None):
        """ Post a message to the the channel as our bot """
        self.slack_client.api_call(
            'chat.postMessage',
            channel=channel or self.channel,
            text=message,
            as_user=True,
            link_names=True,
            username=self.bot_id)

    def remember_timestamp(self, timestamp):
        """ Record the timestamp from a given log line as its mktime float """
        d = datetime.strptime(timestamp, TIMESTAMP_FORMAT)
        seconds_timestamp = time.mktime(d.timetuple())

        with open(self.most_recent_timestamp_file, 'w') as f:
            f.write(str(seconds_timestamp))

    def parse_slack_output(self, slack_rtm_output):
        """ Parse the output of the Slack Real-Time Messaging firehose

            Look for messages directed at our bot (using the self.at_bot marker), and return the relevant information
        """
        output_list = slack_rtm_output
        if output_list and len(output_list) > 0:
            for output in output_list:
                if output and 'text' in output and self.at_bot in output['text']:
                    # return text after the @ mention, whitespace removed
                    return output['text'].split(self.at_bot)[1].strip().lower(), \
                           output['channel']
        return None, None

    def handle_command(self, command, channel):
        """ Process the command given from a channel and write back to same.

            If the command is not understoon, return a helpful message.
        """
        command, args = command.split()
        handler = self.commands.get(command, self.unknown_command)
        response = handler(args)
        self.post_message(response, channel)

    def run(self):
        """ The main loop - read from the Slack RTM firehose, and also keep an eye on the server's latest.log """
        if self.slack_client.rtm_connect():
            with open(self.latest_log) as f:
                while True:
                    command, channel = self.parse_slack_output(self.slack_client.rtm_read())
                    if command and channel:
                        # first, respond to in-Slack messages
                        self.handle_command(command, channel)
                        time.sleep(self.READ_WEBSOCKET_DELAY)
                    else:
                        # else, read server logs and process them
                        line = f.readline()

                        timestamp_match = timestamp_pattern.match(line)
                        if timestamp_match:
                            line_datetime = datetime.strptime(timestamp_match.group(1), TIMESTAMP_FORMAT)

                        if line_datetime <= most_recent_timestamp:
                            continue

                        chat_match = chat_pattern.match(line)
                        if chat_match:
                            timestamp, user, message = chat_match.groups()
                            self.post_message('{} said: {}'.format(user, message))
                            self.remember_timestamp(timestamp)
                            continue

                        join_match = join_pattern.match(line)
                        if join_match:
                            timestamp, user, message = join_match.groups()
                            self.post_message('{} {}'.format(user, message))
                            self.remember_timestamp(timestamp)
                            self.current_players.add(user)
                            continue

                        left_match = left_pattern.match(line)
                        if left_match:
                            timestamp, user, message = left_match.groups()
                            self.post_message('{} {}'.format(user, message))
                            self.remember_timestamp(timestamp)
                            self.current_players.remove(user)
                            continue

                        for pattern in broadcast_patterns:
                            maybe_match = pattern.match(line)
                            if maybe_match:
                                timestamp, user, message = maybe_match.groups()
                                self.post_message('{} {}'.format(user, message))
                                self.remember_timestamp(timestamp)
                                continue
        else:
            print("Connection failed. Invalid Slack token or bot ID?")

    # Commands

    def unknown_command(self):
        """ The default response for commands the bot doesn't understand. """
        return "So far, all I know how to do is `list`! Tell @zacbir to add more smarts!"

    def list_current_players(self):
        """ List the currently logged in users """
        current_players = self.current_players
        response = "There {} currently {} player{} logged into the server{}.".format(
            'is' if len(current_players) == 1 else 'are',
            len(current_players),
            '' if len(current_players) == 1 else 's',
            '' if len(current_players) == 0 else ': {}'.format(', '.join(current_players)))
        return response

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Launch a bot to communicate information about a shared Minecraft server to Slack')
    parser.add_argument('-d', '--directory', help="The directory where the Minecraft server lives")
    args = parser.parse_args()

    api_key = os.environ.get('SLACK_API_KEY')
    slack_client = SlackClient(api_key)

    minecraft_bot = MinecraftBot(
        os.environ.get('SLACK_BOT_ID'),
        slack_client,
        args.directory)

    minecraft_bot.run()
<commit_msg>probably a lot like instance variables<commit_after>import argparse
from datetime import datetime
import os
import os.path
import re
import time

from slackclient import SlackClient

TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'

timestamp_pattern = re.compile(r'^\[(.*?)\].*?$')
chat_pattern = re.compile(r'^\[(.*?)\].*?\:\ \<(.*?)\>\ (.*?)$')
join_pattern = re.compile(r'^\[(.*?)\].*?\:\ (.*?) (joined the game)$')
left_pattern = re.compile(r'^\[(.*?)\].*?\:\ (.*?) (left the game)$')
broadcast_patterns = [
  re.compile(r'^\[(.*?)\].*?\:\ (.*?) (was|walked|drowned|experienced|blew|hit|fell|went|burned|tried|discovered|got|starved|suffocated|withered.*?)$'),
  re.compile(r'^\[(.*?)\].*?\:\ (.*?) (has just earned.*?)$')
]

class MinecraftBot:
    """ A Slack-bot for reporting on and interacting with a multiplayer Minecraft server.

        The bot will read the latest.log and report to the Slack channel player-centered events, such as:

          - Joins
          - Departs
          - Achievements
          - Deaths
          - In-game chat

        In addition, the bot will respond to commands. Currently, the commands understood are:

          - list: list the currently logged-in players

    """

    READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose

    def __init__(self, bot_id, slack_client, server_directory, channel="#general"):
        """ Create a Minecraft bot. It requires a few bits to get going:

              - bot_id: the non-human-readable id of the bot
              - slack_client: an initialized SlackClient (created with your bot's API key)
              - server_directory: the path to the Minecraft server's directory
              - channel: the name of the channel to send messages (defaults to #general)
        """

        self.bot_id = bot_id
        self.at_bot = "<@{}>".format(self.bot_id)
        self.slack_client = slack_client
        self.server_directory = server_directory
        self.latest_log = os.path.join(self.server_directory, 'logs', 'latest.log')
        self.most_recent_timestamp_file = os.path.join(self.server_directory, 'latest_timestamp.txt')
        self.channel = channel
        self.most_recent_timestamp = self.find_most_recent_timestamp()
        self.current_players = set()
        self.commands = {'list': self.list_current_players}

    def find_most_recent_timestamp(self):
        """ Set the most recent timestamp seen by the bot """
        try:
            with open(self.most_recent_timestamp_file) as f:
                timestamp_float = float(f.read().strip())
                most_recent_timestamp = datetime.fromtimestamp(timestamp_float)
        except IOError, e:
            most_recent_timestamp = datetime.min

        return most_recent_timestamp

    def post_message(self, message, channel=None):
        """ Post a message to the the channel as our bot """
        self.slack_client.api_call(
            'chat.postMessage',
            channel=channel or self.channel,
            text=message,
            as_user=True,
            link_names=True,
            username=self.bot_id)

    def remember_timestamp(self, timestamp):
        """ Record the timestamp from a given log line as its mktime float """
        d = datetime.strptime(timestamp, TIMESTAMP_FORMAT)
        seconds_timestamp = time.mktime(d.timetuple())

        with open(self.most_recent_timestamp_file, 'w') as f:
            f.write(str(seconds_timestamp))

    def parse_slack_output(self, slack_rtm_output):
        """ Parse the output of the Slack Real-Time Messaging firehose

            Look for messages directed at our bot (using the self.at_bot marker), and return the relevant information
        """
        output_list = slack_rtm_output
        if output_list and len(output_list) > 0:
            for output in output_list:
                if output and 'text' in output and self.at_bot in output['text']:
                    # return text after the @ mention, whitespace removed
                    return output['text'].split(self.at_bot)[1].strip().lower(), \
                           output['channel']
        return None, None

    def handle_command(self, command, channel):
        """ Process the command given from a channel and write back to same.

            If the command is not understoon, return a helpful message.
        """
        command, args = command.split()
        handler = self.commands.get(command, self.unknown_command)
        response = handler(args)
        self.post_message(response, channel)

    def run(self):
        """ The main loop - read from the Slack RTM firehose, and also keep an eye on the server's latest.log """
        if self.slack_client.rtm_connect():
            with open(self.latest_log) as f:
                while True:
                    command, channel = self.parse_slack_output(self.slack_client.rtm_read())
                    if command and channel:
                        # first, respond to in-Slack messages
                        self.handle_command(command, channel)
                        time.sleep(self.READ_WEBSOCKET_DELAY)
                    else:
                        # else, read server logs and process them
                        line = f.readline()

                        timestamp_match = timestamp_pattern.match(line)
                        if timestamp_match:
                            line_datetime = datetime.strptime(timestamp_match.group(1), TIMESTAMP_FORMAT)

                        if line_datetime <= self.most_recent_timestamp:
                            continue

                        chat_match = chat_pattern.match(line)
                        if chat_match:
                            timestamp, user, message = chat_match.groups()
                            self.post_message('{} said: {}'.format(user, message))
                            self.remember_timestamp(timestamp)
                            continue

                        join_match = join_pattern.match(line)
                        if join_match:
                            timestamp, user, message = join_match.groups()
                            self.post_message('{} {}'.format(user, message))
                            self.remember_timestamp(timestamp)
                            self.current_players.add(user)
                            continue

                        left_match = left_pattern.match(line)
                        if left_match:
                            timestamp, user, message = left_match.groups()
                            self.post_message('{} {}'.format(user, message))
                            self.remember_timestamp(timestamp)
                            self.current_players.remove(user)
                            continue

                        for pattern in broadcast_patterns:
                            maybe_match = pattern.match(line)
                            if maybe_match:
                                timestamp, user, message = maybe_match.groups()
                                self.post_message('{} {}'.format(user, message))
                                self.remember_timestamp(timestamp)
                                continue
        else:
            print("Connection failed. Invalid Slack token or bot ID?")

    # Commands

    def unknown_command(self):
        """ The default response for commands the bot doesn't understand. """
        return "So far, all I know how to do is `list`! Tell @zacbir to add more smarts!"

    def list_current_players(self):
        """ List the currently logged in users """
        current_players = self.current_players
        response = "There {} currently {} player{} logged into the server{}.".format(
            'is' if len(current_players) == 1 else 'are',
            len(current_players),
            '' if len(current_players) == 1 else 's',
            '' if len(current_players) == 0 else ': {}'.format(', '.join(current_players)))
        return response

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Launch a bot to communicate information about a shared Minecraft server to Slack')
    parser.add_argument('-d', '--directory', help="The directory where the Minecraft server lives")
    args = parser.parse_args()

    api_key = os.environ.get('SLACK_API_KEY')
    slack_client = SlackClient(api_key)

    minecraft_bot = MinecraftBot(
        os.environ.get('SLACK_BOT_ID'),
        slack_client,
        args.directory)

    minecraft_bot.run()
<|endoftext|>


<commit_before>import os
import json
import telegram
from mapbox import Geocoder

from libs.googleapis import get_timezone

WELCOME_LOCATION_SETUP = ("I have a lot of amazing functions that depends on your location 🌍, " +
                          "can you tell it?")

HOW_TO_SEND_LOCATION = ("You can attach location to message 📎 or type name of your city 🔡")
TYPE_LOCATION_AGAIN = "Oh, sorry, I don't understand 🙁\n\nYou can try again 🔡 or send me a location 🌐"

geocoder = Geocoder()

def register(bot):
    bot.handlers['welcome-location-setup'] = welcome_location_setup
    bot.handlers['location-setup-result'] = location_setup_result
    bot.handlers['new-location-setup-result'] = new_location_setup_result
    bot.handlers['location-new'] = new_location

def geocode(location_name, bot=None):
    response = geocoder.forward(location_name).json()
    if bot:
        bot.logger.info('Mapbox response: {}'.format(response))
    if 'features' not in response or not response['features']:
        return None
    place = response['features'][0]
    country = None
    for context in place['context']:
        if context['id'].startswith('country'):
            country = context['short_code']
    return {
        'long': place['center'][0],
        'lat': place['center'][1],
        'full_name': place.get('place_name'),
        'name': place.get('text'),
        'country': country,
        'timezone': get_timezone(place['center'][1], place['center'][0])
    }

def reverse_geocode(lat, long, bot=None):
    response = geocoder.reverse(long, lat).json()
    if bot:
        bot.logger.info('Mapbox response: {}'.format(response))
    place = response['features'][0]
    country = None
    for context in place['context']:
        if context['id'].startswith('country'):
            country = context['short_code']
    return {
        'long': place['center'][0],
        'lat': place['center'][1],
        'full_name': place.get('place_name'),
        'name': place.get('text'),
        'country': country,
        'timezone': get_timezone(place['center'][1], place['center'][0])
    }

def welcome_location_setup(message, bot):
    bot.user_set(message.u_id, 'next_handler', 'location-setup-result')
    bot.telegram.send_message(
        message.u_id, WELCOME_LOCATION_SETUP,
        reply_markup=telegram.ReplyKeyboardMarkup(
            [[telegram.KeyboardButton('📍 Send current location', request_location=True)]],
            resize_keyboard=True
        )
    )
    bot.telegram.send_message(message.u_id, HOW_TO_SEND_LOCATION)

def location_setup_result(message, bot):
    if not message.location:
        result = geocode(message.text, bot)
        if not result:
            bot.telegram.send_message(message.u_id, TYPE_LOCATION_AGAIN)
            bot.user_set(message.u_id, 'next_handler', 'location-setup-result')
            return
        bot.user_set(message.u_id, 'location', json.dumps(result))
    else:
        set_location(bot, message.u_id, message.location)
    bot.call_handler(message, 'welcome-setup-result')

def set_location(bot, u_id, location):
    result = reverse_geocode(location['latitude'], location['longitude'], bot)
    bot.user_set(u_id, 'location', json.dumps(result))
    return result

def new_location(message, bot):
    bot.user_set(message.u_id, 'next_handler', 'new-location-setup-result')
    bot.telegram.send_message(message.u_id, HOW_TO_SEND_LOCATION, reply_markup=telegram.ReplyKeyboardMarkup(
        [
            [telegram.KeyboardButton('📍 Send current location', request_location=True)],
            [bot.MENU_BUTTON]
        ],
        resize_keyboard=True
    ))

def new_location_setup_result(message, bot):
    if not message.location:
        result = geocode(message.text, bot)
        if not result:
            bot.telegram.send_message(message.u_id, TYPE_LOCATION_AGAIN)
            bot.user_set(message.u_id, 'next_handler', 'new-location-setup-result')
            return
        bot.user_set(message.u_id, 'location', json.dumps(result))
    else:
        set_location(bot, message.u_id, message.location)
    bot.telegram.send_message(message.u_id, 'Thanks 👌')
    bot.call_handler(message, 'main-menu')
<commit_msg>Location out of range fix<commit_after>import os
import json
import telegram
from mapbox import Geocoder

from libs.googleapis import get_timezone

WELCOME_LOCATION_SETUP = ("I have a lot of amazing functions that depends on your location 🌍, " +
                          "can you tell it?")

HOW_TO_SEND_LOCATION = ("You can attach location to message 📎 or type name of your city 🔡")
TYPE_LOCATION_AGAIN = "Oh, sorry, I don't understand 🙁\n\nYou can try again 🔡 or send me a location 🌐"

geocoder = Geocoder()

def register(bot):
    bot.handlers['welcome-location-setup'] = welcome_location_setup
    bot.handlers['location-setup-result'] = location_setup_result
    bot.handlers['new-location-setup-result'] = new_location_setup_result
    bot.handlers['location-new'] = new_location

def geocode(location_name, bot=None):
    response = geocoder.forward(location_name).json()
    if bot:
        bot.logger.info('Mapbox response: {}'.format(response))
    if 'features' not in response or not response['features']:
        return None
    place = response['features'][0]
    country = None
    for context in place['context']:
        if context['id'].startswith('country'):
            country = context['short_code']
    return {
        'long': place['center'][0],
        'lat': place['center'][1],
        'full_name': place.get('place_name'),
        'name': place.get('text'),
        'country': country,
        'timezone': get_timezone(place['center'][1], place['center'][0])
    }

def reverse_geocode(lat, long, bot=None):
    response = geocoder.reverse(long, lat).json()
    if bot:
        bot.logger.info('Mapbox response: {}'.format(response))
    if len(response['features']) == 0:
        return None
    place = response['features'][0]
    country = None
    for context in place['context']:
        if context['id'].startswith('country'):
            country = context['short_code']
    return {
        'long': place['center'][0],
        'lat': place['center'][1],
        'full_name': place.get('place_name'),
        'name': place.get('text'),
        'country': country,
        'timezone': get_timezone(place['center'][1], place['center'][0])
    }

def welcome_location_setup(message, bot):
    bot.user_set(message.u_id, 'next_handler', 'location-setup-result')
    bot.telegram.send_message(
        message.u_id, WELCOME_LOCATION_SETUP,
        reply_markup=telegram.ReplyKeyboardMarkup(
            [[telegram.KeyboardButton('📍 Send current location', request_location=True)]],
            resize_keyboard=True
        )
    )
    bot.telegram.send_message(message.u_id, HOW_TO_SEND_LOCATION)

def location_setup_result(message, bot):
    if not message.location:
        result = geocode(message.text, bot)
        if not result:
            bot.telegram.send_message(message.u_id, TYPE_LOCATION_AGAIN)
            bot.user_set(message.u_id, 'next_handler', 'location-setup-result')
            return
        bot.user_set(message.u_id, 'location', json.dumps(result))
    else:
        set_location(bot, message.u_id, message.location)
    bot.call_handler(message, 'welcome-setup-result')

def set_location(bot, u_id, location):
    result = reverse_geocode(location['latitude'], location['longitude'], bot)
    if result:
        bot.user_set(u_id, 'location', json.dumps(result))
        return result

def new_location(message, bot):
    bot.user_set(message.u_id, 'next_handler', 'new-location-setup-result')
    bot.telegram.send_message(message.u_id, HOW_TO_SEND_LOCATION, reply_markup=telegram.ReplyKeyboardMarkup(
        [
            [telegram.KeyboardButton('📍 Send current location', request_location=True)],
            [bot.MENU_BUTTON]
        ],
        resize_keyboard=True
    ))

def new_location_setup_result(message, bot):
    if not message.location:
        result = geocode(message.text, bot)
        if not result:
            bot.telegram.send_message(message.u_id, TYPE_LOCATION_AGAIN)
            bot.user_set(message.u_id, 'next_handler', 'new-location-setup-result')
            return
        bot.user_set(message.u_id, 'location', json.dumps(result))
    else:
        set_location(bot, message.u_id, message.location)
    bot.telegram.send_message(message.u_id, 'Thanks 👌')
    bot.call_handler(message, 'main-menu')
<|endoftext|>


<commit_before># Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.

from UM.Mesh.MeshReader import MeshReader
from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Logger import Logger
from UM.Math.Matrix import Matrix
from UM.Math.Vector import Vector
from UM.Scene.SceneNode import SceneNode
from UM.Scene.GroupDecorator import GroupDecorator
from UM.Math.Quaternion import Quaternion
from UM.Job import Job

import math
import zipfile

try:
    import xml.etree.cElementTree as ET
except ImportError:
    import xml.etree.ElementTree as ET

##    Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
class ThreeMFReader(MeshReader):
    def __init__(self):
        super().__init__()
        self._supported_extensions = [".3mf"]

        self._namespaces = {
            "3mf": "http://schemas.microsoft.com/3dmanufacturing/core/2015/02",
            "cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
        }

    def read(self, file_name):
        result = SceneNode()
        # The base object of 3mf is a zipped archive.
        archive = zipfile.ZipFile(file_name, "r")
        try:
            root = ET.parse(archive.open("3D/3dmodel.model"))

            # There can be multiple objects, try to load all of them.
            objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
            if len(objects) == 0:
                Logger.log("w", "No objects found in 3MF file %s, either the file is corrupt or you are using an outdated format", file_name)
                return None

            for entry in objects:
                mesh_builder = MeshBuilder()
                node = SceneNode()
                vertex_list = []

                # for vertex in entry.mesh.vertices.vertex:
                for vertex in entry.findall(".//3mf:vertex", self._namespaces):
                    vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
                    Job.yieldThread()

                triangles = entry.findall(".//3mf:triangle", self._namespaces)
                mesh_builder.reserveFaceCount(len(triangles))

                for triangle in triangles:
                    v1 = int(triangle.get("v1"))
                    v2 = int(triangle.get("v2"))
                    v3 = int(triangle.get("v3"))

                    mesh_builder.addFaceByPoints(vertex_list[v1][0], vertex_list[v1][1], vertex_list[v1][2],
                                                 vertex_list[v2][0], vertex_list[v2][1], vertex_list[v2][2],
                                                 vertex_list[v3][0], vertex_list[v3][1], vertex_list[v3][2])

                    Job.yieldThread()

                # Rotate the model; We use a different coordinate frame.
                rotation = Matrix()
                rotation.setByRotationAxis(-0.5 * math.pi, Vector(1, 0, 0))

                # TODO: We currently do not check for normals and simply recalculate them.
                mesh_builder.calculateNormals()
                mesh_builder.setFileName(file_name)
                mesh_data = mesh_builder.build().getTransformed(rotation)

                if not len(mesh_data.getVertices()):
                    continue  # This object doesn't have data, so skip it.

                node.setMeshData(mesh_data)
                node.setSelectable(True)

                transformations = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(entry.get("id")), self._namespaces)
                transformation = transformations[0] if transformations else None
                if transformation is not None and transformation.get("transform"):
                    splitted_transformation = transformation.get("transform").split()
                    ## Transformation is saved as:
                    ## M00 M01 M02 0.0
                    ## M10 M11 M12 0.0
                    ## M20 M21 M22 0.0
                    ## M30 M31 M32 1.0
                    ## We switch the row & cols as that is how everyone else uses matrices!
                    temp_mat = Matrix()
                    # Rotation & Scale
                    temp_mat._data[0,0] = splitted_transformation[0]
                    temp_mat._data[1,0] = splitted_transformation[1]
                    temp_mat._data[2,0] = splitted_transformation[2]
                    temp_mat._data[0,1] = splitted_transformation[3]
                    temp_mat._data[1,1] = splitted_transformation[4]
                    temp_mat._data[2,1] = splitted_transformation[5]
                    temp_mat._data[0,2] = splitted_transformation[6]
                    temp_mat._data[1,2] = splitted_transformation[7]
                    temp_mat._data[2,2] = splitted_transformation[8]

                    # Translation
                    temp_mat._data[0,3] = splitted_transformation[9]
                    temp_mat._data[1,3] = splitted_transformation[10]
                    temp_mat._data[2,3] = splitted_transformation[11]

                    node.setTransformation(temp_mat)

                try:
                    node.getBoundingBox()  # Selftest - There might be more functions that should fail
                except:
                    continue

                result.addChild(node)

                Job.yieldThread()

            # If there is more then one object, group them.
            if len(objects) > 1:
                group_decorator = GroupDecorator()
                result.addDecorator(group_decorator)
            elif len(objects) == 1:
                result = result.getChildren()[0]  # Only one object found, return that.
        except Exception as e:
            Logger.log("e", "exception occured in 3mf reader: %s", e)
        try:  # Selftest - There might be more functions that should fail
            bounding_box = result.getBoundingBox()
            bounding_box.isValid()
        except:
            return None

        return result
<commit_msg>Added extra checks & logging to 3mf reader<commit_after># Copyright (c) 2015 Ultimaker B.V.
# Cura is released under the terms of the AGPLv3 or higher.

from UM.Mesh.MeshReader import MeshReader
from UM.Mesh.MeshBuilder import MeshBuilder
from UM.Logger import Logger
from UM.Math.Matrix import Matrix
from UM.Math.Vector import Vector
from UM.Scene.SceneNode import SceneNode
from UM.Scene.GroupDecorator import GroupDecorator
from UM.Math.Quaternion import Quaternion
from UM.Job import Job

import math
import zipfile

try:
    import xml.etree.cElementTree as ET
except ImportError:
    import xml.etree.ElementTree as ET

##    Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
class ThreeMFReader(MeshReader):
    def __init__(self):
        super().__init__()
        self._supported_extensions = [".3mf"]

        self._namespaces = {
            "3mf": "http://schemas.microsoft.com/3dmanufacturing/core/2015/02",
            "cura": "http://software.ultimaker.com/xml/cura/3mf/2015/10"
        }

    def read(self, file_name):
        result = SceneNode()
        # The base object of 3mf is a zipped archive.
        archive = zipfile.ZipFile(file_name, "r")
        try:
            root = ET.parse(archive.open("3D/3dmodel.model"))

            # There can be multiple objects, try to load all of them.
            objects = root.findall("./3mf:resources/3mf:object", self._namespaces)
            if len(objects) == 0:
                Logger.log("w", "No objects found in 3MF file %s, either the file is corrupt or you are using an outdated format", file_name)
                return None

            for entry in objects:
                mesh_builder = MeshBuilder()
                node = SceneNode()
                vertex_list = []

                # for vertex in entry.mesh.vertices.vertex:
                for vertex in entry.findall(".//3mf:vertex", self._namespaces):
                    vertex_list.append([vertex.get("x"), vertex.get("y"), vertex.get("z")])
                    Job.yieldThread()

                triangles = entry.findall(".//3mf:triangle", self._namespaces)
                mesh_builder.reserveFaceCount(len(triangles))

                for triangle in triangles:
                    v1 = int(triangle.get("v1"))
                    v2 = int(triangle.get("v2"))
                    v3 = int(triangle.get("v3"))

                    mesh_builder.addFaceByPoints(vertex_list[v1][0], vertex_list[v1][1], vertex_list[v1][2],
                                                 vertex_list[v2][0], vertex_list[v2][1], vertex_list[v2][2],
                                                 vertex_list[v3][0], vertex_list[v3][1], vertex_list[v3][2])

                    Job.yieldThread()

                # Rotate the model; We use a different coordinate frame.
                rotation = Matrix()
                rotation.setByRotationAxis(-0.5 * math.pi, Vector(1, 0, 0))

                # TODO: We currently do not check for normals and simply recalculate them.
                mesh_builder.calculateNormals()
                mesh_builder.setFileName(file_name)
                mesh_data = mesh_builder.build().getTransformed(rotation)

                if not len(mesh_data.getVertices()):
                    Logger.log("d", "One of the objects does not have vertices. Skipping it.")
                    continue  # This object doesn't have data, so skip it.

                node.setMeshData(mesh_data)
                node.setSelectable(True)

                transformations = root.findall("./3mf:build/3mf:item[@objectid='{0}']".format(entry.get("id")), self._namespaces)
                transformation = transformations[0] if transformations else None
                if transformation is not None and transformation.get("transform"):
                    splitted_transformation = transformation.get("transform").split()
                    ## Transformation is saved as:
                    ## M00 M01 M02 0.0
                    ## M10 M11 M12 0.0
                    ## M20 M21 M22 0.0
                    ## M30 M31 M32 1.0
                    ## We switch the row & cols as that is how everyone else uses matrices!
                    temp_mat = Matrix()
                    # Rotation & Scale
                    temp_mat._data[0,0] = splitted_transformation[0]
                    temp_mat._data[1,0] = splitted_transformation[1]
                    temp_mat._data[2,0] = splitted_transformation[2]
                    temp_mat._data[0,1] = splitted_transformation[3]
                    temp_mat._data[1,1] = splitted_transformation[4]
                    temp_mat._data[2,1] = splitted_transformation[5]
                    temp_mat._data[0,2] = splitted_transformation[6]
                    temp_mat._data[1,2] = splitted_transformation[7]
                    temp_mat._data[2,2] = splitted_transformation[8]

                    # Translation
                    temp_mat._data[0,3] = splitted_transformation[9]
                    temp_mat._data[1,3] = splitted_transformation[10]
                    temp_mat._data[2,3] = splitted_transformation[11]

                    node.setTransformation(temp_mat)

                try:
                    node.getBoundingBox()  # Selftest - There might be more functions that should fail
                except:
                    Logger.log("w", "Bounding box test for object failed. Skipping this object")
                    continue

                result.addChild(node)

                Job.yieldThread()

            # If there is more then one object, group them.
            if len(objects) > 1:
                group_decorator = GroupDecorator()
                result.addDecorator(group_decorator)
            elif len(objects) == 1:
                if result.getChildren():
                    result = result.getChildren()[0]  # Only one object found, return that.
                else: # we failed to load any data
                    return None
        except Exception as e:
            Logger.log("e", "exception occured in 3mf reader: %s", e)
        try:  # Selftest - There might be more functions that should fail
            bounding_box = result.getBoundingBox()
            bounding_box.isValid()
        except:
            return None

        return result
<|endoftext|>