<commit_before># -*- coding: utf-8 -*-
# Copyright (C) 2008-2011, Luis Pedro Coelho <luis@luispedro.org>
# vim: set ts=4 sts=4 sw=4 expandtab smartindent:
#
# License: MIT. See COPYING.MIT file in the milk distribution

from __future__ import division
from .classifier import normaliselabels
import numpy as np

__all__ = [
    'one_against_rest',
    'one_against_one',
    'one_against_rest_multi',
    ]

class one_against_rest(object):
    '''
    Implements one vs. rest classification strategy to transform
    a binary classifier into a multi-class classifier.

    classifier = one_against_rest(base)

    base must obey the classifier interface

    Example
    -------

    ::

        multi = one_against_rest(milk.supervised.simple_svm())
        model = multi.train(training_features,labels)
        print model.apply(testing_features)

    See Also
    --------
    one_against_one
    '''

    def __init__(self,base):
        self.base = base
        self.is_multi_class = True
        self.options = {}

    def set_option(self, k, v):
        self.options[k] = v

    def train(self, features, labels, normalisedlabels=False):
        labels, names = normaliselabels(labels)
        nclasses = labels.max() + 1
        models  = []
        for i in xrange(nclasses):
            for k,v in self.options.iteritems():
                self.base.set_option(k, v)
            model = self.base.train(features, (labels == i).astype(int), normalisedlabels=True)
            models.append(model)
        return one_against_rest_model(models, names)

class one_against_rest_model(object):
    def __init__(self, models, names):
        self.models = models
        self.nclasses = len(self.models)
        self.names = names

    def apply(self, feats):
        vals = np.array([c.apply(feats) for c in self.models])
        (idxs,) = np.where(vals)
        if len(idxs) == 1:
            (label,) = idxs
        elif len(idxs) == 0:
            label = 0
        else:
            label = idxs[0]
        return self.names[label]

class one_against_one(object):
    '''
    Implements one vs. one classification strategy to transform
    a binary classifier into a multi-class classifier.

    classifier = one_against_one(base)

    base must obey the classifier interface

    Example
    -------
    ::

        multi = one_against_one(milk.supervised.simple_svm())
        multi.train(training_features,labels)
        print multi.apply(testing_features)

    See Also
    --------
    one_against_rest
    '''

    def __init__(self, base):
        self.base = base
        self.is_multi_class = True
        self.options = {}

    def set_option(self, k, v):
        self.options[k] = v

    def train(self, features, labels, **kwargs):
        '''
        one_against_one.train(objs,labels)
        '''
        labels, names = normaliselabels(labels)
        features = np.asanyarray(features)
        nclasses = labels.max() + 1
        models = [ [None for i in xrange(nclasses)] for j in xrange(nclasses)]
        for i in xrange(nclasses):
            for j in xrange(i+1, nclasses):
                for k,v in self.options.iteritems():
                    self.base.set_option(k, v)
                idxs = (labels == i) | (labels == j)
                assert idxs.sum() > 0, 'milk.multi.one_against_one: Pair-wise classifier has no data'
                # Fixme: here I could add a Null model or something
                model = self.base.train(features[idxs], (labels[idxs]==i).astype(int), normalisedlabels=True)
                models[i][j] = model
        return one_against_one_model(models, names)

class one_against_one_model(object):
    def __init__(self, models, names):
        self.models = models
        self.names = names
        self.nclasses = len(models)

    def apply(self,feats):
        '''
        one_against_one.apply(objs)

        Classify one single object.
        '''
        nc = self.nclasses
        votes = np.zeros(nc)
        for i in xrange(nc):
            for j in xrange(i+1,nc):
                c = self.models[i][j].apply(feats)
                if c:
                    votes[i] += 1
                else:
                    votes[j] += 1
        return self.names[votes.argmax(0)]

class one_against_rest_multi_model(object):
    def __init__(self, models):
        self.models = models

    def apply(self, feats):
        return [lab for lab,model in self.models.iteritems() if model.apply(feats)]

class one_against_rest_multi(object):
    '''
    learner = one_against_rest_multi()
    model = learner.train(features, labels)
    classes = model.apply(f_test)

    This for multi-label problem (i.e., each instance can have more than one label).

    '''

    def __init__(self, base):
        self.base = base
        if hasattr(base, 'set_option'):
            self.set_option = base.set_option

    def train(self, features, labels, normalisedlabels=False):
        '''
        '''
        import operator
        all_labels = set()
        for ls in labels:
            all_labels.update(ls)
        models = {}
        for label in all_labels:
            models[label] = self.base.train(features, [(label in ls) for ls in labels])
        return one_against_rest_multi_model(models)

<commit_msg>ENH Support non-standard features<commit_after># -*- coding: utf-8 -*-
# Copyright (C) 2008-2011, Luis Pedro Coelho <luis@luispedro.org>
# vim: set ts=4 sts=4 sw=4 expandtab smartindent:
#
# License: MIT. See COPYING.MIT file in the milk distribution

from __future__ import division
from .classifier import normaliselabels
import numpy as np

__all__ = [
    'one_against_rest',
    'one_against_one',
    'one_against_rest_multi',
    ]

def _asanyarray(f):
    try:
        return np.asanyarray(f)
    except:
        return np.array(f, dtype=object)

class one_against_rest(object):
    '''
    Implements one vs. rest classification strategy to transform
    a binary classifier into a multi-class classifier.

    classifier = one_against_rest(base)

    base must obey the classifier interface

    Example
    -------

    ::

        multi = one_against_rest(milk.supervised.simple_svm())
        model = multi.train(training_features,labels)
        print model.apply(testing_features)

    See Also
    --------
    one_against_one
    '''

    def __init__(self,base):
        self.base = base
        self.is_multi_class = True
        self.options = {}

    def set_option(self, k, v):
        self.options[k] = v

    def train(self, features, labels, normalisedlabels=False):
        labels, names = normaliselabels(labels)
        nclasses = labels.max() + 1
        models  = []
        for i in xrange(nclasses):
            for k,v in self.options.iteritems():
                self.base.set_option(k, v)
            model = self.base.train(features, (labels == i).astype(int), normalisedlabels=True)
            models.append(model)
        return one_against_rest_model(models, names)

class one_against_rest_model(object):
    def __init__(self, models, names):
        self.models = models
        self.nclasses = len(self.models)
        self.names = names

    def apply(self, feats):
        vals = np.array([c.apply(feats) for c in self.models])
        (idxs,) = np.where(vals)
        if len(idxs) == 1:
            (label,) = idxs
        elif len(idxs) == 0:
            label = 0
        else:
            label = idxs[0]
        return self.names[label]

class one_against_one(object):
    '''
    Implements one vs. one classification strategy to transform
    a binary classifier into a multi-class classifier.

    classifier = one_against_one(base)

    base must obey the classifier interface

    Example
    -------
    ::

        multi = one_against_one(milk.supervised.simple_svm())
        multi.train(training_features,labels)
        print multi.apply(testing_features)

    See Also
    --------
    one_against_rest
    '''

    def __init__(self, base):
        self.base = base
        self.is_multi_class = True
        self.options = {}

    def set_option(self, k, v):
        self.options[k] = v

    def train(self, features, labels, **kwargs):
        '''
        one_against_one.train(objs,labels)
        '''
        labels, names = normaliselabels(labels)
        features = _asanyarray(features)
        nclasses = labels.max() + 1
        models = [ [None for i in xrange(nclasses)] for j in xrange(nclasses)]
        for i in xrange(nclasses):
            for j in xrange(i+1, nclasses):
                for k,v in self.options.iteritems():
                    self.base.set_option(k, v)
                idxs = (labels == i) | (labels == j)
                assert idxs.sum() > 0, 'milk.multi.one_against_one: Pair-wise classifier has no data'
                # Fixme: here I could add a Null model or something
                model = self.base.train(features[idxs], (labels[idxs]==i).astype(int), normalisedlabels=True)
                models[i][j] = model
        return one_against_one_model(models, names)

class one_against_one_model(object):
    def __init__(self, models, names):
        self.models = models
        self.names = names
        self.nclasses = len(models)

    def apply(self,feats):
        '''
        one_against_one.apply(objs)

        Classify one single object.
        '''
        nc = self.nclasses
        votes = np.zeros(nc)
        for i in xrange(nc):
            for j in xrange(i+1,nc):
                c = self.models[i][j].apply(feats)
                if c:
                    votes[i] += 1
                else:
                    votes[j] += 1
        return self.names[votes.argmax(0)]

class one_against_rest_multi_model(object):
    def __init__(self, models):
        self.models = models

    def apply(self, feats):
        return [lab for lab,model in self.models.iteritems() if model.apply(feats)]

class one_against_rest_multi(object):
    '''
    learner = one_against_rest_multi()
    model = learner.train(features, labels)
    classes = model.apply(f_test)

    This for multi-label problem (i.e., each instance can have more than one label).

    '''

    def __init__(self, base):
        self.base = base
        if hasattr(base, 'set_option'):
            self.set_option = base.set_option

    def train(self, features, labels, normalisedlabels=False):
        '''
        '''
        import operator
        all_labels = set()
        for ls in labels:
            all_labels.update(ls)
        models = {}
        for label in all_labels:
            models[label] = self.base.train(features, [(label in ls) for ls in labels])
        return one_against_rest_multi_model(models)

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Created on Thu Jun 14 15:07:29 2018

@author: Maciej Workiewicz
"""

print("""
----------------------------------------------------
Running Module 3: Decentralized local search
----------------------------------------------------
""")

import numpy as np
from os.path import expanduser  # new
import matplotlib.pyplot as plt

# Do not change these parameters----
N = 6  #                           |
i = 1000  # number of iterations   |
t = 50  # time periods             |
# ----------------------------------

'''
You can experiment with different setting of the following two variables:
which_imatrix - select 1 for random IM; 2 modular; 3 nearly-mod; 4 diagonal

K - set to 2 for which_imatrix = 2, 3, and 4. For which_imatrix=1 you can choose
    K from 0 (no interactions) to N-1 (maximum interactions)
'''

# You can change those
which_imatrix = 1  # | type of the interaction matrix
K = 2              # | number of interdependencies per decision variable
reorg = 50         # | reorganization: in which round we merge the two units
# --------------------

# *** 1. LOAD THE NK LANDSCAPE FILE *****************************************

file_name = expanduser("~")
NK_landscape = np.load(file_name + '\\NK_land_type_' + str(which_imatrix) +
                       '_K_' + str(K) + '_i_' + str(i) + '.npy')
# remember to change \\ into / on a Mac

power_key = np.power(2, np.arange(N - 1, -1, -1))

# *** 2. DECENTRALIZED LOCAL SEARCH *****************************************
'''
This simulation is based on the module 2.
'''
Output3 = np.zeros((i, t))

for i1 in np.arange(i):
    combination = np.random.binomial(1, 0.5, N)  # initial combination
    row = np.sum(combination*power_key)
    fitness = NK_landscape[i1, row, 2*N]
    max_fit = np.max(NK_landscape[i1, :, 2*N])  # use for normalization of perf
    min_fit = np.min(NK_landscape[i1, :, 2*N])  # ditto
    fitness_norm = (fitness - min_fit)/(max_fit - min_fit)
    for t1 in np.arange(t):
        Output3[i1, t1] = fitness_norm
        row = np.sum(combination*power_key)
        fitA = np.mean(NK_landscape[i1, row, N:int(N+N/2)])
        fitB = np.mean(NK_landscape[i1, row, int(N+N/2):int(N*2)])
        if t1 < reorg:  # for decentralized search
            '''
            The basic idea here is that we will split the vector of decision
            variables in two halfs {N0, N1, N2} and {N3, N4, N5}. We will then
            perform parallel search. We will locally search and compare
            resulting fitness changes separatelly.
            '''
            new_combination = combination.copy()
            new_combA = combination[:int(N/2)].copy()
            new_combB = combination[int(N/2):].copy()
            choice_varA = int(np.random.randint(0, int(N/2)))
            choice_varB = int(np.random.randint(0, int(N/2)))
            new_combA[choice_varA] = abs(new_combA[choice_varA] - 1)
            new_combB[choice_varB] = abs(new_combB[choice_varB] - 1)
            new_combination[:int(N/2)] = new_combA.copy()
            new_combination[int(N/2):] = new_combB.copy()

            row = np.sum(new_combination*power_key)  # find address for new comb
            new_fitA = np.mean(NK_landscape[i1, row, N:(int(N+N/2))])  # fitness goal 1
            new_fitB = np.mean(NK_landscape[i1, row, (int(N+N/2)):int(N*2)])  # fitness goal 2
            if new_fitA > fitA:
                combination[:int(N/2)] = new_combA.copy()
            if new_fitB > fitB:
                combination[int(N/2):] = new_combB.copy()
            row = int(np.sum(combination*power_key))
            fitness = np.mean(NK_landscape[i1, row, N:2*N])  # final fitness
        else:  # otherwise we centralize the local search
            new_combination = combination.copy()
            choice_var = np.random.randint(N)
            new_combination[choice_var] = abs(new_combination[choice_var] - 1)
            row = np.sum(new_combination*power_key)
            new_fitness = NK_landscape[i1, row, 2*N]
            if new_fitness > fitness:
                combination = new_combination.copy()
                fitness = new_fitness.copy()
        fitness_norm = (fitness - min_fit)/(max_fit - min_fit)

Fitness3 = np.mean(Output3, axis=0)

# *** 3. PLOT ***************************************************************

plt.figure(1, facecolor='white', figsize=(8, 6))
plt.plot(Fitness3, color='blue', linewidth=2, label='centr in t: ' + str(reorg))
plt.ylim(0.5, 1)
plt.legend(loc=4,prop={'size':10})
plt.title('Results of local search', size=12)
plt.xlabel('time periods', size=12)
plt.ylabel('fitness', size=12)

print('For IM=' + str(which_imatrix) + ' and reorg in round: ' + str(reorg))
print('Final fitness level for decentr/centr: ' + str(Fitness3[t-1]))

<commit_msg>Update to 3_decentralized<commit_after># -*- coding: utf-8 -*-
'''
Created on Thu Jun 14 15:07:29 2018

@author: Maciej Workiewicz

The code has been tested on Python 2.7 and 3.6 and higher
'''

print('''
----------------------------------------------------
Running Module 3: Decentralized local search
----------------------------------------------------
''')

import numpy as np
from os.path import expanduser  # new
import matplotlib.pyplot as plt
import csv

# Do not change these parameters---------------------------------------------
N = 6   # Keep at N=6
i = 1000  # number of iterations. Let's keep it at 1000 to save tim
t = 50   # time periods. Initially set to 50
# ---------------------------------------------------------------------------

'''
You can experiment with different setting of the following two variables:
which_imatrix - select 1 for random IM; 2 modular; 3 nearly-mod; 4 diagonal

K - set to 2 for which_imatrix = 2, 3, and 4. For which_imatrix=1 you can choose
    K from 0 (no interactions) to N-1 (maximum interactions)
'''

# You can change those
which_imatrix = 1  # | type of the interaction matrix
K = 2              # | number of interdependencies per decision variable
reorg = 25         # | reorganization: in which round we merge the two units
# --------------------

if which_imatrix >1:  # to avoid a common mistake
    K = 2

# *** 1. LOAD THE NK LANDSCAPE FILE *****************************************

file_name = expanduser("~")
NK_landscape = np.load(file_name + '\\NK_workshop\\NK_land_type_' + str(which_imatrix) +
                       '_K_' + str(K) + '_i_' + str(i) + '.npy')
# remember to change \\ into / on a Mac

power_key = np.power(2, np.arange(N - 1, -1, -1))

# *** 2. DECENTRALIZED LOCAL SEARCH *****************************************
'''
This simulation is based on the module 2.
'''
Output3 = np.zeros((i, t))

for i1 in np.arange(i):
    combination = np.random.binomial(1, 0.5, N)  # initial combination
    row = np.sum(combination*power_key)
    fitness = NK_landscape[i1, row, 2*N]
    max_fit = np.max(NK_landscape[i1, :, 2*N])  # use for normalization of perf
    min_fit = np.min(NK_landscape[i1, :, 2*N])  # ditto
    fitness_norm = (fitness - min_fit)/(max_fit - min_fit)
    for t1 in np.arange(t):
        Output3[i1, t1] = fitness_norm
        row = np.sum(combination*power_key)
        fitA = np.mean(NK_landscape[i1, row, N:int(N+N/2)])
        fitB = np.mean(NK_landscape[i1, row, int(N+N/2):int(N*2)])
        if t1 < reorg:  # for decentralized search
            '''
            The basic idea here is that we will split the vector of decision
            variables in two halfs {N0, N1, N2} and {N3, N4, N5}. We will then
            perform parallel search. We will locally search and compare
            resulting fitness changes separatelly.
            '''
            new_combination = combination.copy()
            new_combA = combination[:int(N/2)].copy()
            new_combB = combination[int(N/2):].copy()
            choice_varA = np.random.randint(0, int(N/2))
            choice_varB = np.random.randint(0, int(N/2))
            new_combA[choice_varA] = abs(new_combA[choice_varA] - 1)
            new_combB[choice_varB] = abs(new_combB[choice_varB] - 1)
            new_combination[:int(N/2)] = new_combA.copy()
            new_combination[int(N/2):] = new_combB.copy()

            row = np.sum(new_combination*power_key)  # find address for new comb
            new_fitA = np.mean(NK_landscape[i1, row, N:(int(N+N/2))])  # fitness goal 1
            new_fitB = np.mean(NK_landscape[i1, row, (int(N+N/2)):int(N*2)])  # fitness goal 2
            if new_fitA > fitA:
                combination[:int(N/2)] = new_combA.copy()
            if new_fitB > fitB:
                combination[int(N/2):] = new_combB.copy()
            row = int(np.sum(combination*power_key))
            fitness = np.mean(NK_landscape[i1, row, N:2*N])  # final fitness
        else:  # otherwise we centralize the local search
            new_combination = combination.copy()
            choice_var = np.random.randint(N)
            new_combination[choice_var] = abs(new_combination[choice_var] - 1)
            row = np.sum(new_combination*power_key)
            new_fitness = NK_landscape[i1, row, 2*N]
            if new_fitness > fitness:
                combination = new_combination.copy()
                fitness = new_fitness.copy()
        fitness_norm = (fitness - min_fit)/(max_fit - min_fit)

Fitness3 = np.mean(Output3, axis=0)

# *** 3. PLOT ***************************************************************

plt.figure(1, facecolor='white', figsize=(8, 6), dpi=150)  # for screens with
#          higher resolution change dpi to 150 or 200. For normal use 75.
plt.plot(Fitness3, color='blue', linewidth=2, label='centr in t=' + str(reorg))
plt.ylim(0.5, 1)
plt.legend(loc=4,prop={'size':10})
plt.title('Results of local search', size=12)
plt.xlabel('time periods', size=12)
plt.ylabel('fitness', size=12)

print('For IM=' + str(which_imatrix) + ' and reorg in round: ' + str(reorg))
print('Final fitness level for decentr/centr: ' + str(Fitness3[t-1]))
print('Avg. cumulative fitness level(decentr): ' + str(np.mean(Fitness3[:t-1])))

# END OF LINE
<|endoftext|>


<commit_before>import re
import logging as log
from collections import namedtuple

import marge.gitlab as gitlab

GET = gitlab.GET
POST = gitlab.POST

class Api(gitlab.Api):
    def __init__(self, gitlab_url, auth_token, initial_state):
        super(Api, self).__init__(gitlab_url, auth_token)

        self._transitions = {}
        self.state = initial_state
        self.notes = []

    def call(self, command, sudo=None):
        log.info(
            'CALL: %s%s @ %s',
            'sudo %s ' % sudo if sudo is not None else '',
            command,
            self.state,
        )
        try:
            response, next_state = self._find(command, sudo)
        except KeyError:
            page = command.args.get('page')
            if page == 0:
                no_page_args = dict((k, v) for k, v in args.items() if k not in ['page', 'per_page'])
                try:
                    return self.call(command._replace(args=no_page_args))
                except MockedEndpointNotFound:
                    pass  # raise the right exception below
            elif page:  # page is not None
                try:
                    # only return an empty list if the command exists
                    self.call(command.for_page(0))
                except MockedEndpointNotFound:
                    pass  # raise the right exception below
                else:
                    return []

            raise MockedEndpointNotFound(command, sudo, self.state)
        else:
            if next_state:
                self.state = next_state

            return response()

    def _find(self, command, sudo):
        more_specific = self._transitions.get(_key(command, sudo, self.state))
        return more_specific or self._transitions[_key(command, sudo, None)]

    def add_transition(self, command, response, sudo=None, from_state=None, to_state=None):
        from_states = from_state if type(from_state) == list else [from_state]

        for from_state in from_states:
            show_from = '*' if from_state is None else repr(from_state)
            log.info(
                'REGISTERING %s%s from %s to %s',
                'sudo %s ' % sudo if sudo is not None else '',
                command,
                show_from,
                show_from if to_state is None else repr(to_state),
            )
            self._transitions[_key(command, sudo, from_state)] = (response, to_state)

    def add_resource(self, path, info, sudo=None, from_state=None, to_state=None):
        self.add_transition(GET(path.format(attrs(info))), Ok(info), sudo, from_state, to_state)

    def add_user(self, info, is_current=False, sudo=None, from_state=None, to_state=None):
        self.add_resource('/users/{0.id}', info, sudo, from_state, to_state)
        if is_current:
            self.add_resource('/user', info, sudo, from_state, to_state)

    def add_project(self, info, sudo=None, from_state=None, to_state=None):
        self.add_resource('/projects/{0.id}', info, sudo, from_state, to_state)
        self.add_transition(
            GET('/projects/{0.id}/merge_requests'.format(attrs(info))),
            List('/projects/\d+/merge_requests/\d+$', self),
            sudo, from_state, to_state,
        )

    def add_merge_request(self, info, sudo=None, from_state=None, to_state=None):
        self.add_resource('/projects/{0.project_id}/merge_requests/{0.iid}', info, sudo, from_state, to_state)

    def add_commit(self, project_id, info, sudo=None, from_state=None, to_state=None):
        path = '/projects/%s/repository/commits/{0.id}' % project_id
        self.add_resource(path, info, sudo, from_state, to_state)

    def add_approvals(self, info, sudo=None, from_state=None, to_state=None):
        path = '/projects/{0.project_id}/merge_requests/{0.iid}/approvals'
        self.add_resource(path, info, sudo, from_state, to_state)

    def expected_note(self, merge_request, note, sudo=None, from_state=None, to_state=None):
        self.add_transition(
            POST('/projects/{0.project_id}/merge_requests/{0.iid}/notes'.format(attrs(merge_request)), args={'body': note}),
            LeaveNote(note, self),
            sudo, from_state, to_state,
        )

def _key(command, sudo, state):
    return command._replace(args=frozenset(command.args.items())), sudo, state

class Ok(namedtuple('Ok', 'result')):
    def __call__(self):
        return self.result

class Error(namedtuple('Error', 'exc')):
    def __call__(self):
        raise self.exc

class List(namedtuple('List', 'prefix api')):
    def _call__(self):
        candidates = (
            command for command, _ in self.api._transitions.keys()
            if type(command) == GET and re.match(self.prefix, command.endpoint)
        )

        results = []
        for command in candidates:
            try:
                results.append(self.api.call(command))
            except MockedEndpointNotFound:
                pass

        return results

class LeaveNote(namedtuple('LeaveNote', 'note api')):
    def __call__(self):
        self.api.notes.append(self.note)
        return {}

class MockedEndpointNotFound(Exception):
    pass

class attrs(object):
    def __init__(self, d):
        self.__dict__.update(d)
<commit_msg>gitlab_api_mock: fix non-existing variable access<commit_after>import re
import logging as log
from collections import namedtuple

import marge.gitlab as gitlab

GET = gitlab.GET
POST = gitlab.POST

class Api(gitlab.Api):
    def __init__(self, gitlab_url, auth_token, initial_state):
        super(Api, self).__init__(gitlab_url, auth_token)

        self._transitions = {}
        self.state = initial_state
        self.notes = []

    def call(self, command, sudo=None):
        log.info(
            'CALL: %s%s @ %s',
            'sudo %s ' % sudo if sudo is not None else '',
            command,
            self.state,
        )
        try:
            response, next_state = self._find(command, sudo)
        except KeyError:
            page = command.args.get('page')
            if page == 0:
                no_page_args = dict((k, v) for k, v in command.args.items() if k not in ['page', 'per_page'])
                try:
                    return self.call(command._replace(args=no_page_args))
                except MockedEndpointNotFound:
                    pass  # raise the right exception below
            elif page:  # page is not None
                try:
                    # only return an empty list if the command exists
                    self.call(command.for_page(0))
                except MockedEndpointNotFound:
                    pass  # raise the right exception below
                else:
                    return []

            raise MockedEndpointNotFound(command, sudo, self.state)
        else:
            if next_state:
                self.state = next_state

            return response()

    def _find(self, command, sudo):
        more_specific = self._transitions.get(_key(command, sudo, self.state))
        return more_specific or self._transitions[_key(command, sudo, None)]

    def add_transition(self, command, response, sudo=None, from_state=None, to_state=None):
        from_states = from_state if type(from_state) == list else [from_state]

        for from_state in from_states:
            show_from = '*' if from_state is None else repr(from_state)
            log.info(
                'REGISTERING %s%s from %s to %s',
                'sudo %s ' % sudo if sudo is not None else '',
                command,
                show_from,
                show_from if to_state is None else repr(to_state),
            )
            self._transitions[_key(command, sudo, from_state)] = (response, to_state)

    def add_resource(self, path, info, sudo=None, from_state=None, to_state=None):
        self.add_transition(GET(path.format(attrs(info))), Ok(info), sudo, from_state, to_state)

    def add_user(self, info, is_current=False, sudo=None, from_state=None, to_state=None):
        self.add_resource('/users/{0.id}', info, sudo, from_state, to_state)
        if is_current:
            self.add_resource('/user', info, sudo, from_state, to_state)

    def add_project(self, info, sudo=None, from_state=None, to_state=None):
        self.add_resource('/projects/{0.id}', info, sudo, from_state, to_state)
        self.add_transition(
            GET('/projects/{0.id}/merge_requests'.format(attrs(info))),
            List('/projects/\d+/merge_requests/\d+$', self),
            sudo, from_state, to_state,
        )

    def add_merge_request(self, info, sudo=None, from_state=None, to_state=None):
        self.add_resource('/projects/{0.project_id}/merge_requests/{0.iid}', info, sudo, from_state, to_state)

    def add_commit(self, project_id, info, sudo=None, from_state=None, to_state=None):
        path = '/projects/%s/repository/commits/{0.id}' % project_id
        self.add_resource(path, info, sudo, from_state, to_state)

    def add_approvals(self, info, sudo=None, from_state=None, to_state=None):
        path = '/projects/{0.project_id}/merge_requests/{0.iid}/approvals'
        self.add_resource(path, info, sudo, from_state, to_state)

    def expected_note(self, merge_request, note, sudo=None, from_state=None, to_state=None):
        self.add_transition(
            POST('/projects/{0.project_id}/merge_requests/{0.iid}/notes'.format(attrs(merge_request)), args={'body': note}),
            LeaveNote(note, self),
            sudo, from_state, to_state,
        )

def _key(command, sudo, state):
    return command._replace(args=frozenset(command.args.items())), sudo, state

class Ok(namedtuple('Ok', 'result')):
    def __call__(self):
        return self.result

class Error(namedtuple('Error', 'exc')):
    def __call__(self):
        raise self.exc

class List(namedtuple('List', 'prefix api')):
    def _call__(self):
        candidates = (
            command for command, _ in self.api._transitions.keys()
            if type(command) == GET and re.match(self.prefix, command.endpoint)
        )

        results = []
        for command in candidates:
            try:
                results.append(self.api.call(command))
            except MockedEndpointNotFound:
                pass

        return results

class LeaveNote(namedtuple('LeaveNote', 'note api')):
    def __call__(self):
        self.api.notes.append(self.note)
        return {}

class MockedEndpointNotFound(Exception):
    pass

class attrs(object):
    def __init__(self, d):
        self.__dict__.update(d)
<|endoftext|>


<commit_before>"""
Dropbox OAuth1 backend, docs at:
    http://psa.matiasaguirre.net/docs/backends/dropbox.html
"""
from social.backends.oauth import BaseOAuth1

class DropboxOAuth(BaseOAuth1):
    """Dropbox OAuth authentication backend"""
    name = 'dropbox'
    ID_KEY = 'uid'
    AUTHORIZATION_URL = 'https://www.dropbox.com/1/oauth/authorize'
    REQUEST_TOKEN_URL = 'https://api.dropbox.com/1/oauth/request_token'
    REQUEST_TOKEN_METHOD = 'POST'
    ACCESS_TOKEN_URL = 'https://api.dropbox.com/1/oauth/access_token'
    ACCESS_TOKEN_METHOD = 'POST'
    REDIRECT_URI_PARAMETER_NAME = 'oauth_callback'
    EXTRA_DATA = [
        ('id', 'id'),
        ('expires', 'expires')
    ]

    def get_user_details(self, response):
        """Return user details from Dropbox account"""
        return {'username': str(response.get('uid')),
                'email': response.get('email'),
                'first_name': response.get('display_name')}

    def user_data(self, access_token, *args, **kwargs):
        """Loads user data from service"""
        return self.get_json('https://api.dropbox.com/1/account/info',
                             auth=self.oauth_auth(access_token))
<commit_msg>Adding Dropbox OAuth2 Support.<commit_after>"""
Dropbox OAuth1 backend, docs at:
    http://psa.matiasaguirre.net/docs/backends/dropbox.html
"""
from social.backends.oauth import BaseOAuth1, BaseOAuth2

class DropboxOAuth(BaseOAuth1):
    """Dropbox OAuth authentication backend"""
    name = 'dropbox'
    ID_KEY = 'uid'
    AUTHORIZATION_URL = 'https://www.dropbox.com/1/oauth/authorize'
    REQUEST_TOKEN_URL = 'https://api.dropbox.com/1/oauth/request_token'
    REQUEST_TOKEN_METHOD = 'POST'
    ACCESS_TOKEN_URL = 'https://api.dropbox.com/1/oauth/access_token'
    ACCESS_TOKEN_METHOD = 'POST'
    REDIRECT_URI_PARAMETER_NAME = 'oauth_callback'
    EXTRA_DATA = [
        ('id', 'id'),
        ('expires', 'expires')
    ]

    def get_user_details(self, response):
        """Return user details from Dropbox account"""
        return {'username': str(response.get('uid')),
                'email': response.get('email'),
                'first_name': response.get('display_name')}

    def user_data(self, access_token, *args, **kwargs):
        """Loads user data from service"""
        return self.get_json('https://api.dropbox.com/1/account/info',
                             auth=self.oauth_auth(access_token))

class DropboxOAuth2(BaseOAuth2):
    name = 'dropbox-oauth2'
    ID_KEY = 'uid'
    AUTHORIZATION_URL = 'https://www.dropbox.com/1/oauth2/authorize'
    ACCESS_TOKEN_URL = 'https://api.dropbox.com/1/oauth2/token'
    ACCESS_TOKEN_METHOD = 'POST'
    REDIRECT_STATE = False
    EXTRA_DATA = [
        ('uid', 'username'),
    ]

    def get_user_details(self, response):
        """Return user details from Dropbox account"""
        return {'username': str(response.get('uid')),
                'email': response.get('email'),
                'first_name': response.get('display_name')}

    def user_data(self, access_token, *args, **kwargs):
        """Loads user data from service"""
        return self.get_json(
            'https://api.dropbox.com/1/account/info',
            headers={'Authorization': 'Bearer {0}'.format(access_token)}
        )
<|endoftext|>


<commit_before>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  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 robot import utils
from robot.common import BaseTestSuite, BaseTestCase
from robot.parsing import TestSuiteData
from robot.errors import ExecutionFailed
from robot.variables import GLOBAL_VARIABLES
from robot.output import LOGGER

from fixture import Setup, Teardown
from timeouts import TestTimeout
from keywords import KeywordFactory
from namespace import Namespace
from userkeyword import UserLibrary

def TestSuite(datasources, settings):
    suitedata = TestSuiteData(datasources, settings['SuiteNames'])
    suite = RunnableTestSuite(suitedata)
    suite.set_options(settings)
    return suite

class RunnableTestSuite(BaseTestSuite):

    _exit_on_failure_error = ('Critical failure occurred and ExitOnFailure '
                              'option is in use')

    def __init__(self, data, testdefaults=None, parent=None):
        BaseTestSuite.__init__(self, data.name, data.source, parent)
        self.variables = GLOBAL_VARIABLES.copy()
        self.variables.set_from_variable_table(data.variables)
        self.source = data.source
        self.doc = data.doc or ''
        self.metadata = data.metadata
        self.imports = data.imports
        self.user_keywords = UserLibrary(data.user_keywords)
        self.setup = data.suite_setup or []
        self.teardown = data.suite_teardown or []
        if not testdefaults:
            testdefaults = _TestCaseDefaults()
        testdefaults.add_defaults(data)
        for suite in data.suites:
            RunnableTestSuite(suite, testdefaults.copy(), parent=self)
        for test in data.tests:
            RunnableTestCase(test, testdefaults, parent=self)
        self._exit_on_failure = False

    def run(self, output, parent=None, error=None):
        self.status = 'RUNNING'
        self.starttime = utils.get_timestamp()
        self.namespace = Namespace(self, parent)
        self.namespace.variables['${SUITE_NAME}'] = self.longname
        init_err = self._init_suite(self.namespace.variables)
        output.start_suite(self)
        setup_err = self._run_fixture(self.setup, output, error, init_err)
        child_err = self._get_child_error(error, init_err, setup_err)
        for suite in self.suites:
            suite.run(output, self, child_err)
            if self._exit_on_failure and not child_err and \
                   suite.critical_stats.failed:
                child_err = self._exit_on_failure_error
        executed_tests = []
        for test in self.tests:
            normname = utils.normalize(test.name)
            if normname in executed_tests:
                LOGGER.warn("Multiple test cases with name '%s' executed in "
                            "test suite '%s'"% (test.name, self.longname))
            executed_tests.append(normname)
            test.run(output, self.namespace, child_err)
            if self._exit_on_failure and not child_err and \
                    test.status == 'FAIL' and test.critical == 'yes':
                child_err = self._exit_on_failure_error
            self._set_prev_test_variables(self.namespace.variables, test)
        self.set_status()
        self.message = self._get_my_error(error, init_err, setup_err)
        self.namespace.variables['${SUITE_STATUS}'] = self.status
        self.namespace.variables['${SUITE_MESSAGE}'] = self.get_full_message()
        td_err = self._run_fixture(self.teardown, output, error, init_err)
        if td_err:
            self.suite_teardown_failed('Suite teardown failed:\n%s' % td_err)
        self.endtime = utils.get_timestamp()
        self.elapsedtime = utils.get_elapsed_time(self.starttime, self.endtime)
        self._set_prev_test_variables(GLOBAL_VARIABLES,
                                      varz=self.namespace.variables)
        output.end_suite(self)
        self.namespace.end_suite()

    def _init_suite(self, varz):
        errors = []
        self.doc = varz.replace_meta('Documentation', self.doc, errors)
        self.setup = Setup(varz.replace_meta('Setup', self.setup, errors))
        self.teardown = Teardown(
            varz.replace_meta('Teardown', self.teardown, errors))
        for name, value in self.metadata.items():
            self.metadata[name] = varz.replace_meta(name, value, errors)
        if errors:
            return 'Suite initialization failed:\n%s' % '\n'.join(errors)

    def _get_child_error(self, error, init_error, setup_error):
        if error:
            return error
        if init_error:
            return 'Initialization of the parent suite failed.'
        if setup_error:
            return 'Setup of the parent suite failed.'
        return None

    def _get_my_error(self, error, init_error, setup_error):
        if error:
            return error
        if init_error:
            return init_error
        if setup_error:
            return 'Suite setup failed:\n%s' % setup_error
        return ''

    def _run_fixture(self, fixture, output, error, init_error):
        if fixture and not (error or init_error):
            try:
                fixture.run(output, self.namespace)
            except ExecutionFailed:
                return utils.get_error_message()

    def _set_prev_test_variables(self, destination, test=None, varz=None):
        if test is not None:
            name, status, message = test.name, test.status, test.message
        else:
            name, status, message = varz['${PREV_TEST_NAME}'], \
                    varz['${PREV_TEST_STATUS}'], varz['${PREV_TEST_MESSAGE}']
        destination['${PREV_TEST_NAME}'] = name
        destination['${PREV_TEST_STATUS}'] = status
        destination['${PREV_TEST_MESSAGE}'] = message

class RunnableTestCase(BaseTestCase):

    def __init__(self, data, defaults, parent):
        BaseTestCase.__init__(self, data.name, parent)
        self.doc = data.doc or ''
        self.setup = utils.get_not_none(data.setup, defaults.test_setup)
        self.teardown = utils.get_not_none(data.teardown,
                                           defaults.test_teardown)
        self.tags = defaults.force_tags \
                    + utils.get_not_none(data.tags, defaults.default_tags)
        self.timeout = utils.get_not_none(data.timeout, defaults.test_timeout)
        self.keywords = [ KeywordFactory(kw) for kw in data.keywords ]

    def run(self, output, namespace, error=None):
        self.status = 'RUNNING'
        self.starttime = utils.get_timestamp()
        init_err = self._init_test(namespace.variables)
        error = error or init_err
        namespace.start_test(self)
        output.start_test(self)
        if not error:
            self._run(output, namespace)
        else:
            self.status = 'FAIL'
            self.message = error
        self.endtime = utils.get_timestamp()
        self.elapsedtime = utils.get_elapsed_time(self.starttime, self.endtime)
        output.end_test(self)
        namespace.end_test()

    def _init_test(self, varz):
        errors = []
        self.doc = varz.replace_meta('Documentation', self.doc, errors)
        self.setup = Setup(varz.replace_meta('Setup', self.setup, errors))
        self.teardown = Teardown(
            varz.replace_meta('Teardown', self.teardown, errors))
        self.tags = utils.normalize_tags(
            varz.replace_meta('Tags', self.tags, errors))
        self.timeout = TestTimeout(
            *varz.replace_meta('Timeout', self.timeout, errors))
        if errors:
            return 'Test case initialization failed:\n%s' % '\n'.join(errors)
        if not self.keywords:
            return 'Test case contains no keywords'

    def _run(self, output, namespace):
        namespace.variables['${TEST_NAME}'] = self.name
        namespace.variables['@{TEST_TAGS}'] = self.tags
        self.timeout.start()
        setup_err = self._run_fixture(self.setup, output, namespace)
        kw_err = self._run_keywords(output, namespace, setup_err)
        self.message = self._get_message(setup_err, kw_err)
        self.status = self.message == '' and 'PASS' or 'FAIL'
        namespace.variables['${TEST_STATUS}'] = self.status
        namespace.variables['${TEST_MESSAGE}'] = self.message
        td_err = self._run_fixture(self.teardown, output, namespace)
        if td_err:
            self.message = self._get_teardown_error(self.message, td_err)
            self.status = 'FAIL'
        if self.status == 'PASS' and self.timeout.timed_out():
            self.status = 'FAIL'
            self.message = self.timeout.get_message()

    def _run_fixture(self, fixture, output, namespace):
        if fixture:
            try:
                fixture.run(output, namespace)
            except ExecutionFailed:
                return utils.get_error_message()

    def _run_keywords(self, output, namespace, setup_err):
        if not setup_err:
            for kw in self.keywords:
                try:
                    kw.run(output, namespace)
                except ExecutionFailed:
                    return utils.get_error_message()

    def _get_message(self, setup_err, kw_err):
        if setup_err:
            return 'Setup failed:\n%s' % setup_err
        return kw_err or ''

    def _get_teardown_error(self, message, teardown_err):
        if message == '':
            return 'Teardown failed:\n%s' % teardown_err
        return '%s\n\nAlso teardown failed:\n%s' % (message, teardown_err)

class _TestCaseDefaults:

    def __init__(self):
        self.force_tags = []
        self.default_tags = []
        self.test_setup = []
        self.test_teardown = []
        self.test_timeout = []

    def add_defaults(self, suite):
        if suite.force_tags:
            self.force_tags.extend(suite.force_tags)
        if suite.default_tags:
            self.default_tags = suite.default_tags
        if suite.test_setup:
            self.test_setup = suite.test_setup
        if suite.test_teardown:
            self.test_teardown = suite.test_teardown
        if suite.test_timeout:
            self.test_timeout = suite.test_timeout

    def copy(self):
        copy = _TestCaseDefaults()
        copy.force_tags = self.force_tags[:]
        copy.default_tags = self.default_tags[:]
        copy.test_setup = self.test_setup[:]
        copy.test_teardown = self.test_teardown[:]
        copy.test_timeout = self.test_timeout[:]
        return copy
<commit_msg>Implementation for ${suite source} variable<commit_after>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  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 robot import utils
from robot.common import BaseTestSuite, BaseTestCase
from robot.parsing import TestSuiteData
from robot.errors import ExecutionFailed
from robot.variables import GLOBAL_VARIABLES
from robot.output import LOGGER

from fixture import Setup, Teardown
from timeouts import TestTimeout
from keywords import KeywordFactory
from namespace import Namespace
from userkeyword import UserLibrary

def TestSuite(datasources, settings):
    suitedata = TestSuiteData(datasources, settings['SuiteNames'])
    suite = RunnableTestSuite(suitedata)
    suite.set_options(settings)
    return suite

class RunnableTestSuite(BaseTestSuite):

    _exit_on_failure_error = ('Critical failure occurred and ExitOnFailure '
                              'option is in use')

    def __init__(self, data, testdefaults=None, parent=None):
        BaseTestSuite.__init__(self, data.name, data.source, parent)
        self.variables = GLOBAL_VARIABLES.copy()
        self.variables.set_from_variable_table(data.variables)
        self.source = data.source
        self.doc = data.doc or ''
        self.metadata = data.metadata
        self.imports = data.imports
        self.user_keywords = UserLibrary(data.user_keywords)
        self.setup = data.suite_setup or []
        self.teardown = data.suite_teardown or []
        if not testdefaults:
            testdefaults = _TestCaseDefaults()
        testdefaults.add_defaults(data)
        for suite in data.suites:
            RunnableTestSuite(suite, testdefaults.copy(), parent=self)
        for test in data.tests:
            RunnableTestCase(test, testdefaults, parent=self)
        self._exit_on_failure = False

    def run(self, output, parent=None, error=None):
        self.status = 'RUNNING'
        self.starttime = utils.get_timestamp()
        self.namespace = Namespace(self, parent)
        self.namespace.variables['${SUITE_NAME}'] = self.longname
        self.namespace.variables['${SUITE_SOURCE}'] = self.source
        init_err = self._init_suite(self.namespace.variables)
        output.start_suite(self)
        setup_err = self._run_fixture(self.setup, output, error, init_err)
        child_err = self._get_child_error(error, init_err, setup_err)
        for suite in self.suites:
            suite.run(output, self, child_err)
            if self._exit_on_failure and not child_err and \
                   suite.critical_stats.failed:
                child_err = self._exit_on_failure_error
        executed_tests = []
        for test in self.tests:
            normname = utils.normalize(test.name)
            if normname in executed_tests:
                LOGGER.warn("Multiple test cases with name '%s' executed in "
                            "test suite '%s'"% (test.name, self.longname))
            executed_tests.append(normname)
            test.run(output, self.namespace, child_err)
            if self._exit_on_failure and not child_err and \
                    test.status == 'FAIL' and test.critical == 'yes':
                child_err = self._exit_on_failure_error
            self._set_prev_test_variables(self.namespace.variables, test)
        self.set_status()
        self.message = self._get_my_error(error, init_err, setup_err)
        self.namespace.variables['${SUITE_STATUS}'] = self.status
        self.namespace.variables['${SUITE_MESSAGE}'] = self.get_full_message()
        td_err = self._run_fixture(self.teardown, output, error, init_err)
        if td_err:
            self.suite_teardown_failed('Suite teardown failed:\n%s' % td_err)
        self.endtime = utils.get_timestamp()
        self.elapsedtime = utils.get_elapsed_time(self.starttime, self.endtime)
        self._set_prev_test_variables(GLOBAL_VARIABLES,
                                      varz=self.namespace.variables)
        output.end_suite(self)
        self.namespace.end_suite()

    def _init_suite(self, varz):
        errors = []
        self.doc = varz.replace_meta('Documentation', self.doc, errors)
        self.setup = Setup(varz.replace_meta('Setup', self.setup, errors))
        self.teardown = Teardown(
            varz.replace_meta('Teardown', self.teardown, errors))
        for name, value in self.metadata.items():
            self.metadata[name] = varz.replace_meta(name, value, errors)
        if errors:
            return 'Suite initialization failed:\n%s' % '\n'.join(errors)

    def _get_child_error(self, error, init_error, setup_error):
        if error:
            return error
        if init_error:
            return 'Initialization of the parent suite failed.'
        if setup_error:
            return 'Setup of the parent suite failed.'
        return None

    def _get_my_error(self, error, init_error, setup_error):
        if error:
            return error
        if init_error:
            return init_error
        if setup_error:
            return 'Suite setup failed:\n%s' % setup_error
        return ''

    def _run_fixture(self, fixture, output, error, init_error):
        if fixture and not (error or init_error):
            try:
                fixture.run(output, self.namespace)
            except ExecutionFailed:
                return utils.get_error_message()

    def _set_prev_test_variables(self, destination, test=None, varz=None):
        if test is not None:
            name, status, message = test.name, test.status, test.message
        else:
            name, status, message = varz['${PREV_TEST_NAME}'], \
                    varz['${PREV_TEST_STATUS}'], varz['${PREV_TEST_MESSAGE}']
        destination['${PREV_TEST_NAME}'] = name
        destination['${PREV_TEST_STATUS}'] = status
        destination['${PREV_TEST_MESSAGE}'] = message

class RunnableTestCase(BaseTestCase):

    def __init__(self, data, defaults, parent):
        BaseTestCase.__init__(self, data.name, parent)
        self.doc = data.doc or ''
        self.setup = utils.get_not_none(data.setup, defaults.test_setup)
        self.teardown = utils.get_not_none(data.teardown,
                                           defaults.test_teardown)
        self.tags = defaults.force_tags \
                    + utils.get_not_none(data.tags, defaults.default_tags)
        self.timeout = utils.get_not_none(data.timeout, defaults.test_timeout)
        self.keywords = [ KeywordFactory(kw) for kw in data.keywords ]

    def run(self, output, namespace, error=None):
        self.status = 'RUNNING'
        self.starttime = utils.get_timestamp()
        init_err = self._init_test(namespace.variables)
        error = error or init_err
        namespace.start_test(self)
        output.start_test(self)
        if not error:
            self._run(output, namespace)
        else:
            self.status = 'FAIL'
            self.message = error
        self.endtime = utils.get_timestamp()
        self.elapsedtime = utils.get_elapsed_time(self.starttime, self.endtime)
        output.end_test(self)
        namespace.end_test()

    def _init_test(self, varz):
        errors = []
        self.doc = varz.replace_meta('Documentation', self.doc, errors)
        self.setup = Setup(varz.replace_meta('Setup', self.setup, errors))
        self.teardown = Teardown(
            varz.replace_meta('Teardown', self.teardown, errors))
        self.tags = utils.normalize_tags(
            varz.replace_meta('Tags', self.tags, errors))
        self.timeout = TestTimeout(
            *varz.replace_meta('Timeout', self.timeout, errors))
        if errors:
            return 'Test case initialization failed:\n%s' % '\n'.join(errors)
        if not self.keywords:
            return 'Test case contains no keywords'

    def _run(self, output, namespace):
        namespace.variables['${TEST_NAME}'] = self.name
        namespace.variables['@{TEST_TAGS}'] = self.tags
        self.timeout.start()
        setup_err = self._run_fixture(self.setup, output, namespace)
        kw_err = self._run_keywords(output, namespace, setup_err)
        self.message = self._get_message(setup_err, kw_err)
        self.status = self.message == '' and 'PASS' or 'FAIL'
        namespace.variables['${TEST_STATUS}'] = self.status
        namespace.variables['${TEST_MESSAGE}'] = self.message
        td_err = self._run_fixture(self.teardown, output, namespace)
        if td_err:
            self.message = self._get_teardown_error(self.message, td_err)
            self.status = 'FAIL'
        if self.status == 'PASS' and self.timeout.timed_out():
            self.status = 'FAIL'
            self.message = self.timeout.get_message()

    def _run_fixture(self, fixture, output, namespace):
        if fixture:
            try:
                fixture.run(output, namespace)
            except ExecutionFailed:
                return utils.get_error_message()

    def _run_keywords(self, output, namespace, setup_err):
        if not setup_err:
            for kw in self.keywords:
                try:
                    kw.run(output, namespace)
                except ExecutionFailed:
                    return utils.get_error_message()

    def _get_message(self, setup_err, kw_err):
        if setup_err:
            return 'Setup failed:\n%s' % setup_err
        return kw_err or ''

    def _get_teardown_error(self, message, teardown_err):
        if message == '':
            return 'Teardown failed:\n%s' % teardown_err
        return '%s\n\nAlso teardown failed:\n%s' % (message, teardown_err)

class _TestCaseDefaults:

    def __init__(self):
        self.force_tags = []
        self.default_tags = []
        self.test_setup = []
        self.test_teardown = []
        self.test_timeout = []

    def add_defaults(self, suite):
        if suite.force_tags:
            self.force_tags.extend(suite.force_tags)
        if suite.default_tags:
            self.default_tags = suite.default_tags
        if suite.test_setup:
            self.test_setup = suite.test_setup
        if suite.test_teardown:
            self.test_teardown = suite.test_teardown
        if suite.test_timeout:
            self.test_timeout = suite.test_timeout

    def copy(self):
        copy = _TestCaseDefaults()
        copy.force_tags = self.force_tags[:]
        copy.default_tags = self.default_tags[:]
        copy.test_setup = self.test_setup[:]
        copy.test_teardown = self.test_teardown[:]
        copy.test_timeout = self.test_timeout[:]
        return copy
<|endoftext|>


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

from django.utils.functional import SimpleLazyObject

from .models import SiteUser

# add 'social_login.middleware.SocialLoginUser' in MIDDLEWARE_CLASSES
# then the request object will has a `siteuser` property
#
# you can using it like this:
# if request.siteuser:
#     # there has a logged user,
#     uid = request.siteuser.id
# else:
#     # no one is logged
#
# Don't worry about the performance,
# `siteuser` is a lazy object, it readly called just access the `request.siteuser`

class SocialLoginUser(object):
    def process_request(self, request):
        def get_user():
            uid = request.session.get('uid', None)
            if not uid:
                return None

            return SiteUser.objects.get(id=int(uid))

        request.siteuser = SimpleLazyObject(get_user)<commit_msg>middleware check user whether is active<commit_after># -*- coding: utf-8 -*-

from django.utils.functional import SimpleLazyObject

from .models import SiteUser

# add 'social_login.middleware.SocialLoginUser' in MIDDLEWARE_CLASSES
# then the request object will has a `siteuser` property
#
# you can using it like this:
# if request.siteuser:
#     # there has a logged user,
#     uid = request.siteuser.id
# else:
#     # no one is logged
#
# Don't worry about the performance,
# `siteuser` is a lazy object, it readly called just access the `request.siteuser`

class SocialLoginUser(object):
    def process_request(self, request):
        def get_user():
            uid = request.session.get('uid', None)
            if not uid:
                return None

            user = SiteUser.objects.get(id=int(uid))
            if not user.is_active:
                user = None
            return user

        request.siteuser = SimpleLazyObject(get_user)<|endoftext|>


<commit_before>import asyncio
import json
import logging
import signal
import websockets

from netdumplings.exceptions import InvalidDumpling
from netdumplings.shared import (
    validate_dumpling, ND_CLOSE_MSGS, DEFAULT_SHIFTY_HOST,
    DEFAULT_SHIFTY_OUT_PORT
)

class DumplingEater:
    """
    Base helper class for Python-based dumpling eaters.

    Connects to `nd-shifty` and listens for any dumplings made by the provided
    list of chefs (or all chefs if ``chefs`` is ``None``).  Can be given
    callables for any of the following events:

    ``on_connect(websocket_uri, websocket_obj)``
        invoked when the connection to `nd-shifty` is made.

    ``on_dumpling(dumpling)``
        invoked whenever a dumpling is emitted from `nd-shifty`.

    ``on_connection_lost(e)``
        invoked when the connection to `nd-shifty` is closed.

    :param name: Name of the dumpling eater. Is ideally unique per eater.
    :param shifty: Address where `nd-shifty` is sending dumplings from.
    :param chefs: List of chef names whose dumplings this eater wants to
        receive. ``None`` means get all chefs' dumplings.
    :param on_connect: Called when connection to shifty is made. Is passed two
        parameters: the shifty websocket URI (string) and websocket
        object (:class:`websockets.client.WebSocketClientProtocol`).
    :param on_dumpling: Called whenever a dumpling is received. Is passed the
        dumpling as a Python dict.
    :param on_connection_lost: Called when connection to `nd-shifty` is lost.
        Is passed the associated exception object.
    """
    def __init__(
            self,
            name='nameless_eater',
            shifty='{}:{}'.format(
                DEFAULT_SHIFTY_HOST, DEFAULT_SHIFTY_OUT_PORT
            ),
            *,
            chefs=None,
            on_connect=None,
            on_dumpling=None,
            on_connection_lost=None
    ):
        self.name = name
        self.chefs = chefs
        self.shifty_uri = "ws://{0}".format(shifty)

        # Configure handlers. If we're not provided with handlers then we
        # fall back on the default handlers or the handlers provided by a
        # subclass.
        self.on_connect = (
            on_connect if on_connect is not None else self.on_connect
        )
        self.on_dumpling = (
            on_dumpling if on_dumpling is not None else self.on_dumpling
        )
        self.on_connection_lost = (
            on_connection_lost if on_connection_lost is not None
            else self.on_connection_lost
        )

        self._was_connected = False
        self._logger_name = "{}.{}".format(__name__, self.name)
        self.logger = logging.getLogger(self._logger_name)

    async def _grab_dumplings(self, dumpling_count=None):
        """
        Receives all dumplings from shifty and looks for any dumplings which
        were created by the chef(s) we're interested in.  All those dumplings
        are then passed to the on_dumpling handler.

        :param dumpling_count: Number of dumplings to eat.  None means eat
            forever.
        """
        dumplings_eaten = 0

        websocket = await websockets.client.connect(self.shifty_uri)
        self._was_connected = True

        self.logger.info("{0}: Connected to shifty at {1}".format(
            self.name, self.shifty_uri))

        try:
            # Announce ourselves to shifty.
            await websocket.send(json.dumps({'eater_name': self.name}))

            if self.on_connect:
                await self.on_connect(self.shifty_uri, websocket)

            while True:
                # Eat a single dumpling.
                dumpling_json = await websocket.recv()

                # Validate the dumpling.  Note that invalid dumplings will
                # probably be stripped out by shifty (the DumplingHub).
                try:
                    dumpling = validate_dumpling(dumpling_json)
                except InvalidDumpling as e:
                    self.logger.error("{0}: Invalid dumpling: {1}".format(
                        self.name, e))
                    continue

                dumpling_chef = dumpling['metadata']['chef']

                self.logger.debug("{0}: Received dumpling from {1}".format(
                    self.name, dumpling_chef))

                # Call the on_dumpling handler if this dumpling is from a
                # chef that we've registered interest in.
                if self.chefs is None or dumpling_chef in self.chefs:
                    self.logger.debug(
                        "{0}: Calling dumpling handler {1}".format(
                            self.name, self.on_dumpling))

                    dumplings_eaten += 1
                    await self.on_dumpling(dumpling)

                # Stop eating dumplings if we've reached our threshold.
                if dumpling_count is not None and \
                        dumplings_eaten >= dumpling_count:
                    await websocket.close(*ND_CLOSE_MSGS['eater_full'])
                    break
        except asyncio.CancelledError:
            self.logger.warning(
                "{0}: Connection to shifty cancelled; closing...".format(
                    self.name))

            try:
                await websocket.close(*ND_CLOSE_MSGS['conn_cancelled'])
            except websockets.exceptions.InvalidState:
                pass
        except websockets.exceptions.ConnectionClosed as e:
            self.logger.warning("{0}: Lost connection to shifty: {1}".format(
                self.name, e))

            if self.on_connection_lost:
                await self.on_connection_lost(e)

    @staticmethod
    def _interrupt_handler():
        """
        Signal handler.  Cancels all running async tasks.
        """
        tasks = asyncio.Task.all_tasks()
        for task in tasks:
            task.cancel()

    def run(self, dumpling_count=None):
        """
        Run the dumpling eater.

        :param dumpling_count: Number of dumplings to eat.  ``None`` means eat
            forever.
        """
        self.logger.info("{0}: Running dumpling eater".format(self.name))

        # Check that we have a valid callable on_dumpling handler.
        if not hasattr(self.on_dumpling, '__call__'):
            self.logger.error(
                "{0}: on_dumpling handler is not callable".format(self.name))
            return

        self.logger.debug("{0}: Looking for shifty at {1}".format(
            self.name, self.shifty_uri))
        self.logger.debug("{0}: Chefs: {1}".format(
            self.name, ", ".join(self.chefs) if self.chefs else 'all'))

        loop = asyncio.get_event_loop()
        task = loop.create_task(self._grab_dumplings(dumpling_count))

        for signal_name in ('SIGTERM', 'SIGINT'):
            loop.add_signal_handler(
                getattr(signal, signal_name), DumplingEater._interrupt_handler)

        try:
            loop.run_until_complete(task)
        except KeyboardInterrupt as e:
            self.logger.warning(
                "{0}: Caught keyboard interrupt; attempting graceful "
                "shutdown...".format(self.name))
            tasks = asyncio.Task.all_tasks()
            for task in tasks:
                task.cancel()
            loop.run_forever()
        except OSError as e:
            self.logger.warning(
                "{0}: There was a problem with the shifty connection. "
                "Is shifty available?".format(self.name))
            self.logger.warning("{0}: {1}".format(self.name, e))
        finally:
            if self._was_connected:
                self.logger.info(
                    "{0}: Done eating dumplings.".format(self.name))
            loop.close()

    async def on_connect(self, websocket_uri, websocket_obj):
        """
        Default on_connect handler.

        This will be used if an ``on_connect`` handler is not provided during
        instantiation, and if a handler is not provided by a DumplingEater
        subclass.
        """
        self.logger.warning(
            '{}: No on_connect handler specified; ignoring '
            'connection.'.format(self.name)
        )

    async def on_dumpling(self, dumpling):
        """
        Default on_dumpling handler.

        This will be used if an ``on_dumpling`` handler is not provided during
        instantiation, and if a handler is not provided by a DumplingEater
        subclass.
        """
        self.logger.warning(
            '{}: No on_dumpling handler specified; ignoring '
            'dumpling.'.format(self.name)
        )

    async def on_connection_lost(self, e):
        """
        Default on_connection_lost handler.

        This will be used if an ``on_connection_lost`` handler is not provided
        during instantiation, and if a handler is not provided by a
        DumplingEater subclass.
        """
        self.logger.warning(
            '{}: No on_connection_lost handler specified; ignoring '
            'connection loss.'.format(self.name)
        )
<commit_msg>Replace hasattr __call__ check with callable()<commit_after>import asyncio
import json
import logging
import signal
import websockets

from netdumplings.exceptions import InvalidDumpling
from netdumplings.shared import (
    validate_dumpling, ND_CLOSE_MSGS, DEFAULT_SHIFTY_HOST,
    DEFAULT_SHIFTY_OUT_PORT
)

class DumplingEater:
    """
    Base helper class for Python-based dumpling eaters.

    Connects to `nd-shifty` and listens for any dumplings made by the provided
    list of chefs (or all chefs if ``chefs`` is ``None``).  Can be given
    callables for any of the following events:

    ``on_connect(websocket_uri, websocket_obj)``
        invoked when the connection to `nd-shifty` is made.

    ``on_dumpling(dumpling)``
        invoked whenever a dumpling is emitted from `nd-shifty`.

    ``on_connection_lost(e)``
        invoked when the connection to `nd-shifty` is closed.

    :param name: Name of the dumpling eater. Is ideally unique per eater.
    :param shifty: Address where `nd-shifty` is sending dumplings from.
    :param chefs: List of chef names whose dumplings this eater wants to
        receive. ``None`` means get all chefs' dumplings.
    :param on_connect: Called when connection to shifty is made. Is passed two
        parameters: the shifty websocket URI (string) and websocket
        object (:class:`websockets.client.WebSocketClientProtocol`).
    :param on_dumpling: Called whenever a dumpling is received. Is passed the
        dumpling as a Python dict.
    :param on_connection_lost: Called when connection to `nd-shifty` is lost.
        Is passed the associated exception object.
    """
    def __init__(
            self,
            name='nameless_eater',
            shifty='{}:{}'.format(
                DEFAULT_SHIFTY_HOST, DEFAULT_SHIFTY_OUT_PORT
            ),
            *,
            chefs=None,
            on_connect=None,
            on_dumpling=None,
            on_connection_lost=None
    ):
        self.name = name
        self.chefs = chefs
        self.shifty_uri = "ws://{0}".format(shifty)

        # Configure handlers. If we're not provided with handlers then we
        # fall back on the default handlers or the handlers provided by a
        # subclass.
        self.on_connect = (
            on_connect if on_connect is not None else self.on_connect
        )
        self.on_dumpling = (
            on_dumpling if on_dumpling is not None else self.on_dumpling
        )
        self.on_connection_lost = (
            on_connection_lost if on_connection_lost is not None
            else self.on_connection_lost
        )

        self._was_connected = False
        self._logger_name = "{}.{}".format(__name__, self.name)
        self.logger = logging.getLogger(self._logger_name)

    async def _grab_dumplings(self, dumpling_count=None):
        """
        Receives all dumplings from shifty and looks for any dumplings which
        were created by the chef(s) we're interested in.  All those dumplings
        are then passed to the on_dumpling handler.

        :param dumpling_count: Number of dumplings to eat.  None means eat
            forever.
        """
        dumplings_eaten = 0

        websocket = await websockets.client.connect(self.shifty_uri)
        self._was_connected = True

        self.logger.info("{0}: Connected to shifty at {1}".format(
            self.name, self.shifty_uri))

        try:
            # Announce ourselves to shifty.
            await websocket.send(json.dumps({'eater_name': self.name}))

            if self.on_connect:
                await self.on_connect(self.shifty_uri, websocket)

            while True:
                # Eat a single dumpling.
                dumpling_json = await websocket.recv()

                # Validate the dumpling.  Note that invalid dumplings will
                # probably be stripped out by shifty (the DumplingHub).
                try:
                    dumpling = validate_dumpling(dumpling_json)
                except InvalidDumpling as e:
                    self.logger.error("{0}: Invalid dumpling: {1}".format(
                        self.name, e))
                    continue

                dumpling_chef = dumpling['metadata']['chef']

                self.logger.debug("{0}: Received dumpling from {1}".format(
                    self.name, dumpling_chef))

                # Call the on_dumpling handler if this dumpling is from a
                # chef that we've registered interest in.
                if self.chefs is None or dumpling_chef in self.chefs:
                    self.logger.debug(
                        "{0}: Calling dumpling handler {1}".format(
                            self.name, self.on_dumpling))

                    dumplings_eaten += 1
                    await self.on_dumpling(dumpling)

                # Stop eating dumplings if we've reached our threshold.
                if dumpling_count is not None and \
                        dumplings_eaten >= dumpling_count:
                    await websocket.close(*ND_CLOSE_MSGS['eater_full'])
                    break
        except asyncio.CancelledError:
            self.logger.warning(
                "{0}: Connection to shifty cancelled; closing...".format(
                    self.name))

            try:
                await websocket.close(*ND_CLOSE_MSGS['conn_cancelled'])
            except websockets.exceptions.InvalidState:
                pass
        except websockets.exceptions.ConnectionClosed as e:
            self.logger.warning("{0}: Lost connection to shifty: {1}".format(
                self.name, e))

            if self.on_connection_lost:
                await self.on_connection_lost(e)

    @staticmethod
    def _interrupt_handler():
        """
        Signal handler.  Cancels all running async tasks.
        """
        tasks = asyncio.Task.all_tasks()
        for task in tasks:
            task.cancel()

    def run(self, dumpling_count=None):
        """
        Run the dumpling eater.

        :param dumpling_count: Number of dumplings to eat.  ``None`` means eat
            forever.
        """
        self.logger.info("{0}: Running dumpling eater".format(self.name))

        if not callable(self.on_dumpling):
            self.logger.error(
                "{0}: on_dumpling handler is not callable".format(self.name))
            return

        self.logger.debug("{0}: Looking for shifty at {1}".format(
            self.name, self.shifty_uri))
        self.logger.debug("{0}: Chefs: {1}".format(
            self.name, ", ".join(self.chefs) if self.chefs else 'all'))

        loop = asyncio.get_event_loop()
        task = loop.create_task(self._grab_dumplings(dumpling_count))

        for signal_name in ('SIGTERM', 'SIGINT'):
            loop.add_signal_handler(
                getattr(signal, signal_name), DumplingEater._interrupt_handler)

        try:
            loop.run_until_complete(task)
        except KeyboardInterrupt as e:
            self.logger.warning(
                "{0}: Caught keyboard interrupt; attempting graceful "
                "shutdown...".format(self.name))
            tasks = asyncio.Task.all_tasks()
            for task in tasks:
                task.cancel()
            loop.run_forever()
        except OSError as e:
            self.logger.warning(
                "{0}: There was a problem with the shifty connection. "
                "Is shifty available?".format(self.name))
            self.logger.warning("{0}: {1}".format(self.name, e))
        finally:
            if self._was_connected:
                self.logger.info(
                    "{0}: Done eating dumplings.".format(self.name))
            loop.close()

    async def on_connect(self, websocket_uri, websocket_obj):
        """
        Default on_connect handler.

        This will be used if an ``on_connect`` handler is not provided during
        instantiation, and if a handler is not provided by a DumplingEater
        subclass.
        """
        self.logger.warning(
            '{}: No on_connect handler specified; ignoring '
            'connection.'.format(self.name)
        )

    async def on_dumpling(self, dumpling):
        """
        Default on_dumpling handler.

        This will be used if an ``on_dumpling`` handler is not provided during
        instantiation, and if a handler is not provided by a DumplingEater
        subclass.
        """
        self.logger.warning(
            '{}: No on_dumpling handler specified; ignoring '
            'dumpling.'.format(self.name)
        )

    async def on_connection_lost(self, e):
        """
        Default on_connection_lost handler.

        This will be used if an ``on_connection_lost`` handler is not provided
        during instantiation, and if a handler is not provided by a
        DumplingEater subclass.
        """
        self.logger.warning(
            '{}: No on_connection_lost handler specified; ignoring '
            'connection loss.'.format(self.name)
        )
<|endoftext|>