<commit_before>from totalimpact.cache import Cache
from totalimpact.dao import Dao
from totalimpact import providers

import requests, os, time, threading, sys, traceback, importlib, urllib

from totalimpact.tilogging import logging
logger = logging.getLogger(__name__)

class ProviderFactory(object):

    @classmethod
    def get_provider(cls, provider_name):
        provider_module = importlib.import_module('totalimpact.providers.'+provider_name)
        provider = getattr(provider_module, provider_name.title())
        instance = provider()
        return instance

    @classmethod
    def get_providers(cls, config_providers):
        """ config is the application configuration """
        providers = []
        for provider_name, v in config_providers.iteritems():
            try:
                prov = ProviderFactory.get_provider(provider_name)
                prov.provider_name = provider_name
                providers.append(prov)
            except ProviderConfigurationError:
                logger.error("Unable to configure provider ... skipping " + str(v))
        return providers

class Provider(object):

    def __init__(self, max_cache_duration=86400, max_retries=3):
        self.max_cache_duration = max_cache_duration
        self.max_retries = max_retries
        self.provider_name = self.__class__.__name__.lower()

    def __repr__(self):
        return "Provider(%s)" % self.provider_name

    # API Methods
    # These should be filled in by each Provider implementing this signature

    # default method; providers can override
    def _get_error(self, response):
        if response.status_code >= 500:
            error = ProviderServerError
        else:
            error = ProviderClientError
        return(error)

    def _get_templated_url(self, template, id, method=None):
        url = template % id
        return(url)

    def relevant_aliases(self, aliases):
        filtered = [alias for alias in aliases
                        if self.is_relevant_alias(alias)]
        return filtered

    def get_best_id(self, aliases):
        filtered = self.relevant_aliases(aliases)
        if filtered:
            alias = filtered[0]
            (namespace, nid) = alias
        else:
            nid = None
        return(nid)

    # default method; providers can override
    def provenance_url(self, metric_name, aliases):
        # Returns the same provenance url for all metrics
        id = self.get_best_id(aliases)

        if id:
            provenance_url = self._get_templated_url(self.provenance_url_template, id, "provenance")
        else:
            provenance_url = None

        return provenance_url

    # default method; providers can override
    def member_items(self,
            query_string,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_members:
            raise NotImplementedError()

        logger.debug("Getting members for %s, %s" % (self.provider_name, query_string))

        if not provider_url_template:
            provider_url_template = self.member_items_url_template

        enc = urllib.quote(query_string)
        url = self._get_templated_url(provider_url_template, enc, "members")
        logger.debug("attempting to retrieve member items from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            error = self._get_error(response)
            raise error(response)

        # extract the member ids
        members = self._extract_members(response.text, query_string)

        return(members)

    # default method; providers can override
    def biblio(self,
            aliases,
            provider_url_template=None):

        if not self.provides_biblio:
            raise NotImplementedError()

        id = self.get_best_id(aliases)

        # Only lookup biblio for items with appropriate ids
        if not id:
            logger.info("Not checking biblio because no relevant id for %s", self.provider_name)
            return None

        if not provider_url_template:
            provider_url_template = self.biblio_url_template

        return self.get_biblio_for_id(id, provider_url_template)

    # default method; providers can override
    def get_biblio_for_id(self,
            id,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_biblio:
            raise NotImplementedError()

        logger.debug("Getting biblio for %s, %s" % (self.provider_name, id))

        if not provider_url_template:
            provider_url_template = self.biblio_url_template
        url = self._get_templated_url(provider_url_template, id, "biblio")
        logger.debug("attempting to retrieve biblio from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            error = self._get_error(response)
            raise error(response)

        # extract the aliases
        biblio_dict = self._extract_biblio(response.text, id)

        return biblio_dict

    # default method; providers can override
    def aliases(self,
            aliases,
            provider_url_template=None):

        if not self.provides_aliases:
            raise NotImplementedError()

        # Get a list of relevant aliases
        relevant_aliases = self.relevant_aliases(aliases)

        if not relevant_aliases:
            logger.info("Not checking aliases because no relevant id for %s", self.provider_name)
            return None

        new_aliases = aliases
        for alias in relevant_aliases:
            (namespace, nid) = alias
            logger.debug("processing alias %s" % str(alias))
            new_aliases += self._get_aliases_for_id(nid, provider_url_template)

        new_aliases_unique = list(set(new_aliases))
        return new_aliases_unique

    # default method; providers can override
    def _get_aliases_for_id(self,
            id,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_aliases:
            raise NotImplementedError()

        logger.debug("Getting aliases for %s, %s" % (self.provider_name, id))

        if not provider_url_template:
            provider_url_template = self.aliases_url_template
        url = self._get_templated_url(provider_url_template, id, "aliases")
        logger.debug("attempting to retrieve aliases from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            error = self._get_error(response)
            raise error(response)

        new_aliases = self._extract_aliases(response.text, id)

        return new_aliases

    # default method; providers can override
    def metrics(self,
            aliases,
            provider_url_template=None):

        if not self.provides_metrics:
            raise NotImplementedError()

        id = self.get_best_id(aliases)

        # Only lookup metrics for items with appropriate ids
        if not id:
            logger.info("Not checking metrics because no relevant id for %s", self.provider_name)
            return None

        if not provider_url_template:
            provider_url_template = self.metrics_url_template

        return self.get_metrics_for_id(id, provider_url_template)

    # default method; providers can override
    def get_metrics_for_id(self,
            id,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_metrics:
            raise NotImplementedError()

        logger.debug("Getting metrics for %s, %s" % (self.provider_name, id))

        if not provider_url_template:
            provider_url_template = self.metrics_url_template
        url = self._get_templated_url(provider_url_template, id, "metrics")
        logger.debug("attempting to retrieve metrics from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            error = self._get_error(response)
            raise error(response)

        # extract the metrics
        metrics_dict = self._extract_metrics(response.text, id)
        return metrics_dict

    # Core methods
    # These should be consistent for all providers

    def get_sleep_time(self, error_type, retry_count):
        """ How long we should sleep for the given error type and count

            error_type - timeout, http_error, ... should match config
            retry_count - this will be our n-th retry (first retry is 1)
        """

        max_retries = self.get_max_retries(error_type)

        # Check we haven't reached max retries
        if retry_count > max_retries:
            raise ValueError("Exceeded max retries for %s" % error_type)

        # exponential delay
        initial_delay = 1  # number of seconds for initial delay
        delay_time = initial_delay * 2**(retry_count-1)

        return delay_time

    def get_max_retries(self, error_type):
        # give up right away if a content_malformed error
        if error_type in ["content_malformed"]:
            max_retries = 0
        else:
            # For other error types, try as up to max_retries times.
            # Other errors include timeout, http_error, client_server_error,
            #    rate_limit_reached, validation_failed
            max_retries = self.max_retries
        return max_retries

    def sleep_time(self, dead_time=0):
        return 0

    @staticmethod
    def filter_aliases(aliases, supported_namespaces):
        aliases = ((ns,v) for (ns,v) in aliases if k == 'github')

    def http_get(self, url, headers=None, timeout=None, cache_enabled=True):
        """ Returns a requests.models.Response object or raises exception
            on failure. Will cache requests to the same URL. """

        from totalimpact.api import app

        # first thing is to try to retrieve from cache
        # use the cache if the config parameter is set and the arg allows it
        use_cache = app.config["CACHE_ENABLED"] and cache_enabled
        cache_data = None
        if use_cache:
            c = Cache(self.max_cache_duration)
            cache_data = c.get_cache_entry(url)
        if cache_data:
            # Return a stripped down equivalent of requests.models.Response
            # We don't store headers or other information here. If we need
            # that later, we can add it
            class CachedResponse:
                pass
            r = CachedResponse()
            r.status_code = cache_data['status_code']
            r.text = cache_data['text']
            return r

        # ensure that a user-agent string is set
        if headers is None:
            headers = {}

        # make the request
        try:
            from totalimpact.api import app
            proxies = None
            if app.config["PROXY"]:
                proxies = {'http' : app.config["PROXY"], 'https' : app.config["PROXY"]}
            r = requests.get(url, headers=headers, timeout=timeout, proxies=proxies)
        except requests.exceptions.Timeout as e:
            logger.debug("Attempt to connect to provider timed out during GET on " + url)
            raise ProviderTimeout("Attempt to connect to provider timed out during GET on " + url, e)
        except requests.exceptions.RequestException as e:
            logger.info("RequestException during GET on: " + url)
            raise ProviderHttpError("RequestException during GET on: " + url, e)

        # cache the response and return
        if use_cache:
            c.set_cache_entry(url, {'text' : r.text, 'status_code' : r.status_code})
        return r

class ProviderError(Exception):
    def __init__(self, message="", inner=None):
        self._message = message  # naming it self.message raises DepreciationWarning
        self.inner = inner
        # NOTE: experimental
        self.stack = traceback.format_stack()[:-1]

    # DeprecationWarning: BaseException.message has been deprecated
    #   as of Python 2.6 so implement property here
    @property
    def message(self):
        return (self._message)

    def log(self):
        msg = " " + self.message + " " if self.message is not None and self.message != "" else ""
        wraps = "(inner exception: " + repr(self.inner) + ")"
        return self.__class__.__name__ + ":" + msg + wraps

    def __str__(self):
        return repr(self._message)

class ProviderConfigurationError(ProviderError):
    pass

class ProviderTimeout(ProviderError):
    pass

class ProviderHttpError(ProviderError):
    pass

class ProviderClientError(ProviderError):
    def __init__(self, response, message="", inner=None):
        super(ProviderClientError, self).__init__(message, inner)
        self.response = response

class ProviderServerError(ProviderError):
    def __init__(self, response, message="", inner=None):
        super(ProviderServerError, self).__init__(message, inner)
        self.response = response

class ProviderContentMalformedError(ProviderError):
    pass

class ProviderValidationFailedError(ProviderError):
    pass

class ProviderRateLimitError(ProviderError):
    pass

<commit_msg>handle provider 404s by returning empty responses because id not known by that provider<commit_after>from totalimpact.cache import Cache
from totalimpact.dao import Dao
from totalimpact import providers

import requests, os, time, threading, sys, traceback, importlib, urllib

from totalimpact.tilogging import logging
logger = logging.getLogger(__name__)

class ProviderFactory(object):

    @classmethod
    def get_provider(cls, provider_name):
        provider_module = importlib.import_module('totalimpact.providers.'+provider_name)
        provider = getattr(provider_module, provider_name.title())
        instance = provider()
        return instance

    @classmethod
    def get_providers(cls, config_providers):
        """ config is the application configuration """
        providers = []
        for provider_name, v in config_providers.iteritems():
            try:
                prov = ProviderFactory.get_provider(provider_name)
                prov.provider_name = provider_name
                providers.append(prov)
            except ProviderConfigurationError:
                logger.error("Unable to configure provider ... skipping " + str(v))
        return providers

class Provider(object):

    def __init__(self, max_cache_duration=86400, max_retries=3):
        self.max_cache_duration = max_cache_duration
        self.max_retries = max_retries
        self.provider_name = self.__class__.__name__.lower()

    def __repr__(self):
        return "Provider(%s)" % self.provider_name

    # API Methods
    # These should be filled in by each Provider implementing this signature

    # default method; providers can override
    def _get_error(self, response):
        if response.status_code >= 500:
            error = ProviderServerError(response)
        else:
            error = ProviderClientError(response)
        return(error)

    def _get_templated_url(self, template, id, method=None):
        url = template % id
        return(url)

    def relevant_aliases(self, aliases):
        filtered = [alias for alias in aliases
                        if self.is_relevant_alias(alias)]
        return filtered

    def get_best_id(self, aliases):
        filtered = self.relevant_aliases(aliases)
        if filtered:
            alias = filtered[0]
            (namespace, nid) = alias
        else:
            nid = None
        return(nid)

    # default method; providers can override
    def provenance_url(self, metric_name, aliases):
        # Returns the same provenance url for all metrics
        id = self.get_best_id(aliases)

        if id:
            provenance_url = self._get_templated_url(self.provenance_url_template, id, "provenance")
        else:
            provenance_url = None

        return provenance_url

    # default method; providers can override
    def member_items(self,
            query_string,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_members:
            raise NotImplementedError()

        logger.debug("Getting members for %s, %s" % (self.provider_name, query_string))

        if not provider_url_template:
            provider_url_template = self.member_items_url_template

        enc = urllib.quote(query_string)
        url = self._get_templated_url(provider_url_template, enc, "members")
        logger.debug("attempting to retrieve member items from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            if response.status_code == 404:
                return {}
            else:
                raise(self._get_error(response))

        # extract the member ids
        members = self._extract_members(response.text, query_string)

        return(members)

    # default method; providers can override
    def biblio(self,
            aliases,
            provider_url_template=None):

        if not self.provides_biblio:
            raise NotImplementedError()

        id = self.get_best_id(aliases)

        # Only lookup biblio for items with appropriate ids
        if not id:
            logger.info("Not checking biblio because no relevant id for %s", self.provider_name)
            return None

        if not provider_url_template:
            provider_url_template = self.biblio_url_template

        return self.get_biblio_for_id(id, provider_url_template)

    # default method; providers can override
    def get_biblio_for_id(self,
            id,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_biblio:
            raise NotImplementedError()

        logger.debug("Getting biblio for %s, %s" % (self.provider_name, id))

        if not provider_url_template:
            provider_url_template = self.biblio_url_template
        url = self._get_templated_url(provider_url_template, id, "biblio")
        logger.debug("attempting to retrieve biblio from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            if response.status_code == 404:
                return {}
            else:
                raise(self._get_error(response))

        # extract the aliases
        biblio_dict = self._extract_biblio(response.text, id)

        return biblio_dict

    # default method; providers can override
    def aliases(self,
            aliases,
            provider_url_template=None):

        if not self.provides_aliases:
            raise NotImplementedError()

        # Get a list of relevant aliases
        relevant_aliases = self.relevant_aliases(aliases)

        if not relevant_aliases:
            logger.info("Not checking aliases because no relevant id for %s", self.provider_name)
            return None

        new_aliases = aliases
        for alias in relevant_aliases:
            (namespace, nid) = alias
            logger.debug("processing alias %s" % str(alias))
            new_aliases += self._get_aliases_for_id(nid, provider_url_template)

        new_aliases_unique = list(set(new_aliases))
        return new_aliases_unique

    # default method; providers can override
    def _get_aliases_for_id(self,
            id,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_aliases:
            raise NotImplementedError()

        logger.debug("Getting aliases for %s, %s" % (self.provider_name, id))

        if not provider_url_template:
            provider_url_template = self.aliases_url_template
        url = self._get_templated_url(provider_url_template, id, "aliases")
        logger.debug("attempting to retrieve aliases from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            if response.status_code == 404:
                return []
            else:
                raise(self._get_error(response))

        new_aliases = self._extract_aliases(response.text, id)

        return new_aliases

    # default method; providers can override
    def metrics(self,
            aliases,
            provider_url_template=None):

        if not self.provides_metrics:
            raise NotImplementedError()

        id = self.get_best_id(aliases)

        # Only lookup metrics for items with appropriate ids
        if not id:
            logger.info("Not checking metrics because no relevant id for %s", self.provider_name)
            return None

        if not provider_url_template:
            provider_url_template = self.metrics_url_template

        return self.get_metrics_for_id(id, provider_url_template)

    # default method; providers can override
    def get_metrics_for_id(self,
            id,
            provider_url_template=None,
            cache_enabled=True):

        if not self.provides_metrics:
            raise NotImplementedError()

        logger.debug("Getting metrics for %s, %s" % (self.provider_name, id))

        if not provider_url_template:
            provider_url_template = self.metrics_url_template
        url = self._get_templated_url(provider_url_template, id, "metrics")
        logger.debug("attempting to retrieve metrics from " + url)

        # try to get a response from the data provider
        response = self.http_get(url, cache_enabled=cache_enabled)

        if response.status_code != 200:
            if response.status_code == 404:
                return {}
            else:
                raise(self._get_error(response))

        # extract the metrics
        metrics_dict = self._extract_metrics(response.text, id)
        return metrics_dict

    # Core methods
    # These should be consistent for all providers

    def get_sleep_time(self, error_type, retry_count):
        """ How long we should sleep for the given error type and count

            error_type - timeout, http_error, ... should match config
            retry_count - this will be our n-th retry (first retry is 1)
        """

        max_retries = self.get_max_retries(error_type)

        # Check we haven't reached max retries
        if retry_count > max_retries:
            raise ValueError("Exceeded max retries for %s" % error_type)

        # exponential delay
        initial_delay = 1  # number of seconds for initial delay
        delay_time = initial_delay * 2**(retry_count-1)

        return delay_time

    def get_max_retries(self, error_type):
        # give up right away if a content_malformed error
        if error_type in ["content_malformed"]:
            max_retries = 0
        else:
            # For other error types, try as up to max_retries times.
            # Other errors include timeout, http_error, client_server_error,
            #    rate_limit_reached, validation_failed
            max_retries = self.max_retries
        return max_retries

    def sleep_time(self, dead_time=0):
        return 0

    @staticmethod
    def filter_aliases(aliases, supported_namespaces):
        aliases = ((ns,v) for (ns,v) in aliases if k == 'github')

    def http_get(self, url, headers=None, timeout=None, cache_enabled=True):
        """ Returns a requests.models.Response object or raises exception
            on failure. Will cache requests to the same URL. """

        from totalimpact.api import app

        # first thing is to try to retrieve from cache
        # use the cache if the config parameter is set and the arg allows it
        use_cache = app.config["CACHE_ENABLED"] and cache_enabled
        cache_data = None
        if use_cache:
            c = Cache(self.max_cache_duration)
            cache_data = c.get_cache_entry(url)
        if cache_data:
            # Return a stripped down equivalent of requests.models.Response
            # We don't store headers or other information here. If we need
            # that later, we can add it
            class CachedResponse:
                pass
            r = CachedResponse()
            r.status_code = cache_data['status_code']
            r.text = cache_data['text']
            return r

        # ensure that a user-agent string is set
        if headers is None:
            headers = {}

        # make the request
        try:
            from totalimpact.api import app
            proxies = None
            if app.config["PROXY"]:
                proxies = {'http' : app.config["PROXY"], 'https' : app.config["PROXY"]}
            r = requests.get(url, headers=headers, timeout=timeout, proxies=proxies)
        except requests.exceptions.Timeout as e:
            logger.debug("Attempt to connect to provider timed out during GET on " + url)
            raise ProviderTimeout("Attempt to connect to provider timed out during GET on " + url, e)
        except requests.exceptions.RequestException as e:
            logger.info("RequestException during GET on: " + url)
            raise ProviderHttpError("RequestException during GET on: " + url, e)

        # cache the response and return
        if use_cache:
            c.set_cache_entry(url, {'text' : r.text, 'status_code' : r.status_code})
        return r

class ProviderError(Exception):
    def __init__(self, message="", inner=None):
        self._message = message  # naming it self.message raises DepreciationWarning
        self.inner = inner
        # NOTE: experimental
        self.stack = traceback.format_stack()[:-1]

    # DeprecationWarning: BaseException.message has been deprecated
    #   as of Python 2.6 so implement property here
    @property
    def message(self):
        return (self._message)

    def log(self):
        msg = " " + self.message + " " if self.message is not None and self.message != "" else ""
        wraps = "(inner exception: " + repr(self.inner) + ")"
        return self.__class__.__name__ + ":" + msg + wraps

    def __str__(self):
        return repr(self._message)

class ProviderConfigurationError(ProviderError):
    pass

class ProviderTimeout(ProviderError):
    pass

class ProviderHttpError(ProviderError):
    pass

class ProviderClientError(ProviderError):
    def __init__(self, response, message="", inner=None):
        super(ProviderClientError, self).__init__(message, inner)
        self.response = response

class ProviderServerError(ProviderError):
    def __init__(self, response, message="", inner=None):
        super(ProviderServerError, self).__init__(message, inner)
        self.response = response

class ProviderContentMalformedError(ProviderError):
    pass

class ProviderValidationFailedError(ProviderError):
    pass

class ProviderRateLimitError(ProviderError):
    pass

<|endoftext|>


<commit_before>"""
Test 'watchpoint command'.
"""

from __future__ import print_function

import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil

class WatchpointPythonCommandTestCase(TestBase):

    mydir = TestBase.compute_mydir(__file__)

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Our simple source filename.
        self.source = 'main.cpp'
        # Find the line number to break inside main().
        self.line = line_number(
            self.source, '// Set break point at this line.')
        # And the watchpoint variable declaration line number.
        self.decl = line_number(self.source,
                                '// Watchpoint variable declaration.')
        # Build dictionary to have unique executable names for each test
        # method.
        self.exe_name = self.testMethodName
        self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}

    @skipIfFreeBSD  # timing out on buildbot
    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
    # Watchpoints not supported
    @expectedFailureAndroid(archs=['arm', 'aarch64'])
    @expectedFailureAll(
        oslist=["linux"],
        archs=["aarch64"],
        bugnumber="llvm.org/pr27710")
    def test_watchpoint_command(self):
        """Test 'watchpoint command'."""
        self.build(dictionary=self.d)
        self.setTearDownCleanup(dictionary=self.d)

        exe = os.path.join(os.getcwd(), self.exe_name)
        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
        lldbutil.run_break_set_by_file_and_line(
            self, None, self.line, num_expected_locations=1)
#        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
#            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
#                       (self.source, self.line))#

        # Run the program.
        self.runCmd("run", RUN_SUCCEEDED)

        # We should be stopped again due to the breakpoint.
        # The stop reason of the thread should be breakpoint.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
                    substrs=['stopped',
                             'stop reason = breakpoint'])

        # Now let's set a write-type watchpoint for 'global'.
        self.expect(
            "watchpoint set variable -w write global",
            WATCHPOINT_CREATED,
            substrs=[
                'Watchpoint created',
                'size = 4',
                'type = w',
                '%s:%d' %
                (self.source,
                 self.decl)])

        self.runCmd(
            'watchpoint command add -s python 1 -o \'frame.EvaluateExpression("cookie = 777")\'')

        # List the watchpoint command we just added.
        self.expect("watchpoint command list 1",
                    substrs=['frame.EvaluateExpression', 'cookie = 777'])

        # Use the '-v' option to do verbose listing of the watchpoint.
        # The hit count should be 0 initially.
        self.expect("watchpoint list -v",
                    substrs=['hit_count = 0'])

        self.runCmd("process continue")

        # We should be stopped again due to the watchpoint (write type).
        # The stop reason of the thread should be watchpoint.
        self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
                    substrs=['stop reason = watchpoint'])

        # Check that the watchpoint snapshoting mechanism is working.
        self.expect("watchpoint list -v",
                    substrs=['old value:', ' = 0',
                             'new value:', ' = 1'])

        # The watchpoint command "forced" our global variable 'cookie' to
        # become 777.
        self.expect("frame variable --show-globals cookie",
                    substrs=['(int32_t)', 'cookie = 777'])

    @skipIfFreeBSD  # timing out on buildbot
    @expectedFailureAll(
        bugnumber="llvm.org/pr28055: continue in watchpoint commands disables the watchpoint")
    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
    # Watchpoints not supported
    @expectedFailureAndroid(archs=['arm', 'aarch64'])
    @expectedFailureAll(
        oslist=["linux"],
        archs=["aarch64"],
        bugnumber="llvm.org/pr27710")
    def test_continue_in_watchpoint_command(self):
        """Test continue in a watchpoint command."""
        self.build(dictionary=self.d)
        self.setTearDownCleanup(dictionary=self.d)

        exe = os.path.join(os.getcwd(), self.exe_name)
        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
        lldbutil.run_break_set_by_file_and_line(
            self, None, self.line, num_expected_locations=1)
#        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
#            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
#                       (self.source, self.line))#

        # Run the program.
        self.runCmd("run", RUN_SUCCEEDED)

        # We should be stopped again due to the breakpoint.
        # The stop reason of the thread should be breakpoint.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
                    substrs=['stopped',
                             'stop reason = breakpoint'])

        # Now let's set a write-type watchpoint for 'global'.
        self.expect(
            "watchpoint set variable -w write global",
            WATCHPOINT_CREATED,
            substrs=[
                'Watchpoint created',
                'size = 4',
                'type = w',
                '%s:%d' %
                (self.source,
                 self.decl)])

        cmd_script_file = os.path.join(os.getcwd(), "watchpoint_command.py")
        self.runCmd("command script import '%s'" % (cmd_script_file))

        self.runCmd(
            'watchpoint command add -F watchpoint_command.watchpoint_command')

        # List the watchpoint command we just added.
        self.expect("watchpoint command list 1",
                    substrs=['watchpoint_command.watchpoint_command'])

        self.runCmd("process continue")

        # We should be stopped again due to the watchpoint (write type).
        # The stop reason of the thread should be watchpoint.
        self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
                    substrs=['stop reason = watchpoint'])

        # We should have hit the watchpoint once, set cookie to 888, then continued to the
        # second hit and set it to 999
        self.expect("frame variable --show-globals cookie",
                    substrs=['(int32_t)', 'cookie = 999'])
<commit_msg>Add the radar number on our end.<commit_after>"""
Test 'watchpoint command'.
"""

from __future__ import print_function

import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil

class WatchpointPythonCommandTestCase(TestBase):

    mydir = TestBase.compute_mydir(__file__)

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Our simple source filename.
        self.source = 'main.cpp'
        # Find the line number to break inside main().
        self.line = line_number(
            self.source, '// Set break point at this line.')
        # And the watchpoint variable declaration line number.
        self.decl = line_number(self.source,
                                '// Watchpoint variable declaration.')
        # Build dictionary to have unique executable names for each test
        # method.
        self.exe_name = self.testMethodName
        self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}

    @skipIfFreeBSD  # timing out on buildbot
    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
    # Watchpoints not supported
    @expectedFailureAndroid(archs=['arm', 'aarch64'])
    @expectedFailureAll(
        oslist=["linux"],
        archs=["aarch64"],
        bugnumber="llvm.org/pr27710")
    def test_watchpoint_command(self):
        """Test 'watchpoint command'."""
        self.build(dictionary=self.d)
        self.setTearDownCleanup(dictionary=self.d)

        exe = os.path.join(os.getcwd(), self.exe_name)
        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
        lldbutil.run_break_set_by_file_and_line(
            self, None, self.line, num_expected_locations=1)
#        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
#            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
#                       (self.source, self.line))#

        # Run the program.
        self.runCmd("run", RUN_SUCCEEDED)

        # We should be stopped again due to the breakpoint.
        # The stop reason of the thread should be breakpoint.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
                    substrs=['stopped',
                             'stop reason = breakpoint'])

        # Now let's set a write-type watchpoint for 'global'.
        self.expect(
            "watchpoint set variable -w write global",
            WATCHPOINT_CREATED,
            substrs=[
                'Watchpoint created',
                'size = 4',
                'type = w',
                '%s:%d' %
                (self.source,
                 self.decl)])

        self.runCmd(
            'watchpoint command add -s python 1 -o \'frame.EvaluateExpression("cookie = 777")\'')

        # List the watchpoint command we just added.
        self.expect("watchpoint command list 1",
                    substrs=['frame.EvaluateExpression', 'cookie = 777'])

        # Use the '-v' option to do verbose listing of the watchpoint.
        # The hit count should be 0 initially.
        self.expect("watchpoint list -v",
                    substrs=['hit_count = 0'])

        self.runCmd("process continue")

        # We should be stopped again due to the watchpoint (write type).
        # The stop reason of the thread should be watchpoint.
        self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
                    substrs=['stop reason = watchpoint'])

        # Check that the watchpoint snapshoting mechanism is working.
        self.expect("watchpoint list -v",
                    substrs=['old value:', ' = 0',
                             'new value:', ' = 1'])

        # The watchpoint command "forced" our global variable 'cookie' to
        # become 777.
        self.expect("frame variable --show-globals cookie",
                    substrs=['(int32_t)', 'cookie = 777'])

    @skipIfFreeBSD  # timing out on buildbot
    @expectedFailureAll(
        bugnumber="llvm.org/pr28055: continue in watchpoint commands disables the watchpoint, <rdar://problem/28680909>")
    @expectedFailureAll(
        oslist=["windows"],
        bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
    # Watchpoints not supported
    @expectedFailureAndroid(archs=['arm', 'aarch64'])
    @expectedFailureAll(
        oslist=["linux"],
        archs=["aarch64"],
        bugnumber="llvm.org/pr27710")
    def test_continue_in_watchpoint_command(self):
        """Test continue in a watchpoint command."""
        self.build(dictionary=self.d)
        self.setTearDownCleanup(dictionary=self.d)

        exe = os.path.join(os.getcwd(), self.exe_name)
        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)

        # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
        lldbutil.run_break_set_by_file_and_line(
            self, None, self.line, num_expected_locations=1)
#        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
#            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
#                       (self.source, self.line))#

        # Run the program.
        self.runCmd("run", RUN_SUCCEEDED)

        # We should be stopped again due to the breakpoint.
        # The stop reason of the thread should be breakpoint.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
                    substrs=['stopped',
                             'stop reason = breakpoint'])

        # Now let's set a write-type watchpoint for 'global'.
        self.expect(
            "watchpoint set variable -w write global",
            WATCHPOINT_CREATED,
            substrs=[
                'Watchpoint created',
                'size = 4',
                'type = w',
                '%s:%d' %
                (self.source,
                 self.decl)])

        cmd_script_file = os.path.join(os.getcwd(), "watchpoint_command.py")
        self.runCmd("command script import '%s'" % (cmd_script_file))

        self.runCmd(
            'watchpoint command add -F watchpoint_command.watchpoint_command')

        # List the watchpoint command we just added.
        self.expect("watchpoint command list 1",
                    substrs=['watchpoint_command.watchpoint_command'])

        self.runCmd("process continue")

        # We should be stopped again due to the watchpoint (write type).
        # The stop reason of the thread should be watchpoint.
        self.expect("thread backtrace", STOPPED_DUE_TO_WATCHPOINT,
                    substrs=['stop reason = watchpoint'])

        # We should have hit the watchpoint once, set cookie to 888, then continued to the
        # second hit and set it to 999
        self.expect("frame variable --show-globals cookie",
                    substrs=['(int32_t)', 'cookie = 999'])
<|endoftext|>


<commit_before>#!/usr/bin/python
#
# Copyright 2018-2022 Polyaxon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import re

from polyaxon.utils.date_utils import parse_datetime

# pylint:disable=anomalous-backslash-in-string

DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S %Z"  # noqa
ISO_DATETIME_REGEX = re.compile(  # noqa
    "([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]"
    "([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\\.[0-9]+)?"
    "(([Zz])|([\\+|\\-]([01][0-9]|2[0-3]):[0-5][0-9]))\s?"
)
DATETIME_REGEX = re.compile(  # noqa
    "\d{2}(?:\d{2})?-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}\s\w+\s?"
)

def timestamp_search_regex(regex, log_line):
    log_search = regex.search(log_line)
    if not log_search:
        return log_line, None

    ts = log_search.group()
    ts = parse_datetime(ts)

    return re.sub(regex, "", log_line), ts
<commit_msg>Update dt parser<commit_after>#!/usr/bin/python
#
# Copyright 2018-2022 Polyaxon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import re

from polyaxon.utils.date_utils import parse_datetime

# pylint:disable=anomalous-backslash-in-string

DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S %Z"  # noqa
ISO_DATETIME_REGEX = re.compile(  # noqa
    r"([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]"
    r"([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?"
    r"(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))\s?"
)
DATETIME_REGEX = re.compile(  # noqa
    r"\d{2}(?:\d{2})?-\d{1,2}-\d{1,2}\s\d{1,2}:\d{1,2}:\d{1,2}\s\w+\s?"
)

def timestamp_search_regex(regex, log_line):
    log_search = regex.search(log_line)
    if not log_search:
        return log_line, None

    ts = log_search.group()
    ts = parse_datetime(ts)

    return re.sub(regex, "", log_line), ts
<|endoftext|>


<commit_before>#!/usr/bin/env python
import os, logging, gym
from baselines import logger
from baselines.common import set_global_seeds
from baselines import bench
from baselines.a2c.a2c import learn
from baselines.common.vec_env.subproc_vec_env import SubprocVecEnv
from baselines.common.atari_wrappers import wrap_deepmind
from baselines.a2c.policies import CnnPolicy, LstmPolicy, LnLstmPolicy

def train(env_id, num_frames, seed, policy, lrschedule, num_cpu):
    num_timesteps = int(num_frames / 4 * 1.1)
    # divide by 4 due to frameskip, then do a little extras so episodes end
    def make_env(rank):
        def _thunk():
            env = gym.make(env_id)
            env.seed(seed + rank)
            env = bench.Monitor(env, logger.get_dir() and
                os.path.join(logger.get_dir(), "{}.monitor.json".format(rank)))
            gym.logger.setLevel(logging.WARN)
            return wrap_deepmind(env)
        return _thunk
    set_global_seeds(seed)
    env = SubprocVecEnv([make_env(i) for i in range(num_cpu)])
    if policy == 'cnn':
        policy_fn = CnnPolicy
    elif policy == 'lstm':
        policy_fn = LstmPolicy
    elif policy == 'lnlstm':
        policy_fn = LnLstmPolicy
    learn(policy_fn, env, seed, total_timesteps=num_timesteps, lrschedule=lrschedule)
    env.close()

def main():
    import argparse
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--env', help='environment ID', default='BreakoutNoFrameskip-v4')
    parser.add_argument('--seed', help='RNG seed', type=int, default=0)
    parser.add_argument('--policy', help='Policy architecture', choices=['cnn', 'lstm', 'lnlstm'], default='cnn')
    parser.add_argument('--lrschedule', help='Learning rate schedule', choices=['constant', 'linear'], default='constant')
    parser.add_argument('--million_frames', help='How many frames to train (/ 1e6). '
        'This number gets divided by 4 due to frameskip', type=int, default=40)
    args = parser.parse_args()
    train(args.env, num_frames=1e6 * args.million_frames, seed=args.seed,
        policy=args.policy, lrschedule=args.lrschedule, num_cpu=16)

if __name__ == '__main__':
    main()
<commit_msg>a2c does not work<commit_after>#!/usr/bin/env python
import os, logging, gym
from baselines import logger
from baselines.common import set_global_seeds
from baselines import bench
from baselines.a2c.a2c import learn
from baselines.common.vec_env.subproc_vec_env import SubprocVecEnv
from baselines.common.atari_wrappers import wrap_deepmind
from baselines.a2c.policies import CnnPolicy, LstmPolicy, LnLstmPolicy
import BaseTraciEnv
import Traci_1_cross_env.Traci_1_cross_env
import Traci_2_cross_env.Traci_2_cross_env
import Traci_3_cross_env.Traci_3_cross_env

def train(env_id, num_frames, seed, policy, lrschedule, num_cpu):
    num_timesteps = int(num_frames / 4 * 1.1)
    # divide by 4 due to frameskip, then do a little extras so episodes end
    def make_env(rank):
        def _thunk():
            env = gym.make(env_id)

            env.configure_traci(num_car_chances=1000,
                                car_props=[0.25, 0.05],
                                reward_func=BaseTraciEnv.BaseTraciEnv.reward_total_waiting_vehicles,
                                state_contain_num_cars_in_queue_history=True,
                                state_contain_avg_speed_between_detectors_history=False,
                                state_contain_time_since_tl_change=True,
                                state_contain_tl_state_history=True,
                                num_actions_pr_trafficlight=3)

            env.seed(seed + rank)
            env = bench.Monitor(env, logger.get_dir() and
                os.path.join(logger.get_dir(), "{}.monitor.json".format(rank)))
            gym.logger.setLevel(logging.WARN)
            return env
        return _thunk
    set_global_seeds(seed)
    env = SubprocVecEnv([make_env(i) for i in range(num_cpu)])
    if policy == 'cnn':
        policy_fn = CnnPolicy
    elif policy == 'lstm':
        policy_fn = LstmPolicy
    elif policy == 'lnlstm':
        policy_fn = LnLstmPolicy
    learn(policy_fn, env, seed, total_timesteps=num_timesteps, lrschedule=lrschedule)
    env.close()

def main():
    import argparse
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--env', help='environment ID', default='Traci_3_cross_env-v0')
    parser.add_argument('--seed', help='RNG seed', type=int, default=0)
    parser.add_argument('--policy', help='Policy architecture', choices=['cnn', 'lstm', 'lnlstm'], default='lnlstm')
    parser.add_argument('--lrschedule', help='Learning rate schedule', choices=['constant', 'linear'], default='constant')
    parser.add_argument('--million_frames', help='How many frames to train (/ 1e6). '
        'This number gets divided by 4 due to frameskip', type=int, default=40)
    args = parser.parse_args()
    train(args.env, num_frames=1e6 * args.million_frames, seed=args.seed,
        policy=args.policy, lrschedule=args.lrschedule, num_cpu=16)

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


<commit_before>"""ExperimentPsychopyView-class."""

import os
import utils
import glib
from psychopy import visual, sound

class ExperimentPsychopyView:
    """Psychopy-view for the experiment-instance."""

    def __init__(self, debug):
        """Constructor."""
        self.window = self.create_window(debug)

        self.playing = []
        self.stopped = False
        self.draw_diagnostics = False
        self.volume = 1.0

        # temporarily here
        self.overlay_texts = {}

        glib.idle_add(self.redraw)

    def on_add_draw_que(self, itemid, draw_parameters):
        """Parameters: txt, loc(x,y) 0->1coord, hloc, vloc."""
        self.overlay_texts[itemid] = draw_parameters

    def on_draw_que_updated(self):
        """Callback for on_draw_que_updated."""
        self.overlay_texts = {}

    def stop(self):
        """Method for stopping the experiment."""
        self.stopped = True

    def play(self):
        """Method for starting to play the experiment."""
        self.stopped = False
        glib.idle_add(self.redraw)

    def add_model(self, model):
        """
        Add a model for this view.

        Parameters: model[section-instance handle]
        """
        model.on("imagefiles_added", self.on_imagefiles_added)
        model.on("moviefiles_added", self.on_moviefiles_added)
        model.on("soundfiles_added", self.on_soundfiles_added)
        model.on("play_image", self.on_play_image)
        model.on("play_movie", self.on_play_movie)
        model.on("play_sound", self.on_play_sound)
        model.on("stimuli_cleared", self.on_stimuli_cleared)
        model.on("draw_diagnostics", self.on_draw_diagnostics)
        model.on("add_draw_que", self.on_add_draw_que)
        model.on("draw_que_updated", self.on_draw_que_updated)

    def remove_model(self, model):
        """
        Remove a model from this view.

        Parameters: model[section-instance handle]
        """
        model.remove_listener("imagefiles_added", self.on_imagefiles_added)
        model.remove_listener("moviefiles_added", self.on_moviefiles_added)
        model.remove_listener("soundfiles_added", self.on_soundfiles_added)
        model.remove_listener("play_image", self.on_play_image)
        model.remove_listener("play_movie", self.on_play_movie)
        model.remove_listener("play_sound", self.on_play_sound)
        model.remove_listener("stimuli_cleared", self.on_stimuli_cleared)
        model.remove_listener("draw_diagnostics", self.on_draw_diagnostics)
        model.remove_listener("add_draw_que", self.on_add_draw_que)
        model.remove_listener("draw_que_updated", self.on_draw_que_updated)

    def on_draw_diagnostics(self, do_it):
        """Callback for draw_diagnostics signal."""
        self.draw_diagnostics = do_it

    def on_imagefiles_added(self, mediadir, files):
        """Load list of imagefiles to RAM."""
        self.imageobjects = []
        for imagef in files:
            himg = self.load_image(self.window, os.path.join(mediadir, imagef))
            self.imageobjects.append(himg)

    def on_moviefiles_added(self, mediadir, files):
        """Load list of moviefiles to RAM."""
        self.movieobjects = []
        for movief in files:
            hmovie = self.load_movie(self.window,
                                     os.path.join(mediadir, movief))
            self.movieobjects.append(hmovie)

    def on_soundfiles_added(self, mediadir, files):
        """Load list of soundfiles to RAM."""
        self.soundobjects = []
        for soundf in files:
            hsound = self.load_sound(os.path.join(mediadir, soundf))
            self.soundobjects.append(hsound)

    def on_play_image(self, stimnum, aoi):
        """Callback for play_image signal."""
        stm = self.imageobjects[stimnum]
        self.play_image(stm, aoi)
        self.playing.append(stm)

    def on_play_movie(self, stimnum, aoi):
        """Callback for play_movie signal."""
        stm = self.movieobjects[stimnum]
        self.play_movie(stm, aoi)
        self.playing.append(stm)

    def on_play_sound(self, stimnum):
        """Callback for play_sound signal."""
        stm = self.soundobjects[stimnum]
        stm.play()
        self.playing.append(stm)

    def redraw(self):
        """Drawing loop."""
        if not self.stopped:
            # draw frames from movies and pictures
            for i in self.playing:
                if i.__class__.__name__ == 'MovieStim3':
                    i.draw()
                elif i.__class__.__name__ == 'ImageStim':
                    i.draw()

            if self.draw_diagnostics:
                self.draw_overlay_texts()

            self.window.flip()

            glib.idle_add(self.redraw)

        return False

    def on_stimuli_cleared(self):
        """Close all running stimuli."""
        for k in self.playing:
            if k.__class__.__name__ == 'MovieStim3':
                k.seek(0)  # go start # errors some times
                k.pause()
                # k.autoDraw = False

            elif k.__class__.__name__ == 'SoundStim':
                k.stop()
            else:
                # imageobject
                k.autoDraw = False

        self.playing = []

    def draw_overlay_texts(self):
        """Draw all elements in the que. Draws by order of the list."""
        ystartloc = 0.95
        # loop through all the elements
        for key in self.overlay_texts:
            item = self.overlay_texts[key]
            itype = item["type"]

            if itype == "text":
                htxt = visual.TextStim(self.window, text=item["txt"],
                                       pos=(-0.95, ystartloc),
                                       alignHoriz="left", alignVert="center")
                htxt.draw()
                ystartloc = ystartloc-0.1
            elif itype == "circle":
                x, y = utils.to_psychopy_coord(item["x"], item["y"])
                htxt = visual.TextStim(self.window, text="o", pos=(x, y),
                                       alignHoriz="center", alignVert="center")
                htxt.draw()

    def create_window(self, debug):
        """Create a window for the experiment. Debug[bool]:windowed mode."""
        res = [1024, 768]
        res_ratio = float(res[1])/float(res[0])

        if debug:
            return visual.Window(size=(500, res_ratio*500), pos=(200, 300))
        else:
            return visual.Window(screen=1,  size=(res[0], res[1]),
                                 fullscr=True, allowGUI=False)

    def load_movie(self, window, filepath):
        """Load a moviefile to RAM tied to specified window."""
        movieobject = visual.MovieStim3(window, filepath, loop=True)
        movieobject.units = "norm"

        return movieobject

    def load_image(self, window, filepath):
        """Load ann imagefile to RAM tied to specified window."""
        return visual.ImageStim(window, image=filepath)

    def load_sound(self, filepath):
        """Load a soundfile to RAM."""
        return sound.SoundPygame(value=filepath)

    def play_movie(self, movieobject, aoi):
        """Start playing movie."""
        # Transfer to psychopy coordinates (-1->1, 1->-1)
        # from normalized (0->1, 0->1)
        p_x, p_y, width, height = utils.aoi_from_experiment_to_psychopy(aoi)

        movieobject.play()

        movieobject.pos = (p_x, p_y)
        movieobject.size = [width, height]
        movieobject.draw()
        # stm.autoDraw = True

    def play_image(self, imageobject, aoi):
        """Start playing image."""
        p_x, p_y, width, height = utils.aoi_from_experiment_to_psychopy(aoi)

        imageobject.pos = (p_x, p_y)
        imageobject.size = [width, height]
        imageobject.draw()
        # stm.autoDraw = True

    def __del__(self):
        """Destructor."""
        self.stopped = True
        self.window.close()
        self.window = None
<commit_msg>Fixed sound issue with Mac OS X.<commit_after>"""ExperimentPsychopyView-class."""

import os
import utils
import glib
from psychopy import visual, sound

class ExperimentPsychopyView:
    """Psychopy-view for the experiment-instance."""

    def __init__(self, debug):
        """Constructor."""
        self.window = self.create_window(debug)

        self.playing = []
        self.stopped = False
        self.draw_diagnostics = False
        self.volume = 1.0

        # temporarily here
        self.overlay_texts = {}

        glib.idle_add(self.redraw)

    def on_add_draw_que(self, itemid, draw_parameters):
        """Parameters: txt, loc(x,y) 0->1coord, hloc, vloc."""
        self.overlay_texts[itemid] = draw_parameters

    def on_draw_que_updated(self):
        """Callback for on_draw_que_updated."""
        self.overlay_texts = {}

    def stop(self):
        """Method for stopping the experiment."""
        self.stopped = True

    def play(self):
        """Method for starting to play the experiment."""
        self.stopped = False
        glib.idle_add(self.redraw)

    def add_model(self, model):
        """
        Add a model for this view.

        Parameters: model[section-instance handle]
        """
        model.on("imagefiles_added", self.on_imagefiles_added)
        model.on("moviefiles_added", self.on_moviefiles_added)
        model.on("soundfiles_added", self.on_soundfiles_added)
        model.on("play_image", self.on_play_image)
        model.on("play_movie", self.on_play_movie)
        model.on("play_sound", self.on_play_sound)
        model.on("stimuli_cleared", self.on_stimuli_cleared)
        model.on("draw_diagnostics", self.on_draw_diagnostics)
        model.on("add_draw_que", self.on_add_draw_que)
        model.on("draw_que_updated", self.on_draw_que_updated)

    def remove_model(self, model):
        """
        Remove a model from this view.

        Parameters: model[section-instance handle]
        """
        model.remove_listener("imagefiles_added", self.on_imagefiles_added)
        model.remove_listener("moviefiles_added", self.on_moviefiles_added)
        model.remove_listener("soundfiles_added", self.on_soundfiles_added)
        model.remove_listener("play_image", self.on_play_image)
        model.remove_listener("play_movie", self.on_play_movie)
        model.remove_listener("play_sound", self.on_play_sound)
        model.remove_listener("stimuli_cleared", self.on_stimuli_cleared)
        model.remove_listener("draw_diagnostics", self.on_draw_diagnostics)
        model.remove_listener("add_draw_que", self.on_add_draw_que)
        model.remove_listener("draw_que_updated", self.on_draw_que_updated)

    def on_draw_diagnostics(self, do_it):
        """Callback for draw_diagnostics signal."""
        self.draw_diagnostics = do_it

    def on_imagefiles_added(self, mediadir, files):
        """Load list of imagefiles to RAM."""
        self.imageobjects = []
        for imagef in files:
            himg = self.load_image(self.window, os.path.join(mediadir, imagef))
            self.imageobjects.append(himg)

    def on_moviefiles_added(self, mediadir, files):
        """Load list of moviefiles to RAM."""
        self.movieobjects = []
        for movief in files:
            hmovie = self.load_movie(self.window,
                                     os.path.join(mediadir, movief))
            self.movieobjects.append(hmovie)

    def on_soundfiles_added(self, mediadir, files):
        """Load list of soundfiles to RAM."""
        self.soundobjects = []
        for soundf in files:
            hsound = self.load_sound(os.path.join(mediadir, soundf))
            self.soundobjects.append(hsound)

    def on_play_image(self, stimnum, aoi):
        """Callback for play_image signal."""
        stm = self.imageobjects[stimnum]
        self.play_image(stm, aoi)
        self.playing.append(stm)

    def on_play_movie(self, stimnum, aoi):
        """Callback for play_movie signal."""
        stm = self.movieobjects[stimnum]
        self.play_movie(stm, aoi)
        self.playing.append(stm)

    def on_play_sound(self, stimnum):
        """Callback for play_sound signal."""
        stm = self.soundobjects[stimnum]
        stm.play()
        self.playing.append(stm)

    def redraw(self):
        """Drawing loop."""
        if not self.stopped:
            # draw frames from movies and pictures
            for i in self.playing:
                if i.__class__.__name__ == 'MovieStim3':
                    i.draw()
                elif i.__class__.__name__ == 'ImageStim':
                    i.draw()

            if self.draw_diagnostics:
                self.draw_overlay_texts()

            self.window.flip()

            glib.idle_add(self.redraw)

        return False

    def on_stimuli_cleared(self):
        """Close all running stimuli."""
        for k in self.playing:
            if k.__class__.__name__ == 'MovieStim3':
                k.seek(0)  # go start # errors some times
                k.pause()
                # k.autoDraw = False

            elif k.__class__.__name__ == 'SoundStim':
                k.stop()
            else:
                # imageobject
                k.autoDraw = False

        self.playing = []

    def draw_overlay_texts(self):
        """Draw all elements in the que. Draws by order of the list."""
        ystartloc = 0.95
        # loop through all the elements
        for key in self.overlay_texts:
            item = self.overlay_texts[key]
            itype = item["type"]

            if itype == "text":
                htxt = visual.TextStim(self.window, text=item["txt"],
                                       pos=(-0.95, ystartloc),
                                       alignHoriz="left", alignVert="center")
                htxt.draw()
                ystartloc = ystartloc-0.1
            elif itype == "circle":
                x, y = utils.to_psychopy_coord(item["x"], item["y"])
                htxt = visual.TextStim(self.window, text="o", pos=(x, y),
                                       alignHoriz="center", alignVert="center")
                htxt.draw()

    def create_window(self, debug):
        """Create a window for the experiment. Debug[bool]:windowed mode."""
        res = [1024, 768]
        res_ratio = float(res[1])/float(res[0])

        if debug:
            return visual.Window(size=(500, res_ratio*500), pos=(200, 300))
        else:
            return visual.Window(screen=1,  size=(res[0], res[1]),
                                 fullscr=True, allowGUI=False)

    def load_movie(self, window, filepath):
        """Load a moviefile to RAM tied to specified window."""
        movieobject = visual.MovieStim3(window, filepath, loop=True)
        movieobject.units = "norm"

        return movieobject

    def load_image(self, window, filepath):
        """Load ann imagefile to RAM tied to specified window."""
        return visual.ImageStim(window, image=filepath)

    def load_sound(self, filepath):
        """Load a soundfile to RAM."""
        return sound.Sound(value=filepath)

    def play_movie(self, movieobject, aoi):
        """Start playing movie."""
        # Transfer to psychopy coordinates (-1->1, 1->-1)
        # from normalized (0->1, 0->1)
        p_x, p_y, width, height = utils.aoi_from_experiment_to_psychopy(aoi)

        movieobject.play()

        movieobject.pos = (p_x, p_y)
        movieobject.size = [width, height]
        movieobject.draw()
        # stm.autoDraw = True

    def play_image(self, imageobject, aoi):
        """Start playing image."""
        p_x, p_y, width, height = utils.aoi_from_experiment_to_psychopy(aoi)

        imageobject.pos = (p_x, p_y)
        imageobject.size = [width, height]
        imageobject.draw()
        # stm.autoDraw = True

    def __del__(self):
        """Destructor."""
        self.stopped = True
        self.window.close()
        self.window = None
<|endoftext|>


<commit_before>from fabric.api import *
import os
import sys
import random
import time
import string
import uuid
# Custom Code Enigma modules
import common.Utils
import DrupalUtils

@task
def main(shortname, branch, bucket_name, method='zip', sanitise='yes'):
  print "===> You want to download a database dump for %s %s. Let's start by fetching a fresh database..." % (shortname, branch)

  try:
    DrupalUtils.get_database(shortname, branch, sanitise)
    common.Utils.s3_upload(shortname, branch, method, shortname, bucket_name)
  except:
    e = sys.exc_info()[1]
    raise SystemError(e)
<commit_msg>In order for s3 uploads to work with the db backup utility some paths need tweaking when it is called.<commit_after>from fabric.api import *
import os
import sys
import random
import time
import string
import uuid
# Custom Code Enigma modules
import common.Utils
import DrupalUtils

@task
def main(shortname, branch, bucket_name, method='zip', sanitise='yes'):
  print "===> You want to download a database dump for %s %s. Let's start by fetching a fresh database..." % (shortname, branch)

  try:
    DrupalUtils.get_database(shortname, branch, sanitise)
    common.Utils.s3_upload(shortname, branch, method, "database_dump", bucket_name, "client-db-dumps")
  except:
    e = sys.exc_info()[1]
    raise SystemError(e)
<|endoftext|>


<commit_before># -*- mode: python; coding: utf-8 -*-
import os
import re
import os.path
import logging
import datetime
from drydrop.lib.utils import open_if_exists
from drydrop.app.models import Resource
from google.appengine.api import urlfetch
from google.appengine.ext import db
from drydrop.app.core.events import log_event

class VFS(object):
    """Virtual File System == filesystem abstraction for DryDrop"""
    def __init__(self):
        super(VFS, self).__init__()

    def fetch_resource_content(self, path):
        logging.warning('fetch_resource not implemented for %s', self.__class__.__name__)
        return None

    def fetch_file_timestamp(self, path):
        return None

    def get_resource(self, path):
        domain = os.environ['SERVER_NAME']
        resource = Resource.find(path=path, generation=self.settings.version, domain=domain)
        if resource is None:
            content = self.fetch_resource_content(path)
            created_on = self.fetch_file_timestamp(path)
            resource = Resource(path=path, content=content, generation=self.settings.version)
            if created_on is not None:
                resource.created_on = created_on
            try:
                length = len(resource.content)
            except:
                length = 0
            if length>0:
                log_event("Caching resource %s (%d bytes)" % (path, length))
            logging.debug("VFS: caching resource %s (%d bytes) for %s", path, length, domain)
            resource.domain = domain
            resource.save()
        try:
            length = len(resource.content)
        except:
            length = 0
        logging.debug("VFS: serving resource %s (%d bytes) for %s", path, length, domain)
        return resource

    def flush_resources(self, count = 1000):
        domain = os.environ['SERVER_NAME']
        deleted = Resource.clear(False, count, domain=domain)
        finished = deleted<count
        return finished, deleted

    def flush_resource(self, path):
        # purge all generations
        resources = Resource.all().filter("path =", path).filter("domain =", os.environ['SERVER_NAME']).fetch(1000)
        db.delete(resources)

    def get_all_resources(self):
        return Resource.all().filter("generation =", self.settings.version).filter("domain =", os.environ['SERVER_NAME']).fetch(1000)

class LocalVFS(VFS):
    """VFS for local development"""

    def __init__(self, settings):
        super(LocalVFS, self).__init__()
        self.settings = settings

    def get_resource(self, path):
        # check if file is fresh in cache
        resource = Resource.find(path=path, domain=os.environ['SERVER_NAME'])
        if resource is not None:
            stamp = self.fetch_file_timestamp(path)
            if stamp is not None and resource.created_on != stamp:
                logging.debug("VFS: file %s has been modified since last time => purged from cache", path)
                resource.delete()
        return super(LocalVFS, self).get_resource(path)

    def fetch_file_timestamp(self, path):
        root = self.settings.source
        if not root:
            return None
        filepath = os.path.join(root, path)
        try:
            s = os.stat(filepath)
        except:
            return None
        return datetime.datetime.fromtimestamp(s.st_mtime)

    def fetch_resource_content(self, path):
        root = self.settings.source
        if not root:
            return None
        filepath = os.path.join(root, path)
        f = open_if_exists(filepath)
        if f is None:
            return None
        try:
            contents = f.read()
        finally:
            f.close()
        return contents

class GAEVFS(VFS):
    """VFS for production"""

    def __init__(self, settings):
        super(GAEVFS, self).__init__()
        self.settings = settings

    def fetch_resource_content(self, path):
        root = self.settings.source
        if not root:
            return None
        if not root.endswith('/'): root = root + "/"
        url = root + path
        params = []
        if self.settings.github_login:
            params.append("login=%s" % self.settings.github_login)
        if self.settings.github_token:
            params.append("token=%s" % self.settings.github_token)

        # note: params should be url-safe, so no need to escape here
        if len(params)>0:
            url = url + "?" + string.join(params, "&")

        response = urlfetch.fetch(url, follow_redirects=False)
        if response.status_code!=200:
            return None
        # HACK: if we get 200 with section referring to status404 treat it as 404, this is bug on github side
        #       see http://github.com/darwin/drydrop/issues/#issue/2 for more info
        if re.search(r'id="error" class="status404"', response.content):
            logging.warning("got bogus 404 response for %s", url)
            return None

        return response.content
<commit_msg>Follow redirects. This fixes a bug that occurs when github redirects from http to https URLs and previously the url fetcher was silently failing<commit_after># -*- mode: python; coding: utf-8 -*-
import os
import re
import os.path
import logging
import datetime
from drydrop.lib.utils import open_if_exists
from drydrop.app.models import Resource
from google.appengine.api import urlfetch
from google.appengine.ext import db
from drydrop.app.core.events import log_event

class VFS(object):
    """Virtual File System == filesystem abstraction for DryDrop"""
    def __init__(self):
        super(VFS, self).__init__()

    def fetch_resource_content(self, path):
        logging.warning('fetch_resource not implemented for %s', self.__class__.__name__)
        return None

    def fetch_file_timestamp(self, path):
        return None

    def get_resource(self, path):
        domain = os.environ['SERVER_NAME']
        resource = Resource.find(path=path, generation=self.settings.version, domain=domain)
        if resource is None:
            content = self.fetch_resource_content(path)
            created_on = self.fetch_file_timestamp(path)
            resource = Resource(path=path, content=content, generation=self.settings.version)
            if created_on is not None:
                resource.created_on = created_on
            try:
                length = len(resource.content)
            except:
                length = 0
            if length>0:
                log_event("Caching resource %s (%d bytes)" % (path, length))
            logging.debug("VFS: caching resource %s (%d bytes) for %s", path, length, domain)
            resource.domain = domain
            resource.save()
        try:
            length = len(resource.content)
        except:
            length = 0
        logging.debug("VFS: serving resource %s (%d bytes) for %s", path, length, domain)
        return resource

    def flush_resources(self, count = 1000):
        domain = os.environ['SERVER_NAME']
        deleted = Resource.clear(False, count, domain=domain)
        finished = deleted<count
        return finished, deleted

    def flush_resource(self, path):
        # purge all generations
        resources = Resource.all().filter("path =", path).filter("domain =", os.environ['SERVER_NAME']).fetch(1000)
        db.delete(resources)

    def get_all_resources(self):
        return Resource.all().filter("generation =", self.settings.version).filter("domain =", os.environ['SERVER_NAME']).fetch(1000)

class LocalVFS(VFS):
    """VFS for local development"""

    def __init__(self, settings):
        super(LocalVFS, self).__init__()
        self.settings = settings

    def get_resource(self, path):
        # check if file is fresh in cache
        resource = Resource.find(path=path, domain=os.environ['SERVER_NAME'])
        if resource is not None:
            stamp = self.fetch_file_timestamp(path)
            if stamp is not None and resource.created_on != stamp:
                logging.debug("VFS: file %s has been modified since last time => purged from cache", path)
                resource.delete()
        return super(LocalVFS, self).get_resource(path)

    def fetch_file_timestamp(self, path):
        root = self.settings.source
        if not root:
            return None
        filepath = os.path.join(root, path)
        try:
            s = os.stat(filepath)
        except:
            return None
        return datetime.datetime.fromtimestamp(s.st_mtime)

    def fetch_resource_content(self, path):
        root = self.settings.source
        if not root:
            return None
        filepath = os.path.join(root, path)
        f = open_if_exists(filepath)
        if f is None:
            return None
        try:
            contents = f.read()
        finally:
            f.close()
        return contents

class GAEVFS(VFS):
    """VFS for production"""

    def __init__(self, settings):
        super(GAEVFS, self).__init__()
        self.settings = settings

    def fetch_resource_content(self, path):
        root = self.settings.source
        if not root:
            return None
        if not root.endswith('/'): root = root + "/"
        url = root + path
        params = []
        if self.settings.github_login:
            params.append("login=%s" % self.settings.github_login)
        if self.settings.github_token:
            params.append("token=%s" % self.settings.github_token)

        # note: params should be url-safe, so no need to escape here
        if len(params)>0:
            url = url + "?" + string.join(params, "&")

        response = urlfetch.fetch(url, follow_redirects=True)
        if response.status_code!=200:
            return None
        # HACK: if we get 200 with section referring to status404 treat it as 404, this is bug on github side
        #       see http://github.com/darwin/drydrop/issues/#issue/2 for more info
        if re.search(r'id="error" class="status404"', response.content):
            logging.warning("got bogus 404 response for %s", url)
            return None

        return response.content
<|endoftext|>


<commit_before>import logging

from flask import request
from flask.views import MethodView
from flask_helpers.build_response import build_response

# Import the Game Controller
from Game.GameController import GameController

class GameModes(MethodView):
    def get(self):
        logging.debug("GameModes: GET: Initializing GameObject")
        game_object = GameController()
        logging.debug("GameModes: GET: GameObject initialized to {}".format(game_object.save()))

        logging.debug("GameModes: GET: Checking if textmode flag set")
        if request.args.get('textmode', None):
            logging.debug("GameModes: GET: Responding with list of names")
            response_data = game_object.game_mode_names
        else:
            logging.debug("GameModes: GET: Responding with JSON object")
            response_data = [{"mode": gt.mode,
                              "digits": gt.digits,
                              "digit-type": gt.digit_type,
                              "guesses": gt.guesses_allowed
                             } for gt in game_object.game_modes]

        logging.debug("GameModes: GET: Return {}".format(response_data))
        return build_response(
            html_status=200,
            response_data=response_data,
            response_mimetype="application/json"
        )
<commit_msg>Update logging for message output and consistency.<commit_after>import logging

from flask import request
from flask.views import MethodView
from flask_helpers.build_response import build_response

# Import the Game Controller
from Game.GameController import GameController

class GameModes(MethodView):
    def get(self):
        logging.debug("GameModes: GET: Initializing GameObject")
        game_object = GameController()
        logging.debug("GameModes: GET: GameObject initialized to {}".format(game_object.save()))

        logging.debug("GameModes: GET: Checking if textmode flag set")
        if request.args.get('textmode', None):
            logging.debug("GameModes: GET: Responding with list of names")
            response_data = game_object.game_mode_names
        else:
            logging.debug("GameModes: GET: Responding with JSON object: {}".format(game_object.game_modes))
            response_data = [{"mode": gt.mode,
                              "digits": gt.digits,
                              "digit-type": gt.digit_type,
                              "guesses": gt.guesses_allowed
                             } for gt in game_object.game_modes]

        logging.debug("GameModes: GET: Return {}".format(response_data))
        return build_response(
            html_status=200,
            response_data=response_data,
            response_mimetype="application/json"
        )
<|endoftext|>


<commit_before>"""
(c) 2013 Rachel Sanders.  All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
   limitations under the License.
"""

from functools import wraps
import logging

from flask import abort, current_app, redirect

__version__ = u'0.4dev'

log = logging.getLogger(u'flask-featureflags')

RAISE_ERROR_ON_MISSING_FEATURES = u'RAISE_ERROR_ON_MISSING_FEATURES'
FEATURE_FLAGS_CONFIG = u'FEATURE_FLAGS'

EXTENSION_NAME = "FeatureFlags"

class StopCheckingFeatureFlags(Exception):
  """ Raise this inside of a feature flag handler to immediately return False and stop any further handers from running """
  pass

def AppConfigFlagHandler(feature=None):
  """ This is the default handler. It checks for feature flags in the current app's configuration.

  For example, to have 'unfinished_feature' hidden in production but active in development:

  config.py

  class ProductionConfig(Config):

    FEATURE_FLAGS = {
      'unfinished_feature' : False,
    }

  class DevelopmentConfig(Config):

    FEATURE_FLAGS = {
      'unfinished_feature' : True,
    }

   """
  if not current_app:
    log.warn(u"Got a request to check for {feature} but we're outside the request context. Returning False".format(feature=feature))
    return False

  try:
    return current_app.config[FEATURE_FLAGS_CONFIG][feature]
  except (AttributeError, KeyError):
    if current_app.debug and current_app.config.get(RAISE_ERROR_ON_MISSING_FEATURES, False):
      raise KeyError(u"No feature flag defined for {feature}".format(feature=feature))
    else:
      log.info(u"No feature flag defined for {feature}".format(feature=feature))
      return False

class FeatureFlag(object):

  JINJA_TEST_NAME = u'active_feature'

  def __init__(self, app=None):
    if app is not None:
      self.init_app(app)

    # The default out-of-the-box handler looks up features in Flask's app config.
    self.handlers = [AppConfigFlagHandler]

  def init_app(self, app):
    """ Add ourselves into the app config and setup, and add a jinja function test """

    app.config.setdefault(FEATURE_FLAGS_CONFIG, {})
    app.config.setdefault(RAISE_ERROR_ON_MISSING_FEATURES, False)

    app.add_template_test(self.check, name=self.JINJA_TEST_NAME)

    if not hasattr(app, 'extensions'):
      app.extensions = {}
    app.extensions[EXTENSION_NAME] = self

  def clear_handlers(self):
    """ Clear all handlers. This effectively turns every feature off."""
    self.handlers = []

  def add_handler(self, function):
    """ Add a new handler to the end of the chain of handlers. """
    self.handlers.append(function)

  def remove_handler(self, function):
    """ Remove a handler from the chain of handlers.  """
    try:
      self.handlers.remove(function)
    except ValueError:  # handler wasn't in the list, pretend we don't notice
      pass

  def check(self, feature):
    """ Loop through all our feature flag checkers and return true if any of them are true.

    The order of handlers matters - we will immediately return True if any handler returns true.

    If you want to a handler to return False and stop the chain, raise the StopCheckingFeatureFlags exception."""
    for handler in self.handlers:
      try:
        if handler(feature):
           return True
      except StopCheckingFeatureFlags:
        return False
    else:
      return False

def is_active(feature):
  """ Check if a feature is active """

  if current_app:
    feature_flagger = current_app.extensions.get(EXTENSION_NAME)
    if feature_flagger:
      return feature_flagger.check(feature)
    else:
      raise AssertionError("Oops. This application doesn't have the Flask-FeatureFlag extention installed.")

  else:
    log.warn(u"Got a request to check for {feature} but we're running outside the request context. Check your setup. Returning False".format(feature=feature))
    return False

def is_active_feature(feature, redirect_to=None):
  """
  Decorator for Flask views. If a feature is off, it can either return a 404 or redirect to a URL if you'd rather.
  """
  def _is_active_feature(func):
    @wraps(func)
    def wrapped(*args, **kwargs):

      if not is_active(feature):
        if redirect_to:
          log.debug(u'Feature {feature} is off, redirecting to {url}'.format(feature=feature, url=redirect_to))
          return redirect(redirect_to, code=302)
        else:
          log.debug(u'Feature {feature} is off, aborting request'.format(feature=feature))
          abort(404)

      return func(*args, **kwargs)
    return wrapped
  return _is_active_feature

# Silence that annoying No handlers could be found for logger "flask-featureflags"
class NullHandler(logging.Handler):
  def emit(self, record):
    pass

log.addHandler(NullHandler())
<commit_msg>Fixed template test check - apparently that was added in 0.10. My bad.<commit_after>"""
(c) 2013 Rachel Sanders.  All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
   limitations under the License.
"""

from functools import wraps
import logging

from flask import abort, current_app, redirect

__version__ = u'0.4dev'

log = logging.getLogger(u'flask-featureflags')

RAISE_ERROR_ON_MISSING_FEATURES = u'RAISE_ERROR_ON_MISSING_FEATURES'
FEATURE_FLAGS_CONFIG = u'FEATURE_FLAGS'

EXTENSION_NAME = "FeatureFlags"

class StopCheckingFeatureFlags(Exception):
  """ Raise this inside of a feature flag handler to immediately return False and stop any further handers from running """
  pass

def AppConfigFlagHandler(feature=None):
  """ This is the default handler. It checks for feature flags in the current app's configuration.

  For example, to have 'unfinished_feature' hidden in production but active in development:

  config.py

  class ProductionConfig(Config):

    FEATURE_FLAGS = {
      'unfinished_feature' : False,
    }

  class DevelopmentConfig(Config):

    FEATURE_FLAGS = {
      'unfinished_feature' : True,
    }

   """
  if not current_app:
    log.warn(u"Got a request to check for {feature} but we're outside the request context. Returning False".format(feature=feature))
    return False

  try:
    return current_app.config[FEATURE_FLAGS_CONFIG][feature]
  except (AttributeError, KeyError):
    if current_app.debug and current_app.config.get(RAISE_ERROR_ON_MISSING_FEATURES, False):
      raise KeyError(u"No feature flag defined for {feature}".format(feature=feature))
    else:
      log.info(u"No feature flag defined for {feature}".format(feature=feature))
      return False

class FeatureFlag(object):

  JINJA_TEST_NAME = u'active_feature'

  def __init__(self, app=None):
    if app is not None:
      self.init_app(app)

    # The default out-of-the-box handler looks up features in Flask's app config.
    self.handlers = [AppConfigFlagHandler]

  def init_app(self, app):
    """ Add ourselves into the app config and setup, and add a jinja function test """

    app.config.setdefault(FEATURE_FLAGS_CONFIG, {})
    app.config.setdefault(RAISE_ERROR_ON_MISSING_FEATURES, False)

    if hasattr(app, "add_template_test"):
      # flask 0.10 and higher has a proper hook
      app.add_template_test(self.check, name=self.JINJA_TEST_NAME)
    else:
      app.jinja_env.tests[self.JINJA_TEST_NAME] = self.check

    if not hasattr(app, 'extensions'):
      app.extensions = {}
    app.extensions[EXTENSION_NAME] = self

  def clear_handlers(self):
    """ Clear all handlers. This effectively turns every feature off."""
    self.handlers = []

  def add_handler(self, function):
    """ Add a new handler to the end of the chain of handlers. """
    self.handlers.append(function)

  def remove_handler(self, function):
    """ Remove a handler from the chain of handlers.  """
    try:
      self.handlers.remove(function)
    except ValueError:  # handler wasn't in the list, pretend we don't notice
      pass

  def check(self, feature):
    """ Loop through all our feature flag checkers and return true if any of them are true.

    The order of handlers matters - we will immediately return True if any handler returns true.

    If you want to a handler to return False and stop the chain, raise the StopCheckingFeatureFlags exception."""
    for handler in self.handlers:
      try:
        if handler(feature):
           return True
      except StopCheckingFeatureFlags:
        return False
    else:
      return False

def is_active(feature):
  """ Check if a feature is active """

  if current_app:
    feature_flagger = current_app.extensions.get(EXTENSION_NAME)
    if feature_flagger:
      return feature_flagger.check(feature)
    else:
      raise AssertionError("Oops. This application doesn't have the Flask-FeatureFlag extention installed.")

  else:
    log.warn(u"Got a request to check for {feature} but we're running outside the request context. Check your setup. Returning False".format(feature=feature))
    return False

def is_active_feature(feature, redirect_to=None):
  """
  Decorator for Flask views. If a feature is off, it can either return a 404 or redirect to a URL if you'd rather.
  """
  def _is_active_feature(func):
    @wraps(func)
    def wrapped(*args, **kwargs):

      if not is_active(feature):
        if redirect_to:
          log.debug(u'Feature {feature} is off, redirecting to {url}'.format(feature=feature, url=redirect_to))
          return redirect(redirect_to, code=302)
        else:
          log.debug(u'Feature {feature} is off, aborting request'.format(feature=feature))
          abort(404)

      return func(*args, **kwargs)
    return wrapped
  return _is_active_feature

# Silence that annoying No handlers could be found for logger "flask-featureflags"
class NullHandler(logging.Handler):
  def emit(self, record):
    pass

log.addHandler(NullHandler())
<|endoftext|>


<commit_before>class RemoteAppFactory(object):
    """The factory to create remote app and bind it to given extension.

    :param default_name: the default name which be used for registering.
    :param kwargs: the pre-defined kwargs.
    :param docstring: the docstring of factory.
    """

    def __init__(self, default_name, kwargs, docstring=''):
        assert 'name' not in kwargs
        assert 'register' not in kwargs
        self.default_name = default_name
        self.kwargs = kwargs
        self._kwargs_processor = None
        self.__doc__ = docstring

    def register_to(self, oauth, name=None, **kwargs):
        """Creates a remote app and registers it."""
        kwargs = self._process_kwargs(
            name=(name or self.default_name), **kwargs)
        return oauth.remote_app(**kwargs)

    def create(self, oauth, **kwargs):
        """Creates a remote app only."""
        kwargs = self._process_kwargs(
            name=self.default_name, register=False, **kwargs)
        return oauth.remote_app(**kwargs)

    def kwargs_processor(self, fn):
        """Sets a function to process kwargs before creating any app."""
        self._kwargs_processor = fn
        if fn.__doc__:
            # appends docstring
            self.__doc__ = '%s\n%s' % (self.__doc__, fn.__doc__)
        return fn

    def _process_kwargs(self, **kwargs):
        final_kwargs = dict(self.kwargs)
        # merges with pre-defined kwargs
        final_kwargs.update(kwargs)
        # use name as app key
        final_kwargs.setdefault('app_key', final_kwargs['name'].upper())
        # processes by pre-defined function
        if self._kwargs_processor is not None:
            final_kwargs = self._kwargs_processor(**final_kwargs)
        return final_kwargs

douban = RemoteAppFactory('douban', {
    'base_url': 'https://api.douban.com/v2/',
    'access_token_url': 'https://www.douban.com/service/auth2/token',
    'authorize_url': 'https://www.douban.com/service/auth2/auth',
    'access_token_method': 'POST',
}, """The OAuth app for douban.com API.""")

@douban.kwargs_processor
def douban_kwargs_processor(**kwargs):
    """
    :param scope: optional. default: ['douban_basic_common'].
                  see also: http://developers.douban.com/wiki/?title=oauth2
    """
    # request_token_url
    kwargs.setdefault('request_token_url', None)
    # request_token_params
    scope = kwargs.pop('scope', ['douban_basic_common'])  # default scope
    if not isinstance(scope, basestring):
        scope = ','.join(scope)  # allows list-style scope
    request_token_params = kwargs.setdefault('request_token_params', {})
    request_token_params.setdefault('scope', scope)  # doesn't override exists
    return kwargs
<commit_msg>refine the docstring processing and add facebook, dropbox, github.<commit_after>class RemoteAppFactory(object):
    """The factory to create remote app and bind it to given extension.

    :param default_name: the default name which be used for registering.
    :param kwargs: the pre-defined kwargs.
    :param docstring: the docstring of factory.
    """

    def __init__(self, default_name, kwargs, docstring=''):
        assert 'name' not in kwargs
        assert 'register' not in kwargs
        self.default_name = default_name
        self.kwargs = kwargs
        self._kwargs_processor = None
        self.__doc__ = docstring.lstrip()

    def register_to(self, oauth, name=None, **kwargs):
        """Creates a remote app and registers it."""
        kwargs = self._process_kwargs(
            name=(name or self.default_name), **kwargs)
        return oauth.remote_app(**kwargs)

    def create(self, oauth, **kwargs):
        """Creates a remote app only."""
        kwargs = self._process_kwargs(
            name=self.default_name, register=False, **kwargs)
        return oauth.remote_app(**kwargs)

    def kwargs_processor(self, fn):
        """Sets a function to process kwargs before creating any app."""
        self._kwargs_processor = fn
        return fn

    def _process_kwargs(self, **kwargs):
        final_kwargs = dict(self.kwargs)
        # merges with pre-defined kwargs
        final_kwargs.update(kwargs)
        # use name as app key
        final_kwargs.setdefault('app_key', final_kwargs['name'].upper())
        # processes by pre-defined function
        if self._kwargs_processor is not None:
            final_kwargs = self._kwargs_processor(**final_kwargs)
        return final_kwargs

def make_scope_processor(default_scope):
    def processor(**kwargs):
        # request_token_params
        scope = kwargs.pop('scope', [default_scope])  # default scope
        if not isinstance(scope, basestring):
            scope = ','.join(scope)  # allows list-style scope
        request_token_params = kwargs.setdefault('request_token_params', {})
        request_token_params.setdefault('scope', scope)  # doesn't override
        return kwargs
    return processor

douban = RemoteAppFactory('douban', {
    'base_url': 'https://api.douban.com/v2/',
    'request_token_url': None,
    'access_token_url': 'https://www.douban.com/service/auth2/token',
    'authorize_url': 'https://www.douban.com/service/auth2/auth',
    'access_token_method': 'POST',
}, """
The OAuth app for douban.com API.

:param scope: optional. default: ['douban_basic_common'].
              see also: http://developers.douban.com/wiki/?title=oauth2
""")
douban.kwargs_processor(make_scope_processor('douban_basic_common'))

dropbox = RemoteAppFactory('dropbox', {
    'base_url': 'https://www.dropbox.com/1/',
    'request_token_url': None,
    'access_token_url': 'https://api.dropbox.com/1/oauth2/token',
    'authorize_url': 'https://www.dropbox.com/1/oauth2/authorize',
    'access_token_method': 'POST',
    'request_token_params': {},
}, """The OAuth app for Dropbox API.""")

facebook = RemoteAppFactory('facebook', {
    'request_token_params': {'scope': 'email'},
    'base_url': 'https://graph.facebook.com',
    'request_token_url': None,
    'access_token_url': '/oauth/access_token',
    'authorize_url': 'https://www.facebook.com/dialog/oauth',
}, """
The OAuth app for Facebook API.

:param scope: optional. default: ['email'].
""")
facebook.kwargs_processor(make_scope_processor('email'))

github = RemoteAppFactory('github', {
    'base_url': 'https://api.github.com/',
    'request_token_url': None,
    'access_token_method': 'POST',
    'access_token_url': 'https://github.com/login/oauth/access_token',
    'authorize_url': 'https://github.com/login/oauth/authorize',
}, """
The OAuth app for GitHub API.

:param scope: optional. default: ['user:email'].
""")
github.kwargs_processor(make_scope_processor('user:email'))
<|endoftext|>


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

from flask_rest_jsonapi.api import Api
from flask_rest_jsonapi.resource import ResourceList, ResourceDetail, ResourceRelationship
from flask_rest_jsonapi.querystring import QueryStringManager
from flask_rest_jsonapi.schema import compute_schema
from flask_rest_jsonapi.errors import jsonapi_errors
from flask_rest_jsonapi.exceptions import JsonApiException

__all__ = [
    'Api',
    'ResourceList',
    'ResourceDetail',
    'ResourceRelationship',
    'QueryStringManager',
    'compute_schema',
    'jsonapi_errors',
    'JsonApiException'
]
<commit_msg>update package init<commit_after># -*- coding: utf-8 -*-

from flask_rest_jsonapi.api import Api
from flask_rest_jsonapi.resource import ResourceList, ResourceDetail, ResourceRelationship
from flask_rest_jsonapi.exceptions import JsonApiException

__all__ = [
    'Api',
    'ResourceList',
    'ResourceDetail',
    'ResourceRelationship',
    'JsonApiException'
]
<|endoftext|>