<commit_before>"""
:class:`.Bing` geocoder.
"""

from geopy.compat import urlencode
from geopy.geocoders.base import Geocoder, DEFAULT_FORMAT_STRING, \
    DEFAULT_TIMEOUT, DEFAULT_SCHEME
from geopy.location import Location
from geopy.util import logger, join_filter

__all__ = ("Bing", )

class Bing(Geocoder):
    """
    Geocoder using the Bing Maps Locations API. Documentation at:
        https://msdn.microsoft.com/en-us/library/ff701715.aspx
    """

    def __init__(
            self,
            api_key,
            format_string=DEFAULT_FORMAT_STRING,
            scheme=DEFAULT_SCHEME,
            timeout=DEFAULT_TIMEOUT,
            proxies=None,
        ):  # pylint: disable=R0913
        """Initialize a customized Bing geocoder with location-specific
        address information and your Bing Maps API key.

        :param string api_key: Should be a valid Bing Maps API key.

        :param string format_string: String containing '%s' where the
            string to geocode should be interpolated before querying the
            geocoder. For example: '%s, Mountain View, CA'. The default
            is just '%s'.

        :param string scheme: Use 'https' or 'http' as the API URL's scheme.
            Default is https. Note that SSL connections' certificates are not
            verified.

            .. versionadded:: 0.97

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception.

            .. versionadded:: 0.97

        :param dict proxies: If specified, routes this geocoder's requests
            through the specified proxy. E.g., {"https": "192.0.2.0"}. For
            more information, see documentation on
            :class:`urllib2.ProxyHandler`.

            .. versionadded:: 0.96
        """
        super(Bing, self).__init__(format_string, scheme, timeout, proxies)
        self.api_key = api_key
        self.api = "%s://dev.virtualearth.net/REST/v1/Locations" % self.scheme

    def geocode(
            self,
            query,
            exactly_one=True,
            user_location=None,
            timeout=None,
            culture=None,
            include_neighborhood=None,
            include_country_code=False
        ):  # pylint: disable=W0221
        """
        Geocode an address.

        :param string query: The address or query you wish to geocode.

        :param bool exactly_one: Return one result or a list of results, if
            available.

        :param user_location: Prioritize results closer to
            this location.

            .. versionadded:: 0.96

        :type user_location: :class:`geopy.point.Point`

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception. Set this only if you wish to override, on this call
            only, the value set during the geocoder's initialization.

            .. versionadded:: 0.97

        :param string culture: Affects the language of the response,
            must be a two-letter country code.

            .. versionadded:: 1.4.0

        :param boolean include_neighborhood: Sets whether to include the
            neighborhood field in the response.

            .. versionadded:: 1.4.0

        :param boolean include_country_code: Sets whether to include the
            two-letter ISO code of the country in the response (field name
            'countryRegionIso2').

            .. versionadded:: 1.4.0
        """
        params = {
            'query': self.format_string % query,
            'key': self.api_key
        }
        if user_location:
            params['userLocation'] = ",".join(
                (str(user_location.latitude), str(user_location.longitude))
            )
        if exactly_one is True:
            params['maxResults'] = 1
        if culture:
            params['culture'] = culture
        if include_neighborhood is not None:
            params['includeNeighborhood'] = include_neighborhood
        if include_country_code:
            params['include'] = 'ciso2'  # the only acceptable value

        url = "?".join((self.api, urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout),
            exactly_one
        )

    def reverse(self, query, exactly_one=True, timeout=None):
        """
        Reverse geocode a point.

        :param query: The coordinates for which you wish to obtain the
            closest human-readable addresses.
        :type query: :class:`geopy.point.Point`, list or tuple of (latitude,
            longitude), or string as "%(latitude)s, %(longitude)s".

        :param bool exactly_one: Return one result, or a list?

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception. Set this only if you wish to override, on this call
            only, the value set during the geocoder's initialization.

            .. versionadded:: 0.97
        """
        point = self._coerce_point_to_string(query)
        params = {'key': self.api_key}
        url = "%s/%s?%s" % (
            self.api, point, urlencode(params))

        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout),
            exactly_one
        )

    @staticmethod
    def _parse_json(doc, exactly_one=True):  # pylint: disable=W0221
        """
        Parse a location name, latitude, and longitude from an JSON response.
        """
        resources = doc['resourceSets'][0]['resources']
        if resources is None or not len(resources): # pragma: no cover
            return None

        def parse_resource(resource):
            """
            Parse each return object.
            """
            stripchars = ", \n"
            addr = resource['address']

            address = addr.get('addressLine', '').strip(stripchars)
            city = addr.get('locality', '').strip(stripchars)
            state = addr.get('adminDistrict', '').strip(stripchars)
            zipcode = addr.get('postalCode', '').strip(stripchars)
            country = addr.get('countryRegion', '').strip(stripchars)

            city_state = join_filter(", ", [city, state])
            place = join_filter(" ", [city_state, zipcode])
            location = join_filter(", ", [address, place, country])

            latitude = resource['point']['coordinates'][0] or None
            longitude = resource['point']['coordinates'][1] or None
            if latitude and longitude:
                latitude = float(latitude)
                longitude = float(longitude)

            return Location(location, (latitude, longitude), resource)

        if exactly_one:
            return parse_resource(resources[0])
        else:
            return [parse_resource(resource) for resource in resources]
<commit_msg>Bing checks statusCode attribute<commit_after>"""
:class:`.Bing` geocoder.
"""

from geopy.compat import urlencode
from geopy.geocoders.base import Geocoder, DEFAULT_FORMAT_STRING, \
    DEFAULT_TIMEOUT, DEFAULT_SCHEME
from geopy.location import Location
from geopy.exc import (
    GeocoderAuthenticationFailure,
    GeocoderQuotaExceeded,
    GeocoderInsufficientPrivileges,
    GeocoderUnavailable,
    GeocoderServiceError,
)
from geopy.util import logger, join_filter

__all__ = ("Bing", )

class Bing(Geocoder):
    """
    Geocoder using the Bing Maps Locations API. Documentation at:
        https://msdn.microsoft.com/en-us/library/ff701715.aspx
    """

    def __init__(
            self,
            api_key,
            format_string=DEFAULT_FORMAT_STRING,
            scheme=DEFAULT_SCHEME,
            timeout=DEFAULT_TIMEOUT,
            proxies=None,
        ):  # pylint: disable=R0913
        """Initialize a customized Bing geocoder with location-specific
        address information and your Bing Maps API key.

        :param string api_key: Should be a valid Bing Maps API key.

        :param string format_string: String containing '%s' where the
            string to geocode should be interpolated before querying the
            geocoder. For example: '%s, Mountain View, CA'. The default
            is just '%s'.

        :param string scheme: Use 'https' or 'http' as the API URL's scheme.
            Default is https. Note that SSL connections' certificates are not
            verified.

            .. versionadded:: 0.97

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception.

            .. versionadded:: 0.97

        :param dict proxies: If specified, routes this geocoder's requests
            through the specified proxy. E.g., {"https": "192.0.2.0"}. For
            more information, see documentation on
            :class:`urllib2.ProxyHandler`.

            .. versionadded:: 0.96
        """
        super(Bing, self).__init__(format_string, scheme, timeout, proxies)
        self.api_key = api_key
        self.api = "%s://dev.virtualearth.net/REST/v1/Locations" % self.scheme

    def geocode(
            self,
            query,
            exactly_one=True,
            user_location=None,
            timeout=None,
            culture=None,
            include_neighborhood=None,
            include_country_code=False
        ):  # pylint: disable=W0221
        """
        Geocode an address.

        :param string query: The address or query you wish to geocode.

        :param bool exactly_one: Return one result or a list of results, if
            available.

        :param user_location: Prioritize results closer to
            this location.

            .. versionadded:: 0.96

        :type user_location: :class:`geopy.point.Point`

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception. Set this only if you wish to override, on this call
            only, the value set during the geocoder's initialization.

            .. versionadded:: 0.97

        :param string culture: Affects the language of the response,
            must be a two-letter country code.

            .. versionadded:: 1.4.0

        :param boolean include_neighborhood: Sets whether to include the
            neighborhood field in the response.

            .. versionadded:: 1.4.0

        :param boolean include_country_code: Sets whether to include the
            two-letter ISO code of the country in the response (field name
            'countryRegionIso2').

            .. versionadded:: 1.4.0
        """
        params = {
            'query': self.format_string % query,
            'key': self.api_key
        }
        if user_location:
            params['userLocation'] = ",".join(
                (str(user_location.latitude), str(user_location.longitude))
            )
        if exactly_one is True:
            params['maxResults'] = 1
        if culture:
            params['culture'] = culture
        if include_neighborhood is not None:
            params['includeNeighborhood'] = include_neighborhood
        if include_country_code:
            params['include'] = 'ciso2'  # the only acceptable value

        url = "?".join((self.api, urlencode(params)))
        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout),
            exactly_one
        )

    def reverse(self, query, exactly_one=True, timeout=None):
        """
        Reverse geocode a point.

        :param query: The coordinates for which you wish to obtain the
            closest human-readable addresses.
        :type query: :class:`geopy.point.Point`, list or tuple of (latitude,
            longitude), or string as "%(latitude)s, %(longitude)s".

        :param bool exactly_one: Return one result, or a list?

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception. Set this only if you wish to override, on this call
            only, the value set during the geocoder's initialization.

            .. versionadded:: 0.97
        """
        point = self._coerce_point_to_string(query)
        params = {'key': self.api_key}
        url = "%s/%s?%s" % (
            self.api, point, urlencode(params))

        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout),
            exactly_one
        )

    @staticmethod
    def _parse_json(doc, exactly_one=True):  # pylint: disable=W0221
        """
        Parse a location name, latitude, and longitude from an JSON response.
        """
        status_code = doc.get("statusCode", 200)
        if status_code != 200:
            err = doc.get("errorDetails", "")
            if status_code == 401:
                raise GeocoderAuthenticationFailure(err)
            elif status_code == 403:
                raise GeocoderInsufficientPrivileges(err)
            elif status_code == 429:
                raise GeocoderQuotaExceeded(err)
            elif status_code == 503:
                raise GeocoderUnavailable(err)
            else:
                raise GeocoderServiceError(err)

        resources = doc['resourceSets'][0]['resources']
        if resources is None or not len(resources): # pragma: no cover
            return None

        def parse_resource(resource):
            """
            Parse each return object.
            """
            stripchars = ", \n"
            addr = resource['address']

            address = addr.get('addressLine', '').strip(stripchars)
            city = addr.get('locality', '').strip(stripchars)
            state = addr.get('adminDistrict', '').strip(stripchars)
            zipcode = addr.get('postalCode', '').strip(stripchars)
            country = addr.get('countryRegion', '').strip(stripchars)

            city_state = join_filter(", ", [city, state])
            place = join_filter(" ", [city_state, zipcode])
            location = join_filter(", ", [address, place, country])

            latitude = resource['point']['coordinates'][0] or None
            longitude = resource['point']['coordinates'][1] or None
            if latitude and longitude:
                latitude = float(latitude)
                longitude = float(longitude)

            return Location(location, (latitude, longitude), resource)

        if exactly_one:
            return parse_resource(resources[0])
        else:
            return [parse_resource(resource) for resource in resources]
<|endoftext|>


<commit_before>"""
Main module for the TerminalView plugin with commands for opening and
initializing a terminal view
"""

import os
import threading
import time

import sublime
import sublime_plugin

from . import sublime_terminal_buffer
from . import linux_pty
from . import utils

class TerminalViewManager():
    """
    A manager to control all SublimeBuffer instances so they can be looked up
    based on the sublime view they are governing.
    """
    @classmethod
    def register(cls, uid, term_view):
        if not hasattr(cls, "term_views"):
            cls.term_views = {}
        cls.term_views[uid] = term_view

    @classmethod
    def deregister(cls, uid):
        if hasattr(cls, "term_views"):
            del cls.term_views[uid]

    @classmethod
    def load_from_id(cls, uid):
        if hasattr(cls, "term_views") and uid in cls.term_views:
            return cls.term_views[uid]
        else:
            return None

class TerminalViewOpen(sublime_plugin.WindowCommand):
    """
    Main entry command for opening a terminal view. Only one instance of this
    class per sublime window. Once a terminal view has been opened the
    TerminalViewActivate instance for that view is called to handle everything.
    """
    def run(self, cmd="/bin/bash -l", title="Terminal", cwd=None, syntax=None):
        """
        Open a new terminal view

        Args:
            cmd (str, optional): Shell to execute. Defaults to 'bash -l.
            title (str, optional): Terminal view title. Defaults to 'Terminal'.
            cwd (str, optional): The working dir to start out with. Defaults to
                                 either the currently open file, the currently
                                 open folder, $HOME, or "/", in that order of
                                 precedence. You may pass arbitrary snippet-like
                                 variables.
            syntax (str, optional): Syntax file to use in the view.
        """
        if sublime.platform() not in ("linux", "osx"):
            sublime.error_message("TerminalView: Unsupported OS")
            return

        st_vars = self.window.extract_variables()
        if not cwd:
            cwd = "${file_path:${folder}}"
        cwd = sublime.expand_variables(cwd, st_vars)
        if not cwd:
            cwd = os.environ.get("HOME", None)
        if not cwd:
            # Last resort
            cwd = "/"

        args = {"cmd": cmd, "title": title, "cwd": cwd, "syntax": syntax}
        self.window.new_file().run_command("terminal_view_activate", args=args)

class TerminalViewActivate(sublime_plugin.TextCommand):
    def run(self, _, cmd, title, cwd, syntax):
        terminal_view = TerminalView(self.view)
        TerminalViewManager.register(self.view.id(), terminal_view)
        terminal_view.run(cmd, title, cwd, syntax)

class TerminalView:
    """
    Main class to glue all parts together for a single instance of a terminal
    view.
    """
    def __init__(self, view):
        self.view = view

    def __del__(self):
        utils.ConsoleLogger.log("Terminal view instance deleted")

    def run(self, cmd, title, cwd, syntax):
        """
        Initialize the view as a terminal view.
        """
        self._cmd = cmd
        self._cwd = cwd

        # Initialize the sublime view
        self._terminal_buffer = \
            sublime_terminal_buffer.SublimeTerminalBuffer(self.view, title, syntax)
        self._terminal_buffer.set_keypress_callback(self.terminal_view_keypress_callback)
        self._terminal_buffer_is_open = True
        self._terminal_rows = 0
        self._terminal_columns = 0

        # Start the underlying shell
        self._shell = linux_pty.LinuxPty(self._cmd.split(), self._cwd)
        self._shell_is_running = True

        # Save the command args in view settings so it can restarted when ST3 is
        # restarted (or when changing back to a project that had a terminal view
        # open)
        args = {"cmd": cmd, "title": title, "cwd": cwd, "syntax": syntax}
        self.view.settings().set("terminal_view_activate_args", args)

        # Start the main loop
        threading.Thread(target=self._main_update_loop).start()

    def terminal_view_keypress_callback(self, key, ctrl=False, alt=False, shift=False, meta=False):
        """
        Callback when a keypress is registered in the Sublime Terminal buffer.

        Args:
            key (str): String describing pressed key. May be a name like 'home'.
            ctrl (boolean, optional)
            alt (boolean, optional)
            shift (boolean, optional)
            meta (boolean, optional)
        """
        self._shell.send_keypress(key, ctrl, alt, shift, meta)

    def send_string_to_shell(self, string):
        self._shell.send_string(string)

    def _main_update_loop(self):
        """
        This is the main update function. It attempts to run at a certain number
        of frames per second, and keeps input and output synchronized.
        """
        # 30 frames per second should be responsive enough
        ideal_delta = 1.0 / 30.0
        current = time.time()
        while True:
            self._poll_shell_output()
            self._terminal_buffer.update_view()
            self._resize_screen_if_needed()
            if (not self._terminal_buffer.is_open()) or (not self._shell.is_running()):
                self._stop()
                break

            previous = current
            current = time.time()
            actual_delta = current - previous
            time_left = ideal_delta - actual_delta
            if time_left > 0.0:
                time.sleep(time_left)

    def _poll_shell_output(self):
        """
        Poll the output of the shell
        """
        max_read_size = 4096
        data = self._shell.receive_output(max_read_size)
        if data is not None:
            utils.ConsoleLogger.log("Got %u bytes of data from shell" % (len(data), ))
            self._terminal_buffer.insert_data(data)

    def _resize_screen_if_needed(self):
        """
        Check if the terminal view was resized. If so update the screen size of
        the terminal and notify the shell.
        """
        (rows, cols) = self._terminal_buffer.view_size()
        row_diff = abs(self._terminal_rows - rows)
        col_diff = abs(self._terminal_columns - cols)

        if row_diff or col_diff:
            log = "Changing screen size from (%i, %i) to (%i, %i)" % \
                  (self._terminal_rows, self._terminal_columns, rows, cols)
            utils.ConsoleLogger.log(log)

            self._terminal_rows = rows
            self._terminal_columns = cols
            self._shell.update_screen_size(self._terminal_rows, self._terminal_columns)
            self._terminal_buffer.update_terminal_size(self._terminal_rows, self._terminal_columns)

    def _stop(self):
        """
        Stop the terminal and close everything down.
        """
        self._terminal_buffer.close()
        self._terminal_buffer_is_open = False
        self._shell.stop()
        self._shell_is_running = False

        # When stopping deregister in the manager
        TerminalViewManager.deregister(self.view.id())

def plugin_loaded():
    # When the plugin gets loaded everything should be dead so wait a bit to
    # make sure views are ready, then try to restart all sessions.
    sublime.set_timeout(restart_all_terminal_view_sessions, 100)

def restart_all_terminal_view_sessions():
    win = sublime.active_window()
    for view in win.views():
        restart_terminal_view_session(view)

class ProjectSwitchWatcher(sublime_plugin.EventListener):
    def on_load(self, view):
        # On load is called on old terminal views when switching between projects
        restart_terminal_view_session(view)

def restart_terminal_view_session(view):
    settings = view.settings()
    if settings.has("terminal_view_activate_args"):
        if TerminalViewManager.load_from_id(view.id()) is None:
            view.run_command("terminal_view_clear")
            args = settings.get("terminal_view_activate_args")
            view.run_command("terminal_view_activate", args=args)

class TerminalViewSendString(sublime_plugin.WindowCommand):
    """
    Command to send a string to an active terminal.

    Example to send sigint:
        window.run_command("terminal_view_send_string", args={"string": "\x03"})
    """
    def run(self, string, current_window_only=True):
        """
        Send a string

        Args:
            string (str): string of characters to send
            current_window_only (bool, optional): constrain terminal search to
                                                  the current ST window only
        """
        if current_window_only:
            windows = [self.window]
        else:
            windows = sublime.windows()

        term_view = None
        for w in windows:
            for v in w.views():
                term_view = TerminalViewManager.load_from_id(v.id())
                if term_view is not None:
                    group, index = w.get_view_index(v)
                    active_view = w.active_view_in_group(group)
                    if active_view == v:
                        break

        if term_view is None:
            utils.ConsoleLogger.log("No terminal found")
            return

        term_view.send_string_to_shell(string)
<commit_msg>Move TerminalView instance registration into run loop to keep it closer coupled with deregistration<commit_after>"""
Main module for the TerminalView plugin with commands for opening and
initializing a terminal view
"""

import os
import threading
import time

import sublime
import sublime_plugin

from . import sublime_terminal_buffer
from . import linux_pty
from . import utils

class TerminalViewManager():
    """
    A manager to control all TerminalView instances so they can be looked up
    based on the sublime view they are governing.
    """
    @classmethod
    def register(cls, uid, term_view):
        if not hasattr(cls, "term_views"):
            cls.term_views = {}
        cls.term_views[uid] = term_view

    @classmethod
    def deregister(cls, uid):
        if hasattr(cls, "term_views"):
            del cls.term_views[uid]

    @classmethod
    def load_from_id(cls, uid):
        if hasattr(cls, "term_views") and uid in cls.term_views:
            return cls.term_views[uid]
        else:
            return None

class TerminalViewOpen(sublime_plugin.WindowCommand):
    """
    Main entry command for opening a terminal view. Only one instance of this
    class per sublime window. Once a terminal view has been opened the
    TerminalViewActivate instance for that view is called to handle everything.
    """
    def run(self, cmd="/bin/bash -l", title="Terminal", cwd=None, syntax=None):
        """
        Open a new terminal view

        Args:
            cmd (str, optional): Shell to execute. Defaults to 'bash -l.
            title (str, optional): Terminal view title. Defaults to 'Terminal'.
            cwd (str, optional): The working dir to start out with. Defaults to
                                 either the currently open file, the currently
                                 open folder, $HOME, or "/", in that order of
                                 precedence. You may pass arbitrary snippet-like
                                 variables.
            syntax (str, optional): Syntax file to use in the view.
        """
        if sublime.platform() not in ("linux", "osx"):
            sublime.error_message("TerminalView: Unsupported OS")
            return

        st_vars = self.window.extract_variables()
        if not cwd:
            cwd = "${file_path:${folder}}"
        cwd = sublime.expand_variables(cwd, st_vars)
        if not cwd:
            cwd = os.environ.get("HOME", None)
        if not cwd:
            # Last resort
            cwd = "/"

        args = {"cmd": cmd, "title": title, "cwd": cwd, "syntax": syntax}
        self.window.new_file().run_command("terminal_view_activate", args=args)

class TerminalViewActivate(sublime_plugin.TextCommand):
    def run(self, _, cmd, title, cwd, syntax):
        terminal_view = TerminalView(self.view)
        terminal_view.run(cmd, title, cwd, syntax)

class TerminalView:
    """
    Main class to glue all parts together for a single instance of a terminal
    view.
    """
    def __init__(self, view):
        self.view = view

    def __del__(self):
        utils.ConsoleLogger.log("Terminal view instance deleted")

    def run(self, cmd, title, cwd, syntax):
        """
        Initialize the view as a terminal view.
        """
        self._cmd = cmd
        self._cwd = cwd

        # Initialize the sublime view
        self._terminal_buffer = \
            sublime_terminal_buffer.SublimeTerminalBuffer(self.view, title, syntax)
        self._terminal_buffer.set_keypress_callback(self.keypress_callback)
        self._terminal_buffer_is_open = True
        self._terminal_rows = 0
        self._terminal_columns = 0

        # Start the underlying shell
        self._shell = linux_pty.LinuxPty(self._cmd.split(), self._cwd)
        self._shell_is_running = True

        # Save the command args in view settings so it can restarted when ST3 is
        # restarted (or when changing back to a project that had a terminal view
        # open)
        args = {"cmd": cmd, "title": title, "cwd": cwd, "syntax": syntax}
        self.view.settings().set("terminal_view_activate_args", args)

        # Register the terminal view instance in the manager
        TerminalViewManager.register(self.view.id(), self)

        # Start the main loop
        threading.Thread(target=self._main_update_loop).start()

    def keypress_callback(self, key, ctrl=False, alt=False, shift=False, meta=False):
        """
        Callback when a keypress is registered in the Sublime Terminal buffer.

        Args:
            key (str): String describing pressed key. May be a name like 'home'.
            ctrl (boolean, optional)
            alt (boolean, optional)
            shift (boolean, optional)
            meta (boolean, optional)
        """
        self._shell.send_keypress(key, ctrl, alt, shift, meta)

    def send_string_to_shell(self, string):
        self._shell.send_string(string)

    def _main_update_loop(self):
        """
        This is the main update function. It attempts to run at a certain number
        of frames per second, and keeps input and output synchronized.
        """
        # 30 frames per second should be responsive enough
        ideal_delta = 1.0 / 30.0
        current = time.time()
        while True:
            self._poll_shell_output()
            self._terminal_buffer.update_view()
            self._resize_screen_if_needed()
            if (not self._terminal_buffer.is_open()) or (not self._shell.is_running()):
                self._stop()
                break

            previous = current
            current = time.time()
            actual_delta = current - previous
            time_left = ideal_delta - actual_delta
            if time_left > 0.0:
                time.sleep(time_left)

    def _poll_shell_output(self):
        """
        Poll the output of the shell
        """
        max_read_size = 4096
        data = self._shell.receive_output(max_read_size)
        if data is not None:
            utils.ConsoleLogger.log("Got %u bytes of data from shell" % (len(data), ))
            self._terminal_buffer.insert_data(data)

    def _resize_screen_if_needed(self):
        """
        Check if the terminal view was resized. If so update the screen size of
        the terminal and notify the shell.
        """
        (rows, cols) = self._terminal_buffer.view_size()
        row_diff = abs(self._terminal_rows - rows)
        col_diff = abs(self._terminal_columns - cols)

        if row_diff or col_diff:
            log = "Changing screen size from (%i, %i) to (%i, %i)" % \
                  (self._terminal_rows, self._terminal_columns, rows, cols)
            utils.ConsoleLogger.log(log)

            self._terminal_rows = rows
            self._terminal_columns = cols
            self._shell.update_screen_size(self._terminal_rows, self._terminal_columns)
            self._terminal_buffer.update_terminal_size(self._terminal_rows, self._terminal_columns)

    def _stop(self):
        """
        Stop the terminal and close everything down.
        """
        self._terminal_buffer.close()
        self._terminal_buffer_is_open = False
        self._shell.stop()
        self._shell_is_running = False

        # When stopping deregister in the manager
        TerminalViewManager.deregister(self.view.id())

def plugin_loaded():
    # When the plugin gets loaded everything should be dead so wait a bit to
    # make sure views are ready, then try to restart all sessions.
    sublime.set_timeout(restart_all_terminal_view_sessions, 100)

def restart_all_terminal_view_sessions():
    win = sublime.active_window()
    for view in win.views():
        restart_terminal_view_session(view)

class ProjectSwitchWatcher(sublime_plugin.EventListener):
    def on_load(self, view):
        # On load is called on old terminal views when switching between projects
        restart_terminal_view_session(view)

def restart_terminal_view_session(view):
    settings = view.settings()
    if settings.has("terminal_view_activate_args"):
        if TerminalViewManager.load_from_id(view.id()) is None:
            view.run_command("terminal_view_clear")
            args = settings.get("terminal_view_activate_args")
            view.run_command("terminal_view_activate", args=args)

class TerminalViewSendString(sublime_plugin.WindowCommand):
    """
    Command to send a string to an active terminal.

    Example to send sigint:
        window.run_command("terminal_view_send_string", args={"string": "\x03"})
    """
    def run(self, string, current_window_only=True):
        """
        Send a string

        Args:
            string (str): string of characters to send
            current_window_only (bool, optional): constrain terminal search to
                                                  the current ST window only
        """
        if current_window_only:
            windows = [self.window]
        else:
            windows = sublime.windows()

        term_view = None
        for w in windows:
            for v in w.views():
                term_view = TerminalViewManager.load_from_id(v.id())
                if term_view is not None:
                    group, index = w.get_view_index(v)
                    active_view = w.active_view_in_group(group)
                    if active_view == v:
                        break

        if term_view is None:
            utils.ConsoleLogger.log("No terminal found")
            return

        term_view.send_string_to_shell(string)
<|endoftext|>


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

"""
The MIT License (MIT)

Copyright (c) 2015-2019 Rapptz

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""

import array
import asyncio
import unicodedata
from base64 import b64encode
from bisect import bisect_left
import datetime
from email.utils import parsedate_to_datetime
import functools
from inspect import isawaitable as _isawaitable
import json
import re
import warnings

from .errors import InvalidArgument
from .object import Object

DISCORD_EPOCH = 1420070400000

class cached_property:
    def __init__(self, function):
        self.function = function
        self.__doc__ = getattr(function, '__doc__')

    def __get__(self, instance, owner):
        if instance is None:
            return self

        value = self.function(instance)
        setattr(instance, self.function.__name__, value)

        return value

class CachedSlotProperty:
    def __init__(self, name, function):
        self.name = name
        self.function = function
        self.__doc__ = getattr(function, '__doc__')

    def __get__(self, instance, owner):
        if instance is None:
            return self

        try:
            return getattr(instance, self.name)
        except AttributeError:
            value = self.function(instance)
            setattr(instance, self.name, value)
            return value

def cached_slot_property(name):
    def decorator(func):
        return CachedSlotProperty(name, func)
    return decorator

def parse_time(timestamp):
    if timestamp:
        return datetime.datetime(*map(int, re.split(r'[^\d]', timestamp.replace('+00:00', ''))))
    return None

def deprecated(instead=None):
    def actual_decorator(func):
        @functools.wraps(func)
        def decorated(*args, **kwargs):
            warnings.simplefilter('always', DeprecationWarning) # turn off filter
            if instead:
                fmt = "{0.__name__} is deprecated, use {1} instead."
            else:
                fmt = '{0.__name__} is deprecated.'

            warnings.warn(fmt.format(func, instead), stacklevel=3, category=DeprecationWarning)
            warnings.simplefilter('default', DeprecationWarning) # reset filter
            return func(*args, **kwargs)
        return decorated
    return actual_decorator

def oauth_url(client_id, permissions=None, guild=None, redirect_uri=None):
    """A helper function that returns the OAuth2 URL for inviting the bot
    into guilds.

    Parameters
    -----------
    client_id: :class:`str`
        The client ID for your bot.
    permissions: :class:`Permissions`
        The permissions you're requesting. If not given then you won't be requesting any
        permissions.
    guild: :class:`Guild`
        The guild to pre-select in the authorization screen, if available.
    redirect_uri: :class:`str`
        An optional valid redirect URI.
    """
    url = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot'.format(client_id)
    if permissions is not None:
        url = url + '&permissions=' + str(permissions.value)
    if guild is not None:
        url = url + "&guild_id=" + str(guild.id)
    if redirect_uri is not None:
        from urllib.parse import urlencode
        url = url + "&response_type=code&" + urlencode({'redirect_uri': redirect_uri})
    return url

def snowflake_time(id):
    """Returns the creation date in UTC of a discord id."""
    return datetime.datetime.utcfromtimestamp(((id >> 22) + DISCORD_EPOCH) / 1000)

def time_snowflake(datetime_obj, high=False):
    """Returns a numeric snowflake pretending to be created at the given date.

    When using as the lower end of a range, use time_snowflake(high=False) - 1 to be inclusive, high=True to be exclusive
    When using as the higher end of a range, use time_snowflake(high=True) + 1 to be inclusive, high=False to be exclusive

    Parameters
    -----------
    datetime_obj
        A timezone-naive datetime object representing UTC time.
    high: :class:`bool`
        Whether or not to set the lower 22 bit to high or low.
    """
    unix_seconds = (datetime_obj - type(datetime_obj)(1970, 1, 1)).total_seconds()
    discord_millis = int(unix_seconds * 1000 - DISCORD_EPOCH)

    return (discord_millis << 22) + (2**22-1 if high else 0)

def find(predicate, seq):
    """A helper to return the first element found in the sequence
    that meets the predicate. For example: ::

        member = find(lambda m: m.name == 'Mighty', channel.guild.members)

    would find the first :class:`Member` whose name is 'Mighty' and return it.
    If an entry is not found, then ``None`` is returned.

    This is different from `filter`_ due to the fact it stops the moment it finds
    a valid entry.

    .. _filter: https://docs.python.org/3.6/library/functions.html#filter

    Parameters
    -----------
    predicate
        A function that returns a boolean-like result.
    seq: iterable
        The iterable to search through.
    """

    for element in seq:
        if predicate(element):
            return element
    return None

def get(iterable, **attrs):
    r"""A helper that returns the first element in the iterable that meets
    all the traits passed in ``attrs``. This is an alternative for
    :func:`discord.utils.find`.

    When multiple attributes are specified, they are checked using
    logical AND, not logical OR. Meaning they have to meet every
    attribute passed in and not one of them.

    To have a nested attribute search (i.e. search by ``x.y``) then
    pass in ``x__y`` as the keyword argument.

    If nothing is found that matches the attributes passed, then
    ``None`` is returned.

    Examples
    ---------

    Basic usage:

    .. code-block:: python3

        member = discord.utils.get(message.guild.members, name='Foo')

    Multiple attribute matching:

    .. code-block:: python3

        channel = discord.utils.get(guild.voice_channels, name='Foo', bitrate=64000)

    Nested attribute matching:

    .. code-block:: python3

        channel = discord.utils.get(client.get_all_channels(), guild__name='Cool', name='general')

    Parameters
    -----------
    iterable
        An iterable to search through.
    \*\*attrs
        Keyword arguments that denote attributes to search with.
    """

    def predicate(elem):
        for attr, val in attrs.items():
            nested = attr.split('__')
            obj = elem
            for attribute in nested:
                obj = getattr(obj, attribute)

            if obj != val:
                return False
        return True

    return find(predicate, iterable)

def _unique(iterable):
    seen = set()
    adder = seen.add
    return [x for x in iterable if not (x in seen or adder(x))]

def _get_as_snowflake(data, key):
    try:
        value = data[key]
    except KeyError:
        return None
    else:
        return value and int(value)

def _get_mime_type_for_image(data):
    if data.startswith(b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A'):
        return 'image/png'
    elif data[6:10] in (b'JFIF', b'Exif'):
        return 'image/jpeg'
    elif data.startswith((b'\x47\x49\x46\x38\x37\x61', b'\x47\x49\x46\x38\x39\x61')):
        return 'image/gif'
    elif data.startswith(b'RIFF') and data[8:12] == b'WEBP':
        return 'image/webp'
    else:
        raise InvalidArgument('Unsupported image type given')

def _bytes_to_base64_data(data):
    fmt = 'data:{mime};base64,{data}'
    mime = _get_mime_type_for_image(data)
    b64 = b64encode(data).decode('ascii')
    return fmt.format(mime=mime, data=b64)

def to_json(obj):
    return json.dumps(obj, separators=(',', ':'), ensure_ascii=True)

def _parse_ratelimit_header(request):
    now = parsedate_to_datetime(request.headers['Date'])
    reset = datetime.datetime.fromtimestamp(int(request.headers['X-Ratelimit-Reset']), datetime.timezone.utc)
    return (reset - now).total_seconds()

async def maybe_coroutine(f, *args, **kwargs):
    value = f(*args, **kwargs)
    if _isawaitable(value):
        return await value
    else:
        return value

async def async_all(gen, *, check=_isawaitable):
    for elem in gen:
        if check(elem):
            elem = await elem
        if not elem:
            return False
    return True

async def sane_wait_for(futures, *, timeout, loop):
    _, pending = await asyncio.wait(futures, timeout=timeout, loop=loop)

    if len(pending) != 0:
        raise asyncio.TimeoutError()

def valid_icon_size(size):
    """Icons must be power of 2 within [16, 4096]."""
    return not size & (size - 1) and size in range(16, 4097)

class SnowflakeList(array.array):
    """Internal data storage class to efficiently store a list of snowflakes.

    This should have the following characteristics:

    - Low memory usage
    - O(n) iteration (obviously)
    - O(n log n) initial creation if data is unsorted
    - O(log n) search and indexing
    - O(n) insertion
    """

    __slots__ = ()

    def __new__(cls, data, *, is_sorted=False):
        return array.array.__new__(cls, 'Q', data if is_sorted else sorted(data))

    def add(self, element):
        i = bisect_left(self, element)
        self.insert(i, element)

    def get(self, element):
        i = bisect_left(self, element)
        return self[i] if i != len(self) and self[i] == element else None

    def has(self, element):
        i = bisect_left(self, element)
        return i != len(self) and self[i] == element

_IS_ASCII = re.compile(r'^[\x00-\x7f]+$')

def _string_width(string, *, _IS_ASCII=_IS_ASCII):
    """Returns string's width."""
    match = _IS_ASCII.match(string)
    if match:
        return match.endpos

    UNICODE_WIDE_CHAR_TYPE = 'WFA'
    width = 0
    func = unicodedata.east_asian_width
    for char in string:
        width += 2 if func(char) in UNICODE_WIDE_CHAR_TYPE else 1
    return width

def resolve_invite(invite):
    """
    Resolves an invite from a :class:`Invite`, URL or ID

    Parameters
    -----------
    invite: Union[:class:`Invite`, :class:`Object`, :class:`str`]
        The invite.

    Returns
    --------
    :class:`str`
        The invite code.
    """
    from .invite import Invite  # circular import
    if isinstance(invite, Invite) or isinstance(invite, Object):
        return invite.id
    else:
        rx = r'(?:https?\:\/\/)?discord(?:\.gg|app\.com\/invite)\/(.+)'
        m = re.match(rx, invite)
        if m:
            return m.group(1)
    return invite

_MARKDOWN_ESCAPE_SUBREGEX = '|'.join(r'\{0}(?=([\s\S]*((?<!\{0})\{0})))'.format(c)
                                     for c in ('*', '`', '_', '~', '|'))

_MARKDOWN_ESCAPE_REGEX = re.compile(r'(?P<markdown>%s)' % _MARKDOWN_ESCAPE_SUBREGEX)

def escape_markdown(text, *, as_needed=False, ignore_links=True):
    r"""A helper function that escapes Discord's markdown.

    Parameters
    -----------
    text: :class:`str`
        The text to escape markdown from.
    as_needed: :class:`bool`
        Whether to escape the markdown characters as needed. This
        means that it does not escape extraneous characters if it's
        not necessary, e.g. ``**hello**`` is escaped into ``\*\*hello**``
        instead of ``\*\*hello\*\*``. Note however that this can open
        you up to some clever syntax abuse. Defaults to ``False``.
    ignore_links: :class:`bool`
        Whether to leave links alone when escaping markdown. For example,
        if a URL in the text contains characters such as ``_`` then it will
        be left alone. This option is not supported with ``as_needed``.
        Defaults to ``True``.

    Returns
    --------
    :class:`str`
        The text with the markdown special characters escaped with a slash.
    """

    if not as_needed:
        url_regex = r'(?P<url>(?:https?|steam)://(?:-\.)?(?:[^\s/?\.#-]+\.?)+(?:/[^\s]*)?)'
        def replacement(match):
            groupdict = match.groupdict()
            is_url = groupdict.get('url')
            if is_url:
                return is_url
            return '\\' + groupdict['markdown']

        regex = r'(?P<markdown>[_\\~|\*])'
        if ignore_links:
            regex = '(?:%s|%s)' % (url_regex, regex)
        return re.sub(regex, replacement, text)
    else:
        text = re.sub(r'\\', r'\\\\', text)
        return _MARKDOWN_ESCAPE_REGEX.sub(r'\\\1', text)

def escape_mentions(text):
    """A helper function that escapes everyone, here, role, and user mentions.

    .. note::

        This does not include channel mentions.

    Parameters
    -----------
    text: :class:`str`
        The text to escape mentions from.

    Returns
    --------
    :class:`str`
        The text with the mentions removed.
    """
    return re.sub(r'@(everyone|here|[!&]?[0-9]{17,21})', '@\u200b\\1', text)
<commit_msg>Forgot to escape backticks.<commit_after># -*- coding: utf-8 -*-

"""
The MIT License (MIT)

Copyright (c) 2015-2019 Rapptz

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""

import array
import asyncio
import unicodedata
from base64 import b64encode
from bisect import bisect_left
import datetime
from email.utils import parsedate_to_datetime
import functools
from inspect import isawaitable as _isawaitable
import json
import re
import warnings

from .errors import InvalidArgument
from .object import Object

DISCORD_EPOCH = 1420070400000

class cached_property:
    def __init__(self, function):
        self.function = function
        self.__doc__ = getattr(function, '__doc__')

    def __get__(self, instance, owner):
        if instance is None:
            return self

        value = self.function(instance)
        setattr(instance, self.function.__name__, value)

        return value

class CachedSlotProperty:
    def __init__(self, name, function):
        self.name = name
        self.function = function
        self.__doc__ = getattr(function, '__doc__')

    def __get__(self, instance, owner):
        if instance is None:
            return self

        try:
            return getattr(instance, self.name)
        except AttributeError:
            value = self.function(instance)
            setattr(instance, self.name, value)
            return value

def cached_slot_property(name):
    def decorator(func):
        return CachedSlotProperty(name, func)
    return decorator

def parse_time(timestamp):
    if timestamp:
        return datetime.datetime(*map(int, re.split(r'[^\d]', timestamp.replace('+00:00', ''))))
    return None

def deprecated(instead=None):
    def actual_decorator(func):
        @functools.wraps(func)
        def decorated(*args, **kwargs):
            warnings.simplefilter('always', DeprecationWarning) # turn off filter
            if instead:
                fmt = "{0.__name__} is deprecated, use {1} instead."
            else:
                fmt = '{0.__name__} is deprecated.'

            warnings.warn(fmt.format(func, instead), stacklevel=3, category=DeprecationWarning)
            warnings.simplefilter('default', DeprecationWarning) # reset filter
            return func(*args, **kwargs)
        return decorated
    return actual_decorator

def oauth_url(client_id, permissions=None, guild=None, redirect_uri=None):
    """A helper function that returns the OAuth2 URL for inviting the bot
    into guilds.

    Parameters
    -----------
    client_id: :class:`str`
        The client ID for your bot.
    permissions: :class:`Permissions`
        The permissions you're requesting. If not given then you won't be requesting any
        permissions.
    guild: :class:`Guild`
        The guild to pre-select in the authorization screen, if available.
    redirect_uri: :class:`str`
        An optional valid redirect URI.
    """
    url = 'https://discordapp.com/oauth2/authorize?client_id={}&scope=bot'.format(client_id)
    if permissions is not None:
        url = url + '&permissions=' + str(permissions.value)
    if guild is not None:
        url = url + "&guild_id=" + str(guild.id)
    if redirect_uri is not None:
        from urllib.parse import urlencode
        url = url + "&response_type=code&" + urlencode({'redirect_uri': redirect_uri})
    return url

def snowflake_time(id):
    """Returns the creation date in UTC of a discord id."""
    return datetime.datetime.utcfromtimestamp(((id >> 22) + DISCORD_EPOCH) / 1000)

def time_snowflake(datetime_obj, high=False):
    """Returns a numeric snowflake pretending to be created at the given date.

    When using as the lower end of a range, use time_snowflake(high=False) - 1 to be inclusive, high=True to be exclusive
    When using as the higher end of a range, use time_snowflake(high=True) + 1 to be inclusive, high=False to be exclusive

    Parameters
    -----------
    datetime_obj
        A timezone-naive datetime object representing UTC time.
    high: :class:`bool`
        Whether or not to set the lower 22 bit to high or low.
    """
    unix_seconds = (datetime_obj - type(datetime_obj)(1970, 1, 1)).total_seconds()
    discord_millis = int(unix_seconds * 1000 - DISCORD_EPOCH)

    return (discord_millis << 22) + (2**22-1 if high else 0)

def find(predicate, seq):
    """A helper to return the first element found in the sequence
    that meets the predicate. For example: ::

        member = find(lambda m: m.name == 'Mighty', channel.guild.members)

    would find the first :class:`Member` whose name is 'Mighty' and return it.
    If an entry is not found, then ``None`` is returned.

    This is different from `filter`_ due to the fact it stops the moment it finds
    a valid entry.

    .. _filter: https://docs.python.org/3.6/library/functions.html#filter

    Parameters
    -----------
    predicate
        A function that returns a boolean-like result.
    seq: iterable
        The iterable to search through.
    """

    for element in seq:
        if predicate(element):
            return element
    return None

def get(iterable, **attrs):
    r"""A helper that returns the first element in the iterable that meets
    all the traits passed in ``attrs``. This is an alternative for
    :func:`discord.utils.find`.

    When multiple attributes are specified, they are checked using
    logical AND, not logical OR. Meaning they have to meet every
    attribute passed in and not one of them.

    To have a nested attribute search (i.e. search by ``x.y``) then
    pass in ``x__y`` as the keyword argument.

    If nothing is found that matches the attributes passed, then
    ``None`` is returned.

    Examples
    ---------

    Basic usage:

    .. code-block:: python3

        member = discord.utils.get(message.guild.members, name='Foo')

    Multiple attribute matching:

    .. code-block:: python3

        channel = discord.utils.get(guild.voice_channels, name='Foo', bitrate=64000)

    Nested attribute matching:

    .. code-block:: python3

        channel = discord.utils.get(client.get_all_channels(), guild__name='Cool', name='general')

    Parameters
    -----------
    iterable
        An iterable to search through.
    \*\*attrs
        Keyword arguments that denote attributes to search with.
    """

    def predicate(elem):
        for attr, val in attrs.items():
            nested = attr.split('__')
            obj = elem
            for attribute in nested:
                obj = getattr(obj, attribute)

            if obj != val:
                return False
        return True

    return find(predicate, iterable)

def _unique(iterable):
    seen = set()
    adder = seen.add
    return [x for x in iterable if not (x in seen or adder(x))]

def _get_as_snowflake(data, key):
    try:
        value = data[key]
    except KeyError:
        return None
    else:
        return value and int(value)

def _get_mime_type_for_image(data):
    if data.startswith(b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A'):
        return 'image/png'
    elif data[6:10] in (b'JFIF', b'Exif'):
        return 'image/jpeg'
    elif data.startswith((b'\x47\x49\x46\x38\x37\x61', b'\x47\x49\x46\x38\x39\x61')):
        return 'image/gif'
    elif data.startswith(b'RIFF') and data[8:12] == b'WEBP':
        return 'image/webp'
    else:
        raise InvalidArgument('Unsupported image type given')

def _bytes_to_base64_data(data):
    fmt = 'data:{mime};base64,{data}'
    mime = _get_mime_type_for_image(data)
    b64 = b64encode(data).decode('ascii')
    return fmt.format(mime=mime, data=b64)

def to_json(obj):
    return json.dumps(obj, separators=(',', ':'), ensure_ascii=True)

def _parse_ratelimit_header(request):
    now = parsedate_to_datetime(request.headers['Date'])
    reset = datetime.datetime.fromtimestamp(int(request.headers['X-Ratelimit-Reset']), datetime.timezone.utc)
    return (reset - now).total_seconds()

async def maybe_coroutine(f, *args, **kwargs):
    value = f(*args, **kwargs)
    if _isawaitable(value):
        return await value
    else:
        return value

async def async_all(gen, *, check=_isawaitable):
    for elem in gen:
        if check(elem):
            elem = await elem
        if not elem:
            return False
    return True

async def sane_wait_for(futures, *, timeout, loop):
    _, pending = await asyncio.wait(futures, timeout=timeout, loop=loop)

    if len(pending) != 0:
        raise asyncio.TimeoutError()

def valid_icon_size(size):
    """Icons must be power of 2 within [16, 4096]."""
    return not size & (size - 1) and size in range(16, 4097)

class SnowflakeList(array.array):
    """Internal data storage class to efficiently store a list of snowflakes.

    This should have the following characteristics:

    - Low memory usage
    - O(n) iteration (obviously)
    - O(n log n) initial creation if data is unsorted
    - O(log n) search and indexing
    - O(n) insertion
    """

    __slots__ = ()

    def __new__(cls, data, *, is_sorted=False):
        return array.array.__new__(cls, 'Q', data if is_sorted else sorted(data))

    def add(self, element):
        i = bisect_left(self, element)
        self.insert(i, element)

    def get(self, element):
        i = bisect_left(self, element)
        return self[i] if i != len(self) and self[i] == element else None

    def has(self, element):
        i = bisect_left(self, element)
        return i != len(self) and self[i] == element

_IS_ASCII = re.compile(r'^[\x00-\x7f]+$')

def _string_width(string, *, _IS_ASCII=_IS_ASCII):
    """Returns string's width."""
    match = _IS_ASCII.match(string)
    if match:
        return match.endpos

    UNICODE_WIDE_CHAR_TYPE = 'WFA'
    width = 0
    func = unicodedata.east_asian_width
    for char in string:
        width += 2 if func(char) in UNICODE_WIDE_CHAR_TYPE else 1
    return width

def resolve_invite(invite):
    """
    Resolves an invite from a :class:`Invite`, URL or ID

    Parameters
    -----------
    invite: Union[:class:`Invite`, :class:`Object`, :class:`str`]
        The invite.

    Returns
    --------
    :class:`str`
        The invite code.
    """
    from .invite import Invite  # circular import
    if isinstance(invite, Invite) or isinstance(invite, Object):
        return invite.id
    else:
        rx = r'(?:https?\:\/\/)?discord(?:\.gg|app\.com\/invite)\/(.+)'
        m = re.match(rx, invite)
        if m:
            return m.group(1)
    return invite

_MARKDOWN_ESCAPE_SUBREGEX = '|'.join(r'\{0}(?=([\s\S]*((?<!\{0})\{0})))'.format(c)
                                     for c in ('*', '`', '_', '~', '|'))

_MARKDOWN_ESCAPE_REGEX = re.compile(r'(?P<markdown>%s)' % _MARKDOWN_ESCAPE_SUBREGEX)

def escape_markdown(text, *, as_needed=False, ignore_links=True):
    r"""A helper function that escapes Discord's markdown.

    Parameters
    -----------
    text: :class:`str`
        The text to escape markdown from.
    as_needed: :class:`bool`
        Whether to escape the markdown characters as needed. This
        means that it does not escape extraneous characters if it's
        not necessary, e.g. ``**hello**`` is escaped into ``\*\*hello**``
        instead of ``\*\*hello\*\*``. Note however that this can open
        you up to some clever syntax abuse. Defaults to ``False``.
    ignore_links: :class:`bool`
        Whether to leave links alone when escaping markdown. For example,
        if a URL in the text contains characters such as ``_`` then it will
        be left alone. This option is not supported with ``as_needed``.
        Defaults to ``True``.

    Returns
    --------
    :class:`str`
        The text with the markdown special characters escaped with a slash.
    """

    if not as_needed:
        url_regex = r'(?P<url>(?:https?|steam)://(?:-\.)?(?:[^\s/?\.#-]+\.?)+(?:/[^\s]*)?)'
        def replacement(match):
            groupdict = match.groupdict()
            is_url = groupdict.get('url')
            if is_url:
                return is_url
            return '\\' + groupdict['markdown']

        regex = r'(?P<markdown>[_\\~|\*`])'
        if ignore_links:
            regex = '(?:%s|%s)' % (url_regex, regex)
        return re.sub(regex, replacement, text)
    else:
        text = re.sub(r'\\', r'\\\\', text)
        return _MARKDOWN_ESCAPE_REGEX.sub(r'\\\1', text)

def escape_mentions(text):
    """A helper function that escapes everyone, here, role, and user mentions.

    .. note::

        This does not include channel mentions.

    Parameters
    -----------
    text: :class:`str`
        The text to escape mentions from.

    Returns
    --------
    :class:`str`
        The text with the mentions removed.
    """
    return re.sub(r'@(everyone|here|[!&]?[0-9]{17,21})', '@\u200b\\1', text)
<|endoftext|>


<commit_before>
import warnings
import os.path as path
import sys
import os

thisdir = path.dirname(path.realpath(__file__))
sys.path.append(path.join(thisdir, '..'))

import matplotlib as mpl
if (os.environ.get('DISPLAY') is None): mpl.use('Agg')

import theano

warnings.filterwarnings(
    action='error',
    category=UserWarning
)
warnings.filterwarnings(
    action='ignore',
    message='numpy.ndarray size changed, may indicate binary incompatibility'
)

if (os.environ.get('DTU_HPC') is not None):
    print('Running on HPC')

if (theano.config.optimizer == 'fast_run'):
    print('Theano optimizer enabled')
<commit_msg>[feature] allow custom backend<commit_after>
import warnings
import os.path as path
import sys
import os

thisdir = path.dirname(path.realpath(__file__))
sys.path.append(path.join(thisdir, '..'))

import matplotlib as mpl
if (os.environ.get('DISPLAY') is None): mpl.use('Agg')
if (os.environ.get('BACKEND') is not None): mpl.use(os.environ.get('BACKEND'))

import theano

warnings.filterwarnings(
    action='error',
    category=UserWarning
)
warnings.filterwarnings(
    action='ignore',
    message='numpy.ndarray size changed, may indicate binary incompatibility'
)

if (os.environ.get('DTU_HPC') is not None):
    print('Running on HPC')

if (theano.config.optimizer == 'fast_run'):
    print('Theano optimizer enabled')
<|endoftext|>


<commit_before># spyral uses a modified version of this file from Gummworld2
# and Trolls Outta Luckland, and thanks the authors for their great,
# reusable piece of code. It is licensed separately from spyral
# under the LGPLv3 or newer.

# This file is part of Gummworld2.
#
# Gummworld2 is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Gummworld2 is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with Gummworld2.  If not, see <http://www.gnu.org/licenses/>.

# CREDITS
#
# The inspiration for this module came from Koen Witters's superb article
# "deWiTTERS Game Loop", aka "Constant Game Speed independent of Variable FPS"
# at http://www.koonsolo.com/news/dewitters-gameloop/.
#
# The clock was changed to use a fixed time-step after many discussions with
# DR0ID, and a few readings of
# http://gafferongames.com/game-physics/fix-your-timestep/.
#
# Thanks to Koen Witters, DR0ID, and Glenn Fiedler for sharing.
#
# Pythonated by Gummbum. While the builtin demo requires pygame, the module
# does not. The GameClock class is purely Python and should be compatible with
# other Python-based multi-media and game development libraries.

__version__ = '$Id: gameclock.py$'
__author__ = 'Gummbum, (c) 2011-2012'

__doc__ = """

GameClock is a fixed time-step clock that keeps time in terms of game
time. It will attempt to keep game time close to real time, so if an
interval takes one second of game time then the user experiences one
second of real time. In the worst case where the CPU cannot keep up with
the game load, game time will subjectively take longer but still remain
accurate enough to keep game elements in synchronization.

GameClock manages time in the following ways:

    1.  Register special callback functions that will be run when they
        are due.
    2.  Schedule game logic updates at a constant speed, independent of
        frame rate.
    3.  Schedule frames at capped frames-per-second, or uncapped.
    4.  Invoke a pre-emptive pause callback when paused.
    5.  Schedule miscellaneous items at user-configurable intervals.
    6.  Optionally sleep between schedules to conserve CPU cycles.
    7.  Gracefully handles corner cases.

Note the Python Library docs mention that not all computer platforms'
time functions return time fractions of a second. This module will not
work on such platforms.

USAGE

Callback:

    clock = GameClock(
        update_callback=update_world,
        frame_callback=draw_scene,
        pause_callback=pause_game)
    while 1:
        clock.tick()

Special callbacks can be directly set and cleared at any time:

    clock.update_callback = my_new_update
    clock.frame_callback = my_new_draw
    clock.pause_callback = my_new_pause

    clock.update_callback = None
    clock.frame_callback = None
    clock.pause_callback = None

Scheduling miscellanous callbacks:

    def every_second_of_every_day(dt):
        "..."
    clock.schedule_interval(every_second_of_every_day, 1.0)

The update_callback receives a single DT argument, which is the time-step
in seconds since the last update.

The frame_callback receives a single INTERPOLATION argument, which is the
fractional position in time of the frame within the current update time-
step. It is a float in the range 0.0 to 1.0.

The pause_callback receives no arguments.

User-defined interval callbacks accept at least a DT argument, which is
the scheduled item's interval, and optional user-defined arguments. See
GameClock.schedule_interval.

"""

import time

class _IntervalItem(object):
    """An interval item runs after an elapsed interval."""
    __slots__ = ['func', 'interval', 'lasttime', 'life', 'args']
    def __init__(self, func, interval, curtime, life, args):
        self.func = func
        self.interval = float(interval)
        self.lasttime = curtime
        self.life = life
        self.args = args

class GameClock(object):
    """
    GameClock is an implementation of fixed-timestep clocks used for
    running the game.

    =============== ============
    Attribute       Description
    =============== ============
    get_ticks       The time source for the game. Should support at least subsecond accuracy.
    max_ups         The maximum number of updates per second. The clock
                    will prioritize trying to keep the number of
                    updates per second at this level, at the cost of
                    frames per second
    max_fps         The maximum number of frames per second.
    use_wait        Boolean which represents whether the clock should
                    try to sleep when possible. Setting this to False
                    will give better game performance on lower end
                    hardware, but take more CPU power
    update_callback The function which should be called when for
                    updates
    frame_callback  The function which should be called for frame
                    rendering
    game_time       Virtual elapsed time in milliseconds
    paused          The game time at which the clock was paused
    =============== ============

    In addition to these attributes, the following read-only attributes
    provide some useful metrics on performance of the program.

    =============== ============
    Attribute       Description
    =============== ============
    num_updates     The number of updates run in the current one-second
                    interval
    num_frames      The number of frames run in the current one-second
                    interval
    dt_update       Duration of the previous update
    dt_frame        Duration of the previous update
    cost_of_update  How much real time the update callback takes
    cost_of_frame   How much real time the frame callback takes
    ups             Average number of updates per second over the last
                    five seconds
    fps             Average number of frames per second over the last
                    five seconds
    =============== ============
    """
    def __init__(self,
            max_ups=30,
            max_fps=0,
            use_wait=False,
            time_source=time.time,
            update_callback=None,
            frame_callback=None,
            paused_callback=None):

        # Configurables.
        self.get_ticks = time_source
        self.max_ups = max_ups
        self.max_fps = max_fps
        self.use_wait = use_wait
        self.update_callback = update_callback
        self.frame_callback = frame_callback
        self.paused_callback = paused_callback

        # Time keeping.
        TIME = self.get_ticks()
        self._real_time = TIME
        self._game_time = TIME
        self._last_update = TIME
        self._last_update_real = TIME
        self._next_update = TIME
        self._last_frame = TIME
        self._next_frame = TIME
        self._next_second = TIME
        self._update_ready = False
        self._frame_ready = False
#        self._frame_skip = 0
        self._paused = 0

        # Schedules
        self._need_sort = False
        self._schedules = []
        self._unschedules = []

        # Metrics: update and frame progress counter in the current one-second
        # interval.
        self.num_updates = 0
        self.num_frames = 0
        # Metrics: duration in seconds of the previous update and frame.
        self.dt_update = 0.0
        self.dt_frame = 0.0
        # Metrics: how much real time a callback consumes
        self.cost_of_update = 0.0
        self.cost_of_frame = 0.0
        # Metrics: average updates and frames per second over the last five
        # seconds.
        self.ups = 0.0
        self.fps = 0.0

    @property
    def max_ups(self):
        return self._max_ups
    @max_ups.setter
    def max_ups(self, val):
        self._max_ups = val
        self._update_interval = 1.0 / val

    @property
    def max_fps(self):
        return self._max_fps
    @max_fps.setter
    def max_fps(self, val):
        self._max_fps = val
        self._frame_interval = 1.0 / val if val>0 else 0

    @property
    def game_time(self):
        return self._game_time
    @property
    def paused(self):
        """The real time at which the clock was paused, or zero if the clock
        is not paused.
        """
        return self._paused

    @property
    def interpolate(self):
        interp = (self._real_time - self._last_update_real) / self._update_interval
        return interp if interp <= 1.0 else 1.0

    def tick(self):
        """
        Should be called in a loop, will run and handle timers.
        """
        # Now.
        real_time = self.get_ticks()
        self._real_time = real_time

        # Pre-emptive pause callback.
        if self._paused:
            if self.paused_callback:
                self.paused_callback()
            return

        # Check if update and frame are due.
        update_interval = self._update_interval
        game_time = self._game_time
        if real_time >= self._next_update:
            self.dt_update = real_time - self._last_update_real
            self._last_update_real = real_time
            game_time += update_interval
            self._game_time = game_time
            self._last_update = game_time
            self._next_update = real_time + update_interval
            self.num_updates += 1
            if self.update_callback:
                self._update_ready = True
#ORIG
#        if real_time + self.cost_of_frame < self._next_update and real_time >= self._next_frame:
#            self.dt_frame = real_time - self._last_frame
#            self._last_frame = real_time
#            self._next_frame = real_time + self._frame_interval
#            self.num_frames += 1
#            if self.frame_callback:
#                self._frame_ready = True
#END ORIG
#
#SACRIFICE FRAMES TO MAINTAIN UPDATES
#        if real_time >= self._next_frame:
#            do_frame = False
#            if real_time + self.cost_of_frame <= self._next_update:
#                do_frame = True
#            elif self._frame_skip > 0:
#                do_frame = True
#            else:
#                self._next_frame = self._next_update
#                self._frame_skip += 1
#            if do_frame:
#                self._frame_skip = 0
#                self.dt_frame = real_time - self._last_frame
#                self._last_frame = real_time
#                self._next_frame = real_time + self._frame_interval
#                self.num_frames += 1
#                if self.frame_callback:
#                    self._frame_ready = True
#END SACRIFICE FRAMES TO MAINTAIN UPDATES
#
        if real_time - self._last_frame >= self._update_interval or (
                real_time + self.cost_of_frame < self._next_update and
                real_time >= self._next_frame):
            self.dt_frame = real_time - self._last_frame
            self._last_frame = real_time
            self._next_frame = real_time + self._frame_interval
            self.num_frames += 1
            if self.frame_callback:
                self._frame_ready = True

        # Check if a schedule is due, and when.
        sched_ready = False
        sched_due = 0
        if self._schedules:
            sched = self._schedules[0]
            sched_due = sched.lasttime + sched.interval
            if real_time >= sched_due:
                sched_ready = True

        # Run schedules if any are due.
        if self._update_ready or sched_ready:
            self._run_schedules()

        # Run the frame callback (moved inline to reduce function calls).
        if self.frame_callback and self._frame_ready:
            get_ticks = self.get_ticks
            t = get_ticks()
            self.frame_callback(self.interpolate)
            self.cost_of_frame = get_ticks() - t
            self._frame_ready = False

        # Flip metrics counters every second.
        if real_time >= self._next_second:
            self._flip(real_time)

        # Sleep to save CPU.
        if self.use_wait:
            upcoming_events = [
                self._next_frame,
                self._next_update,
                self._next_second,
            ]
            if sched_due != 0:
                upcoming_events.append(sched_due)
            next = reduce(min, upcoming_events)
            t = self.get_ticks()
            time_to_sleep = next - t
            if time_to_sleep >= 0.002:
                time.sleep(time_to_sleep)

    def pause(self):
        """Pause the clock so that time does not elapse.

        While the clock is paused, no schedules will fire and tick() returns
        immediately without progressing internal counters. Game loops that
        completely rely on the clock will need to take over timekeeping and
        handling events; otherwise, the game will appear to deadlock. There are
        many ways to solve this scenario. For instance, another clock can be
        created and used temporarily, and the original swapped back in and
        resumed when needed.
        """
        self._paused = self.get_ticks()

    def resume(self):
        """Resume the clock from the point that it was paused."""
        real_time = self.get_ticks()
        paused = self._paused
        for item in self._schedules:
            dt = paused - item.lasttime
            item.lasttime = real_time - dt
        self._last_update_real = real_time - (paused - self._last_update_real)
        self._paused = 0
        self._real_time = real_time

    def schedule_interval(self, func, interval, life=0, args=[]):
        """

        Schedule an item to be called back each time an interval elapses.

        While the clock is paused time does not pass.

        | *func*: The callback function.
        | *interval*: The time in seconds (float) between calls.
        | *life*: The number of times the callback will fire, after which the
          schedule will be removed. If the value 0 is specified, the event
          will persist until manually unscheduled.
        | *args*: A list that will be passed to the callback as an unpacked
          sequence, like so: item.func(\*[item.interval]+item.args).

        """
        self.unschedule(func)
        item = _IntervalItem(
            func, interval, self.get_ticks(), life, [interval]+list(args))
        self._schedules.append(item)
        self._need_sort = True

    def unschedule(self, func):
        """Unschedule a managed function."""
        sched = self._schedules
        for item in list(sched):
            if item.func == func:
                sched.remove(item)

    @staticmethod
    def _interval_item_sort_key(item):
        return item.lasttime + item.interval

    def _run_schedules(self):
        get_ticks = self.get_ticks

        # Run the update callback.
        if self.update_callback and self._update_ready:
            t = get_ticks()
            self.update_callback(self.dt_update)
            self.cost_of_update = get_ticks() - t
            self._update_ready = False

        # Run the interval callbacks.
        if self._need_sort:
            self._schedules.sort(key=self._interval_item_sort_key)
            self._need_sort = False
        real_time = self._real_time
        for sched in self._schedules:
            interval = sched.interval
            due = sched.lasttime + interval
            if real_time >= due:
                sched.func(*sched.args)
                sched.lasttime += interval
                need_sort = True
                if sched.life > 0:
                    if sched.life == 1:
                        self._unschedules.append(sched.func)
                        need_sort = False
                    else:
                        sched.life -= 1
                if need_sort:
                    self._need_sort = True
            else:
                break
        if self._unschedules:
            for func in self._unschedules:
                self.unschedule(func)
            del self._unschedules[:]

    def _flip(self, real_time):
        self.ups = self.num_updates
        self.fps = self.num_frames

        self.num_updates = 0
        self.num_frames = 0

        self._last_second = real_time
        self._next_second += 1.0<commit_msg>Hopefully the last of the clock documentation updates.<commit_after># spyral uses a modified version of this file from Gummworld2
# and Trolls Outta Luckland, and thanks the authors for their great,
# reusable piece of code. It is licensed separately from spyral
# under the LGPLv3 or newer.

# This file is part of Gummworld2.
#
# Gummworld2 is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Gummworld2 is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with Gummworld2.  If not, see <http://www.gnu.org/licenses/>.

# CREDITS
#
# The inspiration for this module came from Koen Witters's superb article
# "deWiTTERS Game Loop", aka "Constant Game Speed independent of Variable FPS"
# at http://www.koonsolo.com/news/dewitters-gameloop/.
#
# The clock was changed to use a fixed time-step after many discussions with
# DR0ID, and a few readings of
# http://gafferongames.com/game-physics/fix-your-timestep/.
#
# Thanks to Koen Witters, DR0ID, and Glenn Fiedler for sharing.
#
# Pythonated by Gummbum. While the builtin demo requires pygame, the module
# does not. The GameClock class is purely Python and should be compatible with
# other Python-based multi-media and game development libraries.

__version__ = '$Id: gameclock.py$'
__author__ = 'Gummbum, (c) 2011-2012'

__doc__ = """

GameClock is a fixed time-step clock that keeps time in terms of game
time. It will attempt to keep game time close to real time, so if an
interval takes one second of game time then the user experiences one
second of real time. In the worst case where the CPU cannot keep up with
the game load, game time will subjectively take longer but still remain
accurate enough to keep game elements in synchronization.

GameClock manages time in the following ways:

    1.  Register special callback functions that will be run when they
        are due.
    2.  Schedule game logic updates at a constant speed, independent of
        frame rate.
    3.  Schedule frames at capped frames-per-second, or uncapped.
    4.  Invoke a pre-emptive pause callback when paused.
    5.  Schedule miscellaneous items at user-configurable intervals.
    6.  Optionally sleep between schedules to conserve CPU cycles.
    7.  Gracefully handles corner cases.

Note the Python Library docs mention that not all computer platforms'
time functions return time fractions of a second. This module will not
work on such platforms.

USAGE

Callback:

    clock = GameClock(
        update_callback=update_world,
        frame_callback=draw_scene,
        pause_callback=pause_game)
    while 1:
        clock.tick()

Special callbacks can be directly set and cleared at any time:

    clock.update_callback = my_new_update
    clock.frame_callback = my_new_draw
    clock.pause_callback = my_new_pause

    clock.update_callback = None
    clock.frame_callback = None
    clock.pause_callback = None

Scheduling miscellanous callbacks:

    def every_second_of_every_day(dt):
        "..."
    clock.schedule_interval(every_second_of_every_day, 1.0)

The update_callback receives a single DT argument, which is the time-step
in seconds since the last update.

The frame_callback receives a single INTERPOLATION argument, which is the
fractional position in time of the frame within the current update time-
step. It is a float in the range 0.0 to 1.0.

The pause_callback receives no arguments.

User-defined interval callbacks accept at least a DT argument, which is
the scheduled item's interval, and optional user-defined arguments. See
GameClock.schedule_interval.

"""

import time

class _IntervalItem(object):
    """An interval item runs after an elapsed interval."""
    __slots__ = ['func', 'interval', 'lasttime', 'life', 'args']
    def __init__(self, func, interval, curtime, life, args):
        self.func = func
        self.interval = float(interval)
        self.lasttime = curtime
        self.life = life
        self.args = args

class GameClock(object):
    """
    GameClock is an implementation of fixed-timestep clocks used for
    running the game.

    =============== ============
    Attribute       Description
    =============== ============
    get_ticks       The time source for the game. Should support at least subsecond accuracy.
    max_ups         The maximum number of updates per second. The clock
                    will prioritize trying to keep the number of
                    updates per second at this level, at the cost of
                    frames per second
    max_fps         The maximum number of frames per second.
    use_wait        Boolean which represents whether the clock should
                    try to sleep when possible. Setting this to False
                    will give better game performance on lower end
                    hardware, but take more CPU power
    update_callback The function which should be called when for
                    updates
    frame_callback  The function which should be called for frame
                    rendering
    game_time       Virtual elapsed time in milliseconds
    paused          The game time at which the clock was paused
    =============== ============

    In addition to these attributes, the following read-only attributes
    provide some useful metrics on performance of the program.

    =============== ============
    Attribute       Description
    =============== ============
    num_updates     The number of updates run in the current one-second
                    interval
    num_frames      The number of frames run in the current one-second
                    interval
    dt_update       Duration of the previous update
    dt_frame        Duration of the previous update
    cost_of_update  How much real time the update callback takes
    cost_of_frame   How much real time the frame callback takes
    ups             Average number of updates per second over the last
                    five seconds
    fps             Average number of frames per second over the last
                    five seconds
    =============== ============
    """
    def __init__(self,
            max_ups=30,
            max_fps=0,
            use_wait=False,
            time_source=time.time,
            update_callback=None,
            frame_callback=None,
            paused_callback=None):

        # Configurables.
        self.get_ticks = time_source
        self.max_ups = max_ups
        self.max_fps = max_fps
        self.use_wait = use_wait
        self.update_callback = update_callback
        self.frame_callback = frame_callback
        self.paused_callback = paused_callback

        # Time keeping.
        TIME = self.get_ticks()
        self._real_time = TIME
        self._game_time = TIME
        self._last_update = TIME
        self._last_update_real = TIME
        self._next_update = TIME
        self._last_frame = TIME
        self._next_frame = TIME
        self._next_second = TIME
        self._update_ready = False
        self._frame_ready = False
#        self._frame_skip = 0
        self._paused = 0

        # Schedules
        self._need_sort = False
        self._schedules = []
        self._unschedules = []

        # Metrics: update and frame progress counter in the current one-second
        # interval.
        self.num_updates = 0
        self.num_frames = 0
        # Metrics: duration in seconds of the previous update and frame.
        self.dt_update = 0.0
        self.dt_frame = 0.0
        # Metrics: how much real time a callback consumes
        self.cost_of_update = 0.0
        self.cost_of_frame = 0.0
        # Metrics: average updates and frames per second over the last five
        # seconds.
        self.ups = 0.0
        self.fps = 0.0

    @property
    def max_ups(self):
        return self._max_ups
    @max_ups.setter
    def max_ups(self, val):
        self._max_ups = val
        self._update_interval = 1.0 / val

    @property
    def max_fps(self):
        return self._max_fps
    @max_fps.setter
    def max_fps(self, val):
        self._max_fps = val
        self._frame_interval = 1.0 / val if val>0 else 0

    @property
    def game_time(self):
        return self._game_time
    @property
    def paused(self):
        return self._paused

    @property
    def interpolate(self):
        interp = (self._real_time - self._last_update_real) / self._update_interval
        return interp if interp <= 1.0 else 1.0

    def tick(self):
        """
        Should be called in a loop, will run and handle timers.
        """
        # Now.
        real_time = self.get_ticks()
        self._real_time = real_time

        # Pre-emptive pause callback.
        if self._paused:
            if self.paused_callback:
                self.paused_callback()
            return

        # Check if update and frame are due.
        update_interval = self._update_interval
        game_time = self._game_time
        if real_time >= self._next_update:
            self.dt_update = real_time - self._last_update_real
            self._last_update_real = real_time
            game_time += update_interval
            self._game_time = game_time
            self._last_update = game_time
            self._next_update = real_time + update_interval
            self.num_updates += 1
            if self.update_callback:
                self._update_ready = True
#ORIG
#        if real_time + self.cost_of_frame < self._next_update and real_time >= self._next_frame:
#            self.dt_frame = real_time - self._last_frame
#            self._last_frame = real_time
#            self._next_frame = real_time + self._frame_interval
#            self.num_frames += 1
#            if self.frame_callback:
#                self._frame_ready = True
#END ORIG
#
#SACRIFICE FRAMES TO MAINTAIN UPDATES
#        if real_time >= self._next_frame:
#            do_frame = False
#            if real_time + self.cost_of_frame <= self._next_update:
#                do_frame = True
#            elif self._frame_skip > 0:
#                do_frame = True
#            else:
#                self._next_frame = self._next_update
#                self._frame_skip += 1
#            if do_frame:
#                self._frame_skip = 0
#                self.dt_frame = real_time - self._last_frame
#                self._last_frame = real_time
#                self._next_frame = real_time + self._frame_interval
#                self.num_frames += 1
#                if self.frame_callback:
#                    self._frame_ready = True
#END SACRIFICE FRAMES TO MAINTAIN UPDATES
#
        if real_time - self._last_frame >= self._update_interval or (
                real_time + self.cost_of_frame < self._next_update and
                real_time >= self._next_frame):
            self.dt_frame = real_time - self._last_frame
            self._last_frame = real_time
            self._next_frame = real_time + self._frame_interval
            self.num_frames += 1
            if self.frame_callback:
                self._frame_ready = True

        # Check if a schedule is due, and when.
        sched_ready = False
        sched_due = 0
        if self._schedules:
            sched = self._schedules[0]
            sched_due = sched.lasttime + sched.interval
            if real_time >= sched_due:
                sched_ready = True

        # Run schedules if any are due.
        if self._update_ready or sched_ready:
            self._run_schedules()

        # Run the frame callback (moved inline to reduce function calls).
        if self.frame_callback and self._frame_ready:
            get_ticks = self.get_ticks
            t = get_ticks()
            self.frame_callback(self.interpolate)
            self.cost_of_frame = get_ticks() - t
            self._frame_ready = False

        # Flip metrics counters every second.
        if real_time >= self._next_second:
            self._flip(real_time)

        # Sleep to save CPU.
        if self.use_wait:
            upcoming_events = [
                self._next_frame,
                self._next_update,
                self._next_second,
            ]
            if sched_due != 0:
                upcoming_events.append(sched_due)
            next = reduce(min, upcoming_events)
            t = self.get_ticks()
            time_to_sleep = next - t
            if time_to_sleep >= 0.002:
                time.sleep(time_to_sleep)

    def pause(self):
        """Pause the clock so that time does not elapse.

        While the clock is paused, no schedules will fire and tick() returns
        immediately without progressing internal counters. Game loops that
        completely rely on the clock will need to take over timekeeping and
        handling events; otherwise, the game will appear to deadlock. There are
        many ways to solve this scenario. For instance, another clock can be
        created and used temporarily, and the original swapped back in and
        resumed when needed.
        """
        self._paused = self.get_ticks()

    def resume(self):
        """Resume the clock from the point that it was paused."""
        real_time = self.get_ticks()
        paused = self._paused
        for item in self._schedules:
            dt = paused - item.lasttime
            item.lasttime = real_time - dt
        self._last_update_real = real_time - (paused - self._last_update_real)
        self._paused = 0
        self._real_time = real_time

    def schedule_interval(self, func, interval, life=0, args=[]):
        """

        Schedule an item to be called back each time an interval elapses.

        While the clock is paused time does not pass.

        | *func*: The callback function.
        | *interval*: The time in seconds (float) between calls.
        | *life*: The number of times the callback will fire, after which the
          schedule will be removed. If the value 0 is specified, the event
          will persist until manually unscheduled.
        | *args*: A list that will be passed to the callback as an unpacked
          sequence, like so: item.func(\*[item.interval]+item.args).

        """
        self.unschedule(func)
        item = _IntervalItem(
            func, interval, self.get_ticks(), life, [interval]+list(args))
        self._schedules.append(item)
        self._need_sort = True

    def unschedule(self, func):
        """Unschedule a managed function."""
        sched = self._schedules
        for item in list(sched):
            if item.func == func:
                sched.remove(item)

    @staticmethod
    def _interval_item_sort_key(item):
        return item.lasttime + item.interval

    def _run_schedules(self):
        get_ticks = self.get_ticks

        # Run the update callback.
        if self.update_callback and self._update_ready:
            t = get_ticks()
            self.update_callback(self.dt_update)
            self.cost_of_update = get_ticks() - t
            self._update_ready = False

        # Run the interval callbacks.
        if self._need_sort:
            self._schedules.sort(key=self._interval_item_sort_key)
            self._need_sort = False
        real_time = self._real_time
        for sched in self._schedules:
            interval = sched.interval
            due = sched.lasttime + interval
            if real_time >= due:
                sched.func(*sched.args)
                sched.lasttime += interval
                need_sort = True
                if sched.life > 0:
                    if sched.life == 1:
                        self._unschedules.append(sched.func)
                        need_sort = False
                    else:
                        sched.life -= 1
                if need_sort:
                    self._need_sort = True
            else:
                break
        if self._unschedules:
            for func in self._unschedules:
                self.unschedule(func)
            del self._unschedules[:]

    def _flip(self, real_time):
        self.ups = self.num_updates
        self.fps = self.num_frames

        self.num_updates = 0
        self.num_frames = 0

        self._last_second = real_time
        self._next_second += 1.0<|endoftext|>


<commit_before>from django.test import TestCase
from gestionpedidos.models import Cliente, Pedido
from django.test.client import RequestFactory

class TestsGestionPedidos(TestCase):
	def test_nombre_cliente(self):
		cliente = Cliente.objects.get(slug="Carlos")
		self.assertEqual(cliente.direccion, 'Spain, Granada, Calle Gran Vía de Colón')
		print ("direccion correcta")
<commit_msg>actualizo tests<commit_after>from django.test import TestCase
from gestionpedidos.models import Cliente, Pedido
from gestionpedidos.views import *
from django.test.client import RequestFactory

class TestsGestionPedidos(TestCase):
	def test_nombre_cliente(self):
		cliente = Cliente.objects.get(slug="Carlos")
		self.assertEqual(cliente.direccion, 'Spain, Granada, Calle Gran Vía de Colón')
		print ("direccion correcta")
<|endoftext|>