<commit_before>import uuid, urllib, facebook

from django.conf import settings
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from django.utils.translation import gettext as _
from django.http import HttpResponseRedirect

try:
    from django.views.decorators.csrf import csrf_protect
    has_csrf = True
except ImportError:
    has_csrf = False

from django.contrib.auth.models import User
from django.contrib.auth import login, authenticate, logout as auth_logout
from django.contrib.sites.models import Site

from socialregistration.forms import UserForm
from socialregistration.utils import (OAuthClient, OAuthTwitter,
    OpenID, _https, DiscoveryFailure)
from socialregistration.models import FacebookProfile, TwitterProfile, LinkedinProfile, OpenIDProfile
from socialregistration import signals

FB_ERROR = _('We couldn\'t validate your Facebook credentials')

GENERATE_USERNAME = bool(getattr(settings, 'SOCIALREGISTRATION_GENERATE_USERNAME', False))

def _get_next(request):
    """
    Returns a url to redirect to after the login
    """
    if 'next' in request.session:
        next = request.session['next']
        del request.session['next']
        return next
    elif 'next' in request.GET:
        return request.GET.get('next')
    elif 'next' in request.POST:
        return request.POST.get('next')
    else:
        return getattr(settings, 'LOGIN_REDIRECT_URL', '/')

def _login(request, user, profile, client):
    login(request, user)
    signals.login.send(sender = profile.__class__,
                                  user = user,
                                  profile = profile,
                                  client = client)

def _connect(user, profile, client):
    signals.connect.send(sender = profile.__class__,
                                    user = user,
                                    profile = profile,
                                    client = client)

def setup(request, template='socialregistration/setup.html',
    form_class=UserForm, extra_context=dict(), initial=dict()):
    """
    Setup view to create a username & set email address after authentication
    """
    try:
        social_user = request.session['socialregistration_user']
        social_profile = request.session['socialregistration_profile']
        social_client = request.session['socialregistration_client']
    except KeyError:
        return render_to_response(
            template, dict(error=True), context_instance=RequestContext(request))

    if GENERATE_USERNAME:
        social_user.username = str(uuid.uuid4())[:30]
        social_user.save()

        social_profile.user = social_user
        social_profile.save()

        user = social_profile.authenticate()

    else:
        if not request.method == "POST":
            form = form_class(social_user, social_profile, initial=initial)
            extra_context.update({'form': form})
            return render_to_response(template, extra_context,
                                      context_instance = RequestContext(request))

        form = form_class(social_user, social_profile, request.POST, initial=initial)

        if form.is_valid():
            form.save(request = request)
            user = form.profile.authenticate()

        else:
            extra_context.update({'form': form})
            return render_to_response(template, extra_context,
                                      context_instance = RequestContext(request))

    social_client.request = request

    # Removing unused bits. It's important to remove the
    # client from the session because the session gets written
    # to the storage on login and the client holds the request,
    # which is going to fail. Might be worth to change the
    # clients to not hold the whole request.
    if 'socialregistration_user' in request.session:
        del request.session['socialregistration_user']
    if 'socialregistration_profile' in request.session:
        del request.session['socialregistration_profile']
    if 'socialregistration_client' in request.session:
        del request.session['socialregistration_client']

    _connect(user, social_profile, social_client)
    _login(request, user, social_profile, social_client)

    return HttpResponseRedirect(_get_next(request))

if has_csrf:
    setup = csrf_protect(setup)

def facebook_login(request):
    """ Handle the login """
    params = {}
    params['client_id'] = settings.FACEBOOK_APP_ID
    params['redirect_uri'] = request.build_absolute_uri(reverse('facebook_connect'))
    params['display'] = getattr(settings, 'FACEBOOK_DISPLAY', 'popup')
    params['scope'] = getattr(settings, 'FACEBOOK_SCOPE', '')

    # Set redirect
    if request.POST.get('next', None):
        request.session['next'] = request.POST.get('next')

    url = 'https://graph.facebook.com/oauth/authorize?' + urllib.urlencode(params)

    return HttpResponseRedirect(url)

def facebook_connect(request, template='socialregistration/facebook.html',
                     extra_context=dict()):
    """
    View to handle graph connecting

    Authorize and create user if none

    """
    if request.facebook.uid:
        uid = request.facebook.uid
        access_token = request.facebook.access_token
    else:
        # if cookie does not exist
        # assume logging in normal way
        params = {}
        params["client_id"] = settings.FACEBOOK_APP_ID
        params["client_secret"] = settings.FACEBOOK_SECRET_KEY
        params["redirect_uri"] = request.build_absolute_uri(reverse("facebook_connect"))
        params["code"] = request.GET.get('code', '')

        url = "https://graph.facebook.com/oauth/access_token?"+urllib.urlencode(params)
        from cgi import parse_qs
        userdata = urllib.urlopen(url).read()
        res_parse_qs = parse_qs(userdata)

        # Could be a bot query
        if not res_parse_qs.has_key('access_token'):
            return render_to_response(template, extra_context,
                                      context_instance=RequestContext(request))

        access_token = res_parse_qs['access_token'][-1]

    graph = facebook.GraphAPI(access_token)
    user_info = graph.get_object('me')

    if request.user.is_authenticated():
        # Handling already logged in users connecting their accounts
        try:
            profile = FacebookProfile.objects.get(uid=user_info['id'])
        except FacebookProfile.DoesNotExist: # There can only be one profile!
            profile = FacebookProfile.objects.create(user=request.user,
                                                     uid=user_info['id'],
                                                     username=user_info['name'],
                                                     access_token=access_token)

            _connect(request.user, profile, request.facebook)
        else:
            profile.access_token = access_token
            profile.save()

        return HttpResponseRedirect(_get_next(request))

    user = authenticate(uid=user_info['id'])

    if user is None:
        profile = FacebookProfile(uid=user_info['id'],
                                  username=user_info['name'],
                                  access_token=access_token)
        user = User()
        request.session['socialregistration_profile'] = profile
        request.session['socialregistration_user'] = user
        # Client is not pickleable with the request on it
        request.session['socialregistration_client'] = request.facebook
        request.session['next'] = _get_next(request)
        return HttpResponseRedirect(reverse('socialregistration_setup'))

    _login(request, user, FacebookProfile.objects.get(user = user), request.facebook)

    return HttpResponseRedirect(_get_next(request))

def logout(request, redirect_url=None):
    """
    Logs the user out of django. This is only a wrapper around
    django.contrib.auth.logout. Logging users out of Facebook for instance
    should be done like described in the developer wiki on facebook.
    http://wiki.developers.facebook.com/index.php/Connect/Authorization_Websites#Logging_Out_Users
    """
    auth_logout(request)

    url = redirect_url or getattr(settings, 'LOGOUT_REDIRECT_URL', '/')

    return HttpResponseRedirect(url)

def twitter(request, account_inactive_template='socialregistration/account_inactive.html',
    extra_context=dict(), client_class=None):
    """
    Actually setup/login an account relating to a twitter user after the oauth
    process is finished successfully
    """
    client = client_class(
        request, settings.TWITTER_CONSUMER_KEY,
        settings.TWITTER_CONSUMER_SECRET_KEY,
        settings.TWITTER_REQUEST_TOKEN_URL,
    )

    user_info = client.get_user_info()

    if request.user.is_authenticated():
        # Handling already logged in users connecting their accounts
        try:
            profile = TwitterProfile.objects.get(twitter_id=user_info['id'])
        except TwitterProfile.DoesNotExist: # There can only be one profile!
            profile = TwitterProfile.objects.create(user=request.user,
                                                    twitter_id=user_info['id'],
                                                    username=user_info['screen_name'])
            _connect(request.user, profile, client)

        return HttpResponseRedirect(_get_next(request))

    user = authenticate(twitter_id=user_info['id'])

    if user is None:
        profile = TwitterProfile(twitter_id=user_info['id'],
                                 username=user_info['screen_name'])
        user = User()
        request.session['socialregistration_profile'] = profile
        request.session['socialregistration_user'] = user
        # Client is not pickleable with the request on it
        client.request = None
        request.session['socialregistration_client'] = client
        request.session['next'] = _get_next(request)
        return HttpResponseRedirect(reverse('socialregistration_setup'))

    if not user.is_active:
        return render_to_response(
            account_inactive_template,
            extra_context,
            context_instance=RequestContext(request)
        )

    _login(request, user, TwitterProfile.objects.get(user = user), client)

    return HttpResponseRedirect(_get_next(request))

def linkedin(request, account_inactive_template='socialregistration/account_inactive.html',
    extra_context=dict(), client_class=None):
    """
    Actually setup/login an account relating to a twitter user after the oauth
    process is finished successfully
    """
    client = client_class(
        request, settings.LINKEDIN_CONSUMER_KEY,
        settings.LINKEDIN_CONSUMER_SECRET_KEY,
        settings.LINKEDIN_REQUEST_TOKEN_URL,
    )

    user_info = client.get_user_info()

    if request.user.is_authenticated():
        # Handling already logged in users connecting their accounts
        try:
            profile = LinkedinProfile.objects.get(linkedin_id=user_info['id'])
        except TwitterProfile.DoesNotExist: # There can only be one profile!
            profile = LinkedinProfile.objects.create(user=request.user,
                                                     linkedin_id=user_info['id'],
                                                     username=user_info['screen_name'])
            _connect(user, profile, client)

        return HttpResponseRedirect(_get_next(request))

    user = authenticate(linkedin_id=user_info['id'])

    if user is None:
        profile = LinkedinProfile(linkedin_id=user_info['id'],
                                  username=user_info['screen_name'])
        user = User()
        request.session['socialregistration_profile'] = profile
        request.session['socialregistration_user'] = user
        # Client is not pickleable with the request on it
        client.request = None
        request.session['socialregistration_client'] = client
        request.session['next'] = _get_next(request)
        return HttpResponseRedirect(reverse('socialregistration_setup'))

    if not user.is_active:
        return render_to_response(
            account_inactive_template,
            extra_context,
            context_instance=RequestContext(request)
        )

    _login(request, user, LinkedinProfile.objects.get(user = user), client)

    return HttpResponseRedirect(_get_next(request))

def oauth_redirect(request, consumer_key=None, secret_key=None,
    request_token_url=None, access_token_url=None, authorization_url=None,
    callback_url=None, parameters=None, client_class = None):
    """
    View to handle the OAuth based authentication redirect to the service provider
    """
    request.session['next'] = _get_next(request)
    client = client_class(request, consumer_key, secret_key,
        request_token_url, access_token_url, authorization_url, callback_url, parameters)
    return client.get_redirect()

def oauth_callback(request, consumer_key=None, secret_key=None,
    request_token_url=None, access_token_url=None, authorization_url=None,
    callback_url=None, template='socialregistration/oauthcallback.html',
    extra_context=dict(), parameters=None, client_class = None):
    """
    View to handle final steps of OAuth based authentication where the user
    gets redirected back to from the service provider
    """
    client = client_class(request, consumer_key, secret_key, request_token_url,
        access_token_url, authorization_url, callback_url, parameters)

    extra_context.update(dict(oauth_client=client))
    if not client.is_valid():
        return render_to_response(
            template, extra_context, context_instance=RequestContext(request)
        )

    # We're redirecting to the setup view for this oauth service
    return HttpResponseRedirect(reverse(client.callback_url))

def openid_redirect(request, client_class = None):
    """
    Redirect the user to the openid provider
    """
    request.session['next'] = _get_next(request)
    request.session['openid_provider'] = request.GET.get('openid_provider')

    client = client_class(
        request,
        'http%s://%s%s' % (
            _https(),
            Site.objects.get_current().domain,
            reverse('openid_callback')
        ),
        request.GET.get('openid_provider')
    )
    try:
        return client.get_redirect()
    except DiscoveryFailure:
        request.session['openid_error'] = True
        return HttpResponseRedirect(settings.LOGIN_URL)

def openid_callback(request, template='socialregistration/openid.html',
    extra_context=dict(), account_inactive_template='socialregistration/account_inactive.html',
    client_class = None):
    """
    Catches the user when he's redirected back from the provider to our site
    """
    client = client_class(
        request,
        'http%s://%s%s' % (
            _https(),
            Site.objects.get_current().domain,
            reverse('openid_callback')
        ),
        request.session.get('openid_provider')
    )

    if client.is_valid():
        identity = client.result.identity_url
        if request.user.is_authenticated():
            # Handling already logged in users just connecting their accounts
            try:
                profile = OpenIDProfile.objects.get(identity=identity)
            except OpenIDProfile.DoesNotExist: # There can only be one profile with the same identity
                profile = OpenIDProfile.objects.create(user=request.user,
                    identity=identity)
                _connect(user, profile, client)

            return HttpResponseRedirect(_get_next(request))

        user = authenticate(identity=identity)
        if user is None:
            request.session['socialregistration_user'] = User()
            request.session['socialregistration_profile'] = OpenIDProfile(
                identity=identity
            )
            # Client is not pickleable with the request on it
            client.request = None
            request.session['socialregistration_client'] = client
            return HttpResponseRedirect(reverse('socialregistration_setup'))

        if not user.is_active:
            return render_to_response(
                account_inactive_template,
                extra_context,
                context_instance=RequestContext(request)
            )

        _login(request, user, OpenIDProfile.objects.get(user = user), client)
        return HttpResponseRedirect(_get_next(request))

    return render_to_response(
        template,
        dict(),
        context_instance=RequestContext(request)
    )
<commit_msg>Try/except in views<commit_after>import uuid, urllib, facebook

from django.conf import settings
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.shortcuts import render_to_response
from django.utils.translation import gettext as _
from django.http import HttpResponseRedirect

try:
    from django.views.decorators.csrf import csrf_protect
    has_csrf = True
except ImportError:
    has_csrf = False

from django.contrib.auth.models import User
from django.contrib.auth import login, authenticate, logout as auth_logout
from django.contrib.sites.models import Site

from socialregistration.forms import UserForm
from socialregistration.utils import (OAuthClient, OAuthTwitter,
    OpenID, _https, DiscoveryFailure)
from socialregistration.models import FacebookProfile, TwitterProfile, LinkedinProfile, OpenIDProfile
from socialregistration import signals

FB_ERROR = _('We couldn\'t validate your Facebook credentials')

GENERATE_USERNAME = bool(getattr(settings, 'SOCIALREGISTRATION_GENERATE_USERNAME', False))

def _get_next(request):
    """
    Returns a url to redirect to after the login
    """
    if 'next' in request.session:
        next = request.session['next']
        del request.session['next']
        return next
    elif 'next' in request.GET:
        return request.GET.get('next')
    elif 'next' in request.POST:
        return request.POST.get('next')
    else:
        return getattr(settings, 'LOGIN_REDIRECT_URL', '/')

def _login(request, user, profile, client):
    login(request, user)
    signals.login.send(sender = profile.__class__,
                                  user = user,
                                  profile = profile,
                                  client = client)

def _connect(user, profile, client):
    signals.connect.send(sender = profile.__class__,
                                    user = user,
                                    profile = profile,
                                    client = client)

def setup(request, template='socialregistration/setup.html',
    form_class=UserForm, extra_context=dict(), initial=dict()):
    """
    Setup view to create a username & set email address after authentication
    """
    try:
        social_user = request.session['socialregistration_user']
        social_profile = request.session['socialregistration_profile']
        social_client = request.session['socialregistration_client']
    except KeyError:
        return render_to_response(
            template, dict(error=True), context_instance=RequestContext(request))

    if GENERATE_USERNAME:
        social_user.username = str(uuid.uuid4())[:30]
        social_user.save()

        social_profile.user = social_user
        social_profile.save()

        user = social_profile.authenticate()

    else:
        if not request.method == "POST":
            form = form_class(social_user, social_profile, initial=initial)
            extra_context.update({'form': form})
            return render_to_response(template, extra_context,
                                      context_instance = RequestContext(request))

        form = form_class(social_user, social_profile, request.POST, initial=initial)

        if form.is_valid():
            form.save(request = request)
            user = form.profile.authenticate()

        else:
            extra_context.update({'form': form})
            return render_to_response(template, extra_context,
                                      context_instance = RequestContext(request))

    social_client.request = request

    # Removing unused bits. It's important to remove the
    # client from the session because the session gets written
    # to the storage on login and the client holds the request,
    # which is going to fail. Might be worth to change the
    # clients to not hold the whole request.
    if 'socialregistration_user' in request.session:
        del request.session['socialregistration_user']
    if 'socialregistration_profile' in request.session:
        del request.session['socialregistration_profile']
    if 'socialregistration_client' in request.session:
        del request.session['socialregistration_client']

    _connect(user, social_profile, social_client)
    _login(request, user, social_profile, social_client)

    return HttpResponseRedirect(_get_next(request))

if has_csrf:
    setup = csrf_protect(setup)

def facebook_login(request):
    """ Handle the login """
    params = {}
    params['client_id'] = settings.FACEBOOK_APP_ID
    params['redirect_uri'] = request.build_absolute_uri(reverse('facebook_connect'))
    params['display'] = getattr(settings, 'FACEBOOK_DISPLAY', 'popup')
    params['scope'] = getattr(settings, 'FACEBOOK_SCOPE', '')

    # Set redirect
    if request.POST.get('next', None):
        request.session['next'] = request.POST.get('next')

    url = 'https://graph.facebook.com/oauth/authorize?' + urllib.urlencode(params)

    return HttpResponseRedirect(url)

def facebook_connect(request, template='socialregistration/facebook.html',
                     extra_context=dict()):
    """
    View to handle graph connecting

    Authorize and create user if none

    """
    try:
        uid = request.facebook.uid
    except:
        # if cookie does not exist
        # assume logging in normal way
        params = {}
        params["client_id"] = settings.FACEBOOK_APP_ID
        params["client_secret"] = settings.FACEBOOK_SECRET_KEY
        params["redirect_uri"] = request.build_absolute_uri(reverse("facebook_connect"))
        params["code"] = request.GET.get('code', '')

        url = "https://graph.facebook.com/oauth/access_token?"+urllib.urlencode(params)
        from cgi import parse_qs
        userdata = urllib.urlopen(url).read()
        res_parse_qs = parse_qs(userdata)

        # Could be a bot query
        if not res_parse_qs.has_key('access_token'):
            return render_to_response(template, extra_context,
                                      context_instance=RequestContext(request))

        access_token = res_parse_qs['access_token'][-1]
    else:
        access_token = request.facebook.access_token

    graph = facebook.GraphAPI(access_token)
    user_info = graph.get_object('me')

    if request.user.is_authenticated():
        # Handling already logged in users connecting their accounts
        try:
            profile = FacebookProfile.objects.get(uid=user_info['id'])
        except FacebookProfile.DoesNotExist: # There can only be one profile!
            profile = FacebookProfile.objects.create(user=request.user,
                                                     uid=user_info['id'],
                                                     username=user_info['name'],
                                                     access_token=access_token)

            _connect(request.user, profile, request.facebook)
        else:
            profile.access_token = access_token
            profile.save()

        return HttpResponseRedirect(_get_next(request))

    user = authenticate(uid=user_info['id'])

    if user is None:
        profile = FacebookProfile(uid=user_info['id'],
                                  username=user_info['name'],
                                  access_token=access_token)
        user = User()
        request.session['socialregistration_profile'] = profile
        request.session['socialregistration_user'] = user
        # Client is not pickleable with the request on it
        request.session['socialregistration_client'] = request.facebook
        request.session['next'] = _get_next(request)
        return HttpResponseRedirect(reverse('socialregistration_setup'))

    _login(request, user, FacebookProfile.objects.get(user = user), request.facebook)

    return HttpResponseRedirect(_get_next(request))

def logout(request, redirect_url=None):
    """
    Logs the user out of django. This is only a wrapper around
    django.contrib.auth.logout. Logging users out of Facebook for instance
    should be done like described in the developer wiki on facebook.
    http://wiki.developers.facebook.com/index.php/Connect/Authorization_Websites#Logging_Out_Users
    """
    auth_logout(request)

    url = redirect_url or getattr(settings, 'LOGOUT_REDIRECT_URL', '/')

    return HttpResponseRedirect(url)

def twitter(request, account_inactive_template='socialregistration/account_inactive.html',
    extra_context=dict(), client_class=None):
    """
    Actually setup/login an account relating to a twitter user after the oauth
    process is finished successfully
    """
    client = client_class(
        request, settings.TWITTER_CONSUMER_KEY,
        settings.TWITTER_CONSUMER_SECRET_KEY,
        settings.TWITTER_REQUEST_TOKEN_URL,
    )

    try:
        user_info = client.get_user_info()
    except:
        return render_to_response(
            account_inactive_template,
            extra_context,
            context_instance=RequestContext(request)
        )

    if request.user.is_authenticated():
        # Handling already logged in users connecting their accounts
        try:
            profile = TwitterProfile.objects.get(twitter_id=user_info['id'])
        except TwitterProfile.DoesNotExist: # There can only be one profile!
            profile = TwitterProfile.objects.create(user=request.user,
                                                    twitter_id=user_info['id'],
                                                    username=user_info['screen_name'])
            _connect(request.user, profile, client)

        return HttpResponseRedirect(_get_next(request))

    user = authenticate(twitter_id=user_info['id'])

    if user is None:
        profile = TwitterProfile(twitter_id=user_info['id'],
                                 username=user_info['screen_name'])
        user = User()
        request.session['socialregistration_profile'] = profile
        request.session['socialregistration_user'] = user
        # Client is not pickleable with the request on it
        client.request = None
        request.session['socialregistration_client'] = client
        request.session['next'] = _get_next(request)
        return HttpResponseRedirect(reverse('socialregistration_setup'))

    if not user.is_active:
        return render_to_response(
            account_inactive_template,
            extra_context,
            context_instance=RequestContext(request)
        )

    _login(request, user, TwitterProfile.objects.get(user = user), client)

    return HttpResponseRedirect(_get_next(request))

def linkedin(request, account_inactive_template='socialregistration/account_inactive.html',
    extra_context=dict(), client_class=None):
    """
    Actually setup/login an account relating to a twitter user after the oauth
    process is finished successfully
    """
    client = client_class(
        request, settings.LINKEDIN_CONSUMER_KEY,
        settings.LINKEDIN_CONSUMER_SECRET_KEY,
        settings.LINKEDIN_REQUEST_TOKEN_URL,
    )

    try:
        user_info = client.get_user_info()
    except:
        return render_to_response(
            account_inactive_template,
            extra_context,
            context_instance=RequestContext(request)
        )

    if request.user.is_authenticated():
        # Handling already logged in users connecting their accounts
        try:
            profile = LinkedinProfile.objects.get(linkedin_id=user_info['id'])
        except TwitterProfile.DoesNotExist: # There can only be one profile!
            profile = LinkedinProfile.objects.create(user=request.user,
                                                     linkedin_id=user_info['id'],
                                                     username=user_info['screen_name'])
            _connect(user, profile, client)

        return HttpResponseRedirect(_get_next(request))

    user = authenticate(linkedin_id=user_info['id'])

    if user is None:
        profile = LinkedinProfile(linkedin_id=user_info['id'],
                                  username=user_info['screen_name'])
        user = User()
        request.session['socialregistration_profile'] = profile
        request.session['socialregistration_user'] = user
        # Client is not pickleable with the request on it
        client.request = None
        request.session['socialregistration_client'] = client
        request.session['next'] = _get_next(request)
        return HttpResponseRedirect(reverse('socialregistration_setup'))

    if not user.is_active:
        return render_to_response(
            account_inactive_template,
            extra_context,
            context_instance=RequestContext(request)
        )

    _login(request, user, LinkedinProfile.objects.get(user = user), client)

    return HttpResponseRedirect(_get_next(request))

def oauth_redirect(request, consumer_key=None, secret_key=None,
    request_token_url=None, access_token_url=None, authorization_url=None,
    callback_url=None, parameters=None, client_class = None):
    """
    View to handle the OAuth based authentication redirect to the service provider
    """
    request.session['next'] = _get_next(request)
    client = client_class(request, consumer_key, secret_key,
        request_token_url, access_token_url, authorization_url, callback_url, parameters)
    return client.get_redirect()

def oauth_callback(request, consumer_key=None, secret_key=None,
    request_token_url=None, access_token_url=None, authorization_url=None,
    callback_url=None, template='socialregistration/oauthcallback.html',
    extra_context=dict(), parameters=None, client_class = None):
    """
    View to handle final steps of OAuth based authentication where the user
    gets redirected back to from the service provider
    """
    client = client_class(request, consumer_key, secret_key, request_token_url,
        access_token_url, authorization_url, callback_url, parameters)

    extra_context.update(dict(oauth_client=client))
    if not client.is_valid():
        return render_to_response(
            template, extra_context, context_instance=RequestContext(request)
        )

    # We're redirecting to the setup view for this oauth service
    return HttpResponseRedirect(reverse(client.callback_url))

def openid_redirect(request, client_class = None):
    """
    Redirect the user to the openid provider
    """
    request.session['next'] = _get_next(request)
    request.session['openid_provider'] = request.GET.get('openid_provider')

    client = client_class(
        request,
        'http%s://%s%s' % (
            _https(),
            Site.objects.get_current().domain,
            reverse('openid_callback')
        ),
        request.GET.get('openid_provider')
    )
    try:
        return client.get_redirect()
    except DiscoveryFailure:
        request.session['openid_error'] = True
        return HttpResponseRedirect(settings.LOGIN_URL)

def openid_callback(request, template='socialregistration/openid.html',
    extra_context=dict(), account_inactive_template='socialregistration/account_inactive.html',
    client_class = None):
    """
    Catches the user when he's redirected back from the provider to our site
    """
    client = client_class(
        request,
        'http%s://%s%s' % (
            _https(),
            Site.objects.get_current().domain,
            reverse('openid_callback')
        ),
        request.session.get('openid_provider')
    )

    if client.is_valid():
        identity = client.result.identity_url
        if request.user.is_authenticated():
            # Handling already logged in users just connecting their accounts
            try:
                profile = OpenIDProfile.objects.get(identity=identity)
            except OpenIDProfile.DoesNotExist: # There can only be one profile with the same identity
                profile = OpenIDProfile.objects.create(user=request.user,
                    identity=identity)
                _connect(user, profile, client)

            return HttpResponseRedirect(_get_next(request))

        user = authenticate(identity=identity)
        if user is None:
            request.session['socialregistration_user'] = User()
            request.session['socialregistration_profile'] = OpenIDProfile(
                identity=identity
            )
            # Client is not pickleable with the request on it
            client.request = None
            request.session['socialregistration_client'] = client
            return HttpResponseRedirect(reverse('socialregistration_setup'))

        if not user.is_active:
            return render_to_response(
                account_inactive_template,
                extra_context,
                context_instance=RequestContext(request)
            )

        _login(request, user, OpenIDProfile.objects.get(user = user), client)
        return HttpResponseRedirect(_get_next(request))

    return render_to_response(
        template,
        dict(),
        context_instance=RequestContext(request)
    )
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
__author__ = "Sergey Aganezov"
__email__ = "aganezov(at)gwu.edu"
__status__ = "production"

version = "1.9.0"

__all__ = ["grimm",
           "breakpoint_graph",
           "graphviz",
           "utils",
           "edge",
           "genome",
           "kbreak",
           "multicolor",
           "tree",
           "vertices",
           "utils",
           "distances"]

<commit_msg>version bump (i) and email update (ii) due to (i) code updated to support networkx 2.2+ (ii) relocation to computer science department at JHU<commit_after># -*- coding: utf-8 -*-
__author__ = "Sergey Aganezov"
__email__ = "aganezov(at)cs.jhu.edu"
__status__ = "production"

version = "1.9.1"

__all__ = ["grimm",
           "breakpoint_graph",
           "graphviz",
           "utils",
           "edge",
           "genome",
           "kbreak",
           "multicolor",
           "tree",
           "vertices",
           "utils",
           "distances"]

<|endoftext|>


<commit_before>'''
@author: jnaous
'''
try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

class threadlocal(local):
    d_stack = []

_thread_locals = threadlocal()

def push_frame(**kw):
    """
    Push a new frame on the stack.
    """
    _thread_locals.d_stack.append(kw)

def pop_frame():
    """
    Pop a frame from the stack.
    """
    try:
        _thread_locals.d_stack.pop()
    except IndexError:
        pass

def get_thread_locals():
    """
    Returns the dictionary of all parsed keywords in the request.
    """
    return _thread_locals.d_stack[-1]

def add_parser(kw, func):
    """
    Add a request parser for a keyword.
    When a request arrives, the parser C{func} will be used to set the value
    for the C{kw} keyword in the thread-local storage.

    @param kw: The keyword to use for the result of this parser.
    @type kw: hashable value
    @param func: a function that accepts the request and returns a value
    @type func: callable.
    """
    ThreadLocals.add_parser(kw, func)

def get_parser(kw):
    """
    Get the parser function stored for the keyword C{kw} or None if
    it doesn't exist.
    """
    return ThreadLocals.__parser.get(kw, None)

class ParserRedefined(Exception):
    """
    Raised when L{models.ThreadLocals.add_parser} is called twice for the same
    keyword.
    """
    def __init__(self, keyword):
        self.keyword = keyword
        super(ParserRedefined, self).__init__(
            "Threadlocals parser to get keyword %s from request redefined."
            % keyword)

class ThreadLocals(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""

    __parsers = {}

    @classmethod
    def add_parser(cls, kw, func):
        """
        Add a function to parse a request, get an object, and store it in
        thread locals storage
        """
        if kw in cls.__parsers:
            raise ParserRedefined(kw)

        cls.__parsers[kw] = func

    def process_request(self, request):
        """Parse request and set keywords"""
        d = {}
        for kw, func in self.__parsers.items():
            d[kw] = func(request)
        push_frame(**d)
        return None

    def process_response(self, request, response):
        """Reset thread locals"""
        pop_frame()
        return response
    <commit_msg>first stack should always be empty to prevent bad indices.<commit_after>'''
@author: jnaous
'''
try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

class threadlocal(local):
    d_stack = [{}]

_thread_locals = threadlocal()

def push_frame(**kw):
    """
    Push a new frame on the stack.
    """
    _thread_locals.d_stack.append(kw)

def pop_frame():
    """
    Pop a frame from the stack.
    """
    try:
        _thread_locals.d_stack.pop()
    except IndexError:
        pass

def get_thread_locals():
    """
    Returns the dictionary of all parsed keywords in the request.
    """
    return _thread_locals.d_stack[-1]

def add_parser(kw, func):
    """
    Add a request parser for a keyword.
    When a request arrives, the parser C{func} will be used to set the value
    for the C{kw} keyword in the thread-local storage.

    @param kw: The keyword to use for the result of this parser.
    @type kw: hashable value
    @param func: a function that accepts the request and returns a value
    @type func: callable.
    """
    ThreadLocals.add_parser(kw, func)

def get_parser(kw):
    """
    Get the parser function stored for the keyword C{kw} or None if
    it doesn't exist.
    """
    return ThreadLocals.__parser.get(kw, None)

class ParserRedefined(Exception):
    """
    Raised when L{models.ThreadLocals.add_parser} is called twice for the same
    keyword.
    """
    def __init__(self, keyword):
        self.keyword = keyword
        super(ParserRedefined, self).__init__(
            "Threadlocals parser to get keyword %s from request redefined."
            % keyword)

class ThreadLocals(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""

    __parsers = {}

    @classmethod
    def add_parser(cls, kw, func):
        """
        Add a function to parse a request, get an object, and store it in
        thread locals storage
        """
        if kw in cls.__parsers:
            raise ParserRedefined(kw)

        cls.__parsers[kw] = func

    def process_request(self, request):
        """Parse request and set keywords"""
        d = {}
        for kw, func in self.__parsers.items():
            d[kw] = func(request)
        push_frame(**d)
        return None

    def process_response(self, request, response):
        """Reset thread locals"""
        pop_frame()
        return response
    <|endoftext|>


<commit_before>#!/usr/bin/python
# Copyright (c) 2008-2009 AG Projects
# Author: Denis Bilenko
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import sys
import os
import sqlite3
import glob

REPO_URL = 'http://bitbucket.org/denis/eventlet'

hubs_order = ['poll', 'selects', 'libevent', 'libev', 'twistedr/selectreactor', 'twistedr/pollreactor', 'twistedr/epollreactor']

def make_table(database):
    c = sqlite3.connect(database)
    res = c.execute(('select command_record.id, testname, hub, runs, errors, fails, '
                     'timeouts, exitcode, stdout from parsed_command_record join '
                     'command_record on parsed_command_record.id=command_record.id ')).fetchall()
    table = {} # testname -> hub -> test_result (runs, errors, fails, timeouts)
    tests = set()
    for id, testname, hub, runs, errors, fails, timeouts, exitcode, stdout in res:
        tests.add(testname)
        test_result = TestResult(runs, errors, fails, timeouts, exitcode, id, stdout)
        table.setdefault(testname, {})[hub] = test_result
    return table, sorted(tests)

def calc_hub_stats(table):
    hub_stats = {} # hub -> cumulative test_result
    for testname in table:
        for hub in table[testname]:
            test_result = table[testname][hub]
            hub_stats.setdefault(hub, TestResult(0,0,0,0)).__iadd__(test_result)
    hubs = hub_stats.items()
    hub_names = sorted(hub_stats.keys())
    def get_order(hub):
        try:
            return hubs_order.index(hub)
        except ValueError:
            return 100 + hub_names.index(hub)
    hubs.sort(key=lambda (hub, stats): get_order(hub))
    return hub_stats, [x[0] for x in hubs]

class TestResult:

    def __init__(self, runs, errors, fails, timeouts, exitcode=None, id=None, output=None):
        self.runs = max(runs, 0)
        self.errors = max(errors, 0)
        self.fails = max(fails, 0)
        self.timeouts = max(timeouts, 0)
        self.exitcode = exitcode
        self.id = id
        self.output = output

    @property
    def passed(self):
        return max(0, self.runs - self.errors - self.fails)

    @property
    def failed(self):
        return self.errors + self.fails

    @property
    def total(self):
        return self.runs + self.timeouts

    @property
    def percentage(self):
        return float(self.passed) / self.total

    def __iadd__(self, other):
        self.runs += other.runs
        self.errors += other.errors
        self.fails += other.fails
        self.timeouts += other.timeouts
        if self.exitcode != other.exitcode:
            self.exitcode = None
        self.id = None
        self.output = None

    def color(self):
        if self.id is None:
            return 'white'
        if self.timeouts or self.exitcode in [7, 9, 10]:
            return 'red'
        elif self.errors or self.fails or self.exitcode:
            return 'yellow'
        else:
            return '"#72ff75"'

    def warnings(self):
        r = []
        if not self.failed and not self.timeouts:
            if self.exitcode in [7, 9, 10]:
                r += ['TIMEOUT']
            if self.exitcode:
                r += ['exitcode=%s' % self.exitcode]
            if self.output is not None:
                output = self.output.lower()
                warning = output.count('warning')
                if warning:
                    r += ['%s warnings' % warning]
                tracebacks = output.count('traceback')
                if tracebacks:
                    r += ['%s tracebacks' % tracebacks]
        return r

    def text(self):
        errors = []
        if self.fails:
            errors += ['%s failed' % self.fails]
        if self.errors:
            errors += ['%s raised' % self.errors]
        if self.timeouts:
            errors += ['%s timeout' % self.timeouts]
        errors += self.warnings()
        if self.id is None:
            errors += ['
%s total' % self.total]
        return '\n'.join(["%s passed" % self.passed] + errors).replace(' ', ' ')

    # shorter passed/failed/raised/timeout
    def text_short(self):
        r = '%s/%s/%s' % (self.passed, self.failed, self.timeouts)
        if self.warnings():
            r += '\n' + '\n'.join(self.warnings()).replace(' ', ' ')
        return r

    def format(self):
        text = self.text().replace('\n', '
\n')
        if self.id is None:
            valign = 'bottom'
        else:
            text = '%s' % (self.id, text)
            valign = 'center'
        return '%s	' % (valign, self.color(), text)

def format_testname(changeset, test):
    return '%s' % (REPO_URL, changeset, test, test)

def format_table(table, hubs, tests, hub_stats, changeset):
    r = '
\n
\n\n'
    for hub in hubs:
        r += '%s	\n' % hub
    r += '
\n'

    r += '
Total	'
    for hub in hubs:
        test_result = hub_stats.get(hub)
        if test_result is None:
            r += 'no data	'
        else:
            r += test_result.format() + '\n'
    r += '
'

    r += '

' % (len(hubs)+1)

    for test in tests:
        r += '
%s	' % format_testname(changeset, test)
        for hub in hubs:
            test_result = table[test].get(hub)
            if test_result is None:
                r += 'no data	'
            else:
                r += test_result.format() + '\n'
        r += '
'

    r += '
'
    return r

def format_header(rev, changeset, pyversion):
    result = '

'
    if REPO_URL is None:
        result += 'Eventlet changeset %s: %s' % (rev, changeset)
    else:
        url = '%s/changeset/%s' % (REPO_URL, changeset)
        result += 'Eventlet changeset %s: %s' % (url, rev, changeset)
    result += '

Python version: %s

' % pyversion
    return result

def format_html(table, rev, changeset, pyversion):
    r = ''
    r += format_header(rev, changeset, pyversion)
    r += table
    r += ''
    return r

def generate_raw_results(path, database):
    c = sqlite3.connect(database)
    res = c.execute('select id, stdout from command_record').fetchall()
    for id, out in res:
        file(os.path.join(path, '%s.txt' % id), 'w').write(out.encode('utf-8'))
        sys.stderr.write('.')
    sys.stderr.write('\n')

def main(db):
    full_changeset = '.'.join(db.split('.')[1:-1])
    rev, changeset, pyversion = full_changeset.split('_')
    table, tests = make_table(db)
    hub_stats, hubs = calc_hub_stats(table)
    report = format_html(format_table(table, hubs, tests, hub_stats, changeset), rev, changeset, pyversion)
    path = '../htmlreports/%s' % full_changeset
    try:
        os.makedirs(path)
    except OSError, ex:
        if 'File exists' not in str(ex):
            raise
    file(path + '/index.html', 'w').write(report)
    generate_raw_results(path, db)

if __name__=='__main__':
    if not sys.argv[1:]:
        latest_db = sorted(glob.glob('results.*.db'), key=lambda f: os.stat(f).st_mtime)[-1]
        print latest_db
        sys.argv.append(latest_db)
    for db in sys.argv[1:]:
        main(db)

<commit_msg>Added underlines on hover to html output so fools like me know they are links.<commit_after>#!/usr/bin/python
# Copyright (c) 2008-2009 AG Projects
# Author: Denis Bilenko
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import sys
import os
import sqlite3
import glob

REPO_URL = 'http://bitbucket.org/denis/eventlet'

hubs_order = ['poll', 'selects', 'libevent', 'libev', 'twistedr/selectreactor', 'twistedr/pollreactor', 'twistedr/epollreactor']

def make_table(database):
    c = sqlite3.connect(database)
    res = c.execute(('select command_record.id, testname, hub, runs, errors, fails, '
                     'timeouts, exitcode, stdout from parsed_command_record join '
                     'command_record on parsed_command_record.id=command_record.id ')).fetchall()
    table = {} # testname -> hub -> test_result (runs, errors, fails, timeouts)
    tests = set()
    for id, testname, hub, runs, errors, fails, timeouts, exitcode, stdout in res:
        tests.add(testname)
        test_result = TestResult(runs, errors, fails, timeouts, exitcode, id, stdout)
        table.setdefault(testname, {})[hub] = test_result
    return table, sorted(tests)

def calc_hub_stats(table):
    hub_stats = {} # hub -> cumulative test_result
    for testname in table:
        for hub in table[testname]:
            test_result = table[testname][hub]
            hub_stats.setdefault(hub, TestResult(0,0,0,0)).__iadd__(test_result)
    hubs = hub_stats.items()
    hub_names = sorted(hub_stats.keys())
    def get_order(hub):
        try:
            return hubs_order.index(hub)
        except ValueError:
            return 100 + hub_names.index(hub)
    hubs.sort(key=lambda (hub, stats): get_order(hub))
    return hub_stats, [x[0] for x in hubs]

class TestResult:

    def __init__(self, runs, errors, fails, timeouts, exitcode=None, id=None, output=None):
        self.runs = max(runs, 0)
        self.errors = max(errors, 0)
        self.fails = max(fails, 0)
        self.timeouts = max(timeouts, 0)
        self.exitcode = exitcode
        self.id = id
        self.output = output

    @property
    def passed(self):
        return max(0, self.runs - self.errors - self.fails)

    @property
    def failed(self):
        return self.errors + self.fails

    @property
    def total(self):
        return self.runs + self.timeouts

    @property
    def percentage(self):
        return float(self.passed) / self.total

    def __iadd__(self, other):
        self.runs += other.runs
        self.errors += other.errors
        self.fails += other.fails
        self.timeouts += other.timeouts
        if self.exitcode != other.exitcode:
            self.exitcode = None
        self.id = None
        self.output = None

    def color(self):
        if self.id is None:
            return 'white'
        if self.timeouts or self.exitcode in [7, 9, 10]:
            return 'red'
        elif self.errors or self.fails or self.exitcode:
            return 'yellow'
        else:
            return '"#72ff75"'

    def warnings(self):
        r = []
        if not self.failed and not self.timeouts:
            if self.exitcode in [7, 9, 10]:
                r += ['TIMEOUT']
            if self.exitcode:
                r += ['exitcode=%s' % self.exitcode]
            if self.output is not None:
                output = self.output.lower()
                warning = output.count('warning')
                if warning:
                    r += ['%s warnings' % warning]
                tracebacks = output.count('traceback')
                if tracebacks:
                    r += ['%s tracebacks' % tracebacks]
        return r

    def text(self):
        errors = []
        if self.fails:
            errors += ['%s failed' % self.fails]
        if self.errors:
            errors += ['%s raised' % self.errors]
        if self.timeouts:
            errors += ['%s timeout' % self.timeouts]
        errors += self.warnings()
        if self.id is None:
            errors += ['
%s total' % self.total]
        return '\n'.join(["%s passed" % self.passed] + errors).replace(' ', ' ')

    # shorter passed/failed/raised/timeout
    def text_short(self):
        r = '%s/%s/%s' % (self.passed, self.failed, self.timeouts)
        if self.warnings():
            r += '\n' + '\n'.join(self.warnings()).replace(' ', ' ')
        return r

    def format(self):
        text = self.text().replace('\n', '
\n')
        if self.id is None:
            valign = 'bottom'
        else:
            text = '%s' % (self.id, text)
            valign = 'center'
        return '%s	' % (valign, self.color(), text)

def format_testname(changeset, test):
    return '%s' % (REPO_URL, changeset, test, test)

def format_table(table, hubs, tests, hub_stats, changeset):
    r = '
\n
\n\n'
    for hub in hubs:
        r += '%s	\n' % hub
    r += '
\n'

    r += '
Total	'
    for hub in hubs:
        test_result = hub_stats.get(hub)
        if test_result is None:
            r += 'no data	'
        else:
            r += test_result.format() + '\n'
    r += '
'

    r += '

' % (len(hubs)+1)

    for test in tests:
        r += '
%s	' % format_testname(changeset, test)
        for hub in hubs:
            test_result = table[test].get(hub)
            if test_result is None:
                r += 'no data	'
            else:
                r += test_result.format() + '\n'
        r += '
'

    r += '
'
    return r

def format_header(rev, changeset, pyversion):
    result = '

'
    if REPO_URL is None:
        result += 'Eventlet changeset %s: %s' % (rev, changeset)
    else:
        url = '%s/changeset/%s' % (REPO_URL, changeset)
        result += 'Eventlet changeset %s: %s' % (url, rev, changeset)
    result += '

Python version: %s

' % pyversion
    return result

def format_html(table, rev, changeset, pyversion):
    r = ''
    r += format_header(rev, changeset, pyversion)
    r += table
    r += ''
    return r

def generate_raw_results(path, database):
    c = sqlite3.connect(database)
    res = c.execute('select id, stdout from command_record').fetchall()
    for id, out in res:
        file(os.path.join(path, '%s.txt' % id), 'w').write(out.encode('utf-8'))
        sys.stderr.write('.')
    sys.stderr.write('\n')

def main(db):
    full_changeset = '.'.join(db.split('.')[1:-1])
    rev, changeset, pyversion = full_changeset.split('_')
    table, tests = make_table(db)
    hub_stats, hubs = calc_hub_stats(table)
    report = format_html(format_table(table, hubs, tests, hub_stats, changeset), rev, changeset, pyversion)
    path = '../htmlreports/%s' % full_changeset
    try:
        os.makedirs(path)
    except OSError, ex:
        if 'File exists' not in str(ex):
            raise
    file(path + '/index.html', 'w').write(report)
    generate_raw_results(path, db)

if __name__=='__main__':
    if not sys.argv[1:]:
        latest_db = sorted(glob.glob('results.*.db'), key=lambda f: os.stat(f).st_mtime)[-1]
        print latest_db
        sys.argv.append(latest_db)
    for db in sys.argv[1:]:
        main(db)

<|endoftext|>


<commit_before>{
    "name" : "OpenERP Web web",
    "category" : "Hidden",
    "version" : "2.0",
    "depends" : [],
    'active': False,
    'js' : [
        "../web/static/lib/datejs/date-en-US.js",
        "../web/static/lib/jquery/jquery-1.6.2.js",
        "../web/static/lib/json/json2.js",
        "../web/static/lib/qweb/qweb2.js",
        "../web/static/lib/underscore/underscore.js",
        "../web/static/lib/underscore/underscore.string.js",
        "../web/static/src/js/boot.js",
        "../web/static/src/js/core.js",
        "../web/static/src/js/formats.js",
        "../web/static/src/js/chrome.js",
        "../web/static/src/js/data.js",
    ],
    'css' : [
    ],
}
<commit_msg>[FIX] webrpc double load jquery<commit_after>{
    "name" : "OpenERP Web web",
    "category" : "Hidden",
    "version" : "2.0",
    "depends" : [],
    "installable" : False,
    'active': False,
    'js' : [
        "../web/static/lib/datejs/date-en-US.js",
        "../web/static/lib/jquery/jquery-1.6.2.js",
        "../web/static/lib/json/json2.js",
        "../web/static/lib/qweb/qweb2.js",
        "../web/static/lib/underscore/underscore.js",
        "../web/static/lib/underscore/underscore.string.js",
        "../web/static/src/js/boot.js",
        "../web/static/src/js/core.js",
        "../web/static/src/js/formats.js",
        "../web/static/src/js/chrome.js",
        "../web/static/src/js/data.js",
    ],
    'css' : [
    ],
}
<|endoftext|>


<commit_before>import asyncio
import itertools
import json
from functools import wraps

from aiorest_validator.fields.base import BaseField
from aiorest_validator.fields.manager import ManagerField

__all__ = ['validator_factory']

def _loads(data):
    try:
        return json.loads(data)
    except json.JSONDecodeError:
        return {}

def validator_factory(loads=_loads):
    @asyncio.coroutine
    def validator(app, handler):
        if getattr(handler, 'skip_validate', False):
            return handler

        cls_field = getattr(handler, 'Field', None)

        if not cls_field:
            return handler
        else:
            fields = (
                (name, getattr(cls_field, name))
                for name in dir(cls_field)
                if isinstance(getattr(cls_field, name), BaseField)
            )

        load = getattr(handler, 'validator_loads', None) or loads

        @wraps(handler)
        @asyncio.coroutine
        def wrapper(request):
            data = dict(itertools.chain(
                request.match_info.items(),
                request.GET.items(),
                load((yield from request.text())).items()))

            manager = ManagerField(fields, request, data)
            yield from manager.init()
            request['fields'] = manager.manager_dict
            return (yield from handler(request))

        return wrapper

    return validator
<commit_msg>fix python 3.5 JSONDecodeError<commit_after>import asyncio
import itertools
import json
import sys
from functools import wraps

from aiorest_validator.fields.base import BaseField
from aiorest_validator.fields.manager import ManagerField

PY_35 = sys.version_info >= (3, 5)
if PY_35:
    from json import JSONDecodeError
else:
    JSONDecodeError = ValueError

__all__ = ['validator_factory']

def _loads(data):
    try:
        return json.loads(data)
    except JSONDecodeError:
        return {}

def validator_factory(loads=_loads):
    @asyncio.coroutine
    def validator(app, handler):
        if getattr(handler, 'skip_validate', False):
            return handler

        cls_field = getattr(handler, 'Field', None)

        if not cls_field:
            return handler
        else:
            fields = (
                (name, getattr(cls_field, name))
                for name in dir(cls_field)
                if isinstance(getattr(cls_field, name), BaseField)
            )

        load = getattr(handler, 'validator_loads', None) or loads

        @wraps(handler)
        @asyncio.coroutine
        def wrapper(request):
            data = dict(itertools.chain(
                request.match_info.items(),
                request.GET.items(),
                load((yield from request.text())).items()))

            manager = ManagerField(fields, request, data)
            yield from manager.init()
            request['fields'] = manager.manager_dict
            return (yield from handler(request))

        return wrapper

    return validator
<|endoftext|>


<commit_before>from gears.environment import Suffixes
from unittest2 import TestCase

class SuffixesTests(TestCase):

    def setUp(self):
        self.suffixes = Suffixes()

    def test_register_root_extensions(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.assertEqual(
            self.suffixes,
            [{'extensions': ['.css'], 'mimetype': 'text/css'},
             {'extensions': ['.txt'], 'mimetype': 'text/plain'}])

    def test_register_extension_to_mimetype(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(
            self.suffixes,
            [{'extensions': ['.css'], 'mimetype': 'text/css'},
             {'extensions': ['.txt'], 'mimetype': 'text/plain'},
             {'extensions': ['.css', '.styl'], 'mimetype': None}])

    def test_register_extension_to_none(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.suffixes.register('.tmpl')
        self.assertEqual(
            self.suffixes,
            [{'extensions': ['.css'], 'mimetype': 'text/css'},
             {'extensions': ['.txt'], 'mimetype': 'text/plain'},
             {'extensions': ['.css', '.styl'], 'mimetype': None},
             {'extensions': ['.css', '.tmpl'], 'mimetype': None},
             {'extensions': ['.txt', '.tmpl'], 'mimetype': None},
             {'extensions': ['.css', '.styl', '.tmpl'], 'mimetype': None}])

    def test_unregister_extension(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.suffixes.register('.tmpl')
        self.suffixes.unregister('.css')
        self.assertEqual(
            self.suffixes,
            [{'extensions': ['.txt'], 'mimetype': 'text/plain'},
             {'extensions': ['.txt', '.tmpl'], 'mimetype': None}])

    def test_find_all(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(self.suffixes.find(), ['.css', '.txt', '.css.styl'])

    def test_find_by_extension(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(self.suffixes.find('.css'), ['.css', '.css.styl'])

    def test_find_by_many_extensions(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(self.suffixes.find('.css', '.styl'), ['.css.styl'])

    def test_find_nothing(self):
        self.assertEqual(self.suffixes.find('.css'), [])
<commit_msg>Improve code formatting in tests<commit_after>from gears.environment import Suffixes
from unittest2 import TestCase

class SuffixesTests(TestCase):

    def setUp(self):
        self.suffixes = Suffixes()

    def test_register_root_extensions(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.assertEqual(self.suffixes, [
            {'extensions': ['.css'], 'mimetype': 'text/css'},
            {'extensions': ['.txt'], 'mimetype': 'text/plain'},
        ])

    def test_register_extension_to_mimetype(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(self.suffixes, [
            {'extensions': ['.css'], 'mimetype': 'text/css'},
            {'extensions': ['.txt'], 'mimetype': 'text/plain'},
            {'extensions': ['.css', '.styl'], 'mimetype': None},
        ])

    def test_register_extension_to_none(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.suffixes.register('.tmpl')
        self.assertEqual(self.suffixes, [
            {'extensions': ['.css'], 'mimetype': 'text/css'},
            {'extensions': ['.txt'], 'mimetype': 'text/plain'},
            {'extensions': ['.css', '.styl'], 'mimetype': None},
            {'extensions': ['.css', '.tmpl'], 'mimetype': None},
            {'extensions': ['.txt', '.tmpl'], 'mimetype': None},
            {'extensions': ['.css', '.styl', '.tmpl'], 'mimetype': None},
        ])

    def test_unregister_extension(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.suffixes.register('.tmpl')
        self.suffixes.unregister('.css')
        self.assertEqual(self.suffixes, [
            {'extensions': ['.txt'], 'mimetype': 'text/plain'},
            {'extensions': ['.txt', '.tmpl'], 'mimetype': None},
        ])

    def test_find_all(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(self.suffixes.find(), ['.css', '.txt', '.css.styl'])

    def test_find_by_extension(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(self.suffixes.find('.css'), ['.css', '.css.styl'])

    def test_find_by_many_extensions(self):
        self.suffixes.register('.css', root=True, mimetype='text/css')
        self.suffixes.register('.txt', root=True, mimetype='text/plain')
        self.suffixes.register('.styl', to='text/css')
        self.assertEqual(self.suffixes.find('.css', '.styl'), ['.css.styl'])

    def test_find_nothing(self):
        self.assertEqual(self.suffixes.find('.css'), [])
<|endoftext|>


<commit_before>import logging
import urlparse
from celery.task.base import Task
from django.contrib.auth.models import User
from billy.core import db, elasticsearch, settings, user_db
from billy.utils.fulltext import plaintext

class ElasticSearchPush(Task):
    # results go into ES
    ignore_result = True
    _log = logging.getLogger('billy.tasks.ElasticSearchPush')

    def run(self, doc_id):
        doc = db.tracked_versions.find_one(doc_id)

        try:
            text = plaintext(doc_id)

            elasticsearch.index(dict(doc, text=text), 'bills', 'version',
                                id=doc_id)
            db.tracked_versions.update({'_id': doc_id},
                                       {'$set': {'_elasticsearch': True}},
                                       safe=True)
            self._log.info('pushed %s to ElasticSearch', doc_id)

        except Exception:
            self._log.warning('error pushing %s to ElasticSearch', doc_id,
                              exc_info=True)
            raise

class ScoutPush(Task):
    # no results needed
    ignore_result = True
    _log = logging.getLogger('billy.tasks.ScoutPush')

    def run(self, user_id):
        user = User.objects.get(pk=user_id)
        payload = {'email': user.email,
                   'secret_key': settings.SCOUT_SECRET_KEY,
                   'source': settings.SCOUT_SOURCE,
                   'notifications': 'email_daily'}
        interests = []
        for favorite in user_db.favorites.find({'user_id': user_id}):
            if favorite['obj_type'] in ('legislator', 'bill'):
                interest = {'interest_type': 'item',
                            'item_type': 'state_' + favorite['obj_type'],
                            'item_id': favorite['obj_type'],
                           }
            elif favorite['obj_type'] == 'search':
                params = urlparse.parse_qs(favorite['search_params'])
                search_text = params.pop('search_text')
                # TODO: handle session, status, type, sponsor__leg_id
                interest = {
                    'interest_type': 'search',
                    'search_type': 'state_bills',
                    'query_type': 'advanced',
                    'in': search_text,
                    'filters': {'state': favorite['search_abbr'].upper()}
                }
            else:
                self._log.warning('Unknown favorite type: %s',
                                  favorite['obj_type'])
                continue

            interest['active'] = favorite['is_favorite']
            interest['timestamp'] = favorite['timestamp']
            interests.append(interest)

        self._log.info('pushing %s interests for %s', len(interests),
                       payload['email'])

        # TODO: push to scout & handle response
<commit_msg>Get basic scout task push working<commit_after>'''
A few notes from our initial tests of this (Thom 12/20/2012)
- the user search page allows chamber to be a checkbox with multiple values
  but the api requires a string (upper or lower)
- Some keys don't appear to be supported in the api:
  - type
  - status (checkbox/list)
  So we lose them in the post to Scout unless we add them to the api. this
  just means people will think they're getting alerts for a narrower
  set of contstraints, but will get (ie.,

'''
# import sys, os
# sys.path.append('/home/thom/sunlight/openstates/site')
# os.environ['DJANGO_SETTINGS_MODULE'] = 'openstates_site.settings'

import json
import logging
import urlparse
#from celery.task.base import Task
from django.contrib.auth.models import User
from billy.core import db, elasticsearch, settings, user_db
from billy.utils import JSONEncoderPlus
from billy.utils.fulltext import plaintext

import requests

class Task(object):
    '''A dummy task to temporarily remove celery from the equation.
    '''

class ElasticSearchPush(Task):
    # results go into ES
    ignore_result = True
    _log = logging.getLogger('billy.tasks.ElasticSearchPush')

    def run(self, doc_id):
        doc = db.tracked_versions.find_one(doc_id)

        try:
            text = plaintext(doc_id)

            elasticsearch.index(dict(doc, text=text), 'bills', 'version',
                                id=doc_id)
            db.tracked_versions.update({'_id': doc_id},
                                       {'$set': {'_elasticsearch': True}},
                                       safe=True)
            self._log.info('pushed %s to ElasticSearch', doc_id)

        except Exception:
            self._log.warning('error pushing %s to ElasticSearch', doc_id,
                              exc_info=True)
            raise

class ScoutPush(Task):
    # no results needed
    ignore_result = True
    _log = logging.getLogger('billy.tasks.ScoutPush')

    def run(self, user_id):
        user = User.objects.get(pk=user_id)
        payload = {'email': user.email,
                   'secret_key': settings.SCOUT_SECRET_KEY,
                   'service': settings.SCOUT_SERVICE,
                   'notifications': 'email_daily'}
        interests = []
        for favorite in user_db.favorites.find({'user_id': user_id}):
            if favorite['obj_type'] in ('legislator', 'bill', 'committee'):
                interest = {'interest_type': 'item',
                            'item_type': 'state_' + favorite['obj_type'],
                            'item_id': favorite['obj_id'],
                           }
            elif favorite['obj_type'] == 'search':
                params = urlparse.parse_qs(favorite['search_params'])
                search_text = params.pop('search_text').pop()
                interest = {
                    'interest_type': 'search',
                    'search_type': 'state_bills',
                    'query_type': 'advanced',
                    'in': search_text,
                    'filters': self._translate_filter_data(params)
                }

            else:
                self._log.warning('Unknown favorite type: %s',
                                  favorite['obj_type'])
                continue

            interest['active'] = favorite['is_favorite']
            interest['changed_at'] = favorite['timestamp']
            interests.append(interest)

        payload['interests'] = interests
        self._log.info('pushing %s interests for %s', len(interests),
                       payload['email'])

        url = 'http://scout.sunlightlabs.com/remote/service/sync'
        payload = json.dumps(payload, cls=JSONEncoderPlus)
        resp = requests.post(url, data=payload)

    def _translate_filter_data(self, params):
        '''Edit the favorite['search_params'] object and make them
        match the param names used in an api request.
        '''
        # Two api params have no analog in the front-end search: bill_id__in
        # and updated_since
        api_param_names = 'q state search_window chamber subjects sponsor_id'
        api_param_name_set = set(api_param_names.split())

        result = {}

        api_param_names = {
            'search_text': 'q',
            'search_state': 'state',
            'session': 'search_window',
            'sponsor__leg_id': 'spnosor_id'
            }

        for k, v in params.items():
            print k, v
            if k == 'session':
                v = 'session:' + v.pop()

            elif k == 'search_state':
                # Scout expects uppercase.
                v = v.upper()

            elif k == 'chamber':
                # XXX Hack: the front-end search allows users to select
                # multiple chambers, but the api method only accepts one.
                v = v.pop()

            api_param_name = api_param_names.get(k)
            if api_param_name is None:
                api_param_name = k

            if api_param_name in api_param_name_set:
                result[api_param_name] = v

        return result

def main():
    for user in user_db.profiles.find():
        ScoutPush().run(user['_id'])

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


<commit_before># test_filtering_postgresql.py - filtering tests for PostgreSQL
#
# Copyright 2011 Lincoln de Sousa <lincoln@comum.org>.
# Copyright 2012, 2013, 2014, 2015, 2016 Jeffrey Finkelstein
#           <jeffrey.finkelstein@gmail.com> and contributors.
#
# This file is part of Flask-Restless.
#
# Flask-Restless is distributed under both the GNU Affero General Public
# License version 3 and under the 3-clause BSD license. For more
# information, see LICENSE.AGPL and LICENSE.BSD.
"""Unit tests for PostgreSQL-specific filtering operators."""

# The psycopg2cffi import is required for testing on PyPy. CPython can
# use psycopg2, but PyPy can only use psycopg2cffi.
try:
    import psycopg2  # noqa
except ImportError:
    from psycopg2cffi import compat
    compat.register()
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy.dialects.postgresql import INET
from sqlalchemy.exc import OperationalError

from .helpers import loads
from .test_filtering import SearchTestBase

class TestNetworkOperators(SearchTestBase):
    """Unit tests for the network address operators in PostgreSQL.

    For more information, see `Network Address Functions and Operators`_
    in the PostgreSQL documentation.

    .. _Network Address Functions and Operators:
       http://www.postgresql.org/docs/current/interactive/functions-net.html

    """

    def setUp(self):
        super(TestNetworkOperators, self).setUp()

        class Network(self.Base):
            __tablename__ = 'network'
            id = Column(Integer, primary_key=True)
            address = Column(INET)

        self.Network = Network
        # This try/except skips the tests if we are unable to create the
        # tables in the PostgreSQL database.
        try:
            self.Base.metadata.create_all()
        except OperationalError as e:
            raise e
            # self.skipTest('error creating tables in PostgreSQL database')
        self.manager.create_api(Network)

    def database_uri(self):
        """Return a PostgreSQL connection URI.

        Since this test case is for operators specific to PostgreSQL, we
        return a PostgreSQL connection URI. The particular
        Python-to-PostgreSQL adapter we are using is currently
        `Psycopg`_.

        .. _Psycopg: http://initd.org/psycopg/

        """
        return 'postgresql+psycopg2://postgres@localhost:5432/testdb'

    def test_is_not_equal(self):
        """Test for the ``<>`` ("is not equal") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1.5' <> inet '192.168.1.4'

        """
        network1 = self.Network(id=1, address='192.168.1.5')
        network2 = self.Network(id=2, address='192.168.1.4')
        self.session.add_all([network1, network2])
        self.session.commit()
        filters = [dict(name='address', op='<>', val='192.168.1.4')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1'] == sorted(network['id'] for network in networks)

    def test_is_contained_by(self):
        """Test for the ``<<`` ("is contained by") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1.5' << inet '192.168.1/24'

        """
        network1 = self.Network(id=1, address='192.168.1.5')
        network2 = self.Network(id=2, address='192.168.2.1')
        self.session.add_all([network1, network2])
        self.session.commit()
        filters = [dict(name='address', op='<<', val='192.168.1/24')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1'] == sorted(network['id'] for network in networks)

    def test_is_contained_by_or_equals(self):
        """Test for the ``<<=`` ("is contained by or equals") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' <<= inet '192.168.1/24'

        """
        network1 = self.Network(id=1, address='192.168.1/24')
        network2 = self.Network(id=2, address='192.168.1.5')
        network3 = self.Network(id=3, address='192.168.2.1')
        self.session.add_all([network1, network2, network3])
        self.session.commit()
        filters = [dict(name='address', op='<<=', val='192.168.1/24')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1', '2'] == sorted(network['id'] for network in networks)

    def test_contains(self):
        """Test for the ``>>`` ("contains") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' >> inet '192.168.1.5'

        """
        network1 = self.Network(id=1, address='192.168.1/24')
        network2 = self.Network(id=2, address='192.168.2/24')
        self.session.add_all([network1, network2])
        self.session.commit()
        filters = [dict(name='address', op='>>', val='192.168.1.5')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1'] == sorted(network['id'] for network in networks)

    def test_contains_or_equals(self):
        """Test for the ``>>=`` ("contains or equals") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' >>= inet '192.168.1/24'

        """
        network1 = self.Network(id=1, address='192.168.1/24')
        network2 = self.Network(id=2, address='192.168/16')
        network3 = self.Network(id=3, address='192.168.2/24')
        self.session.add_all([network1, network2, network3])
        self.session.commit()
        filters = [dict(name='address', op='>>=', val='192.168.1/24')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1', '2'] == sorted(network['id'] for network in networks)

    def test_contains_or_is_contained_by(self):
        """Test for the ``&&`` ("contains or is contained by") operator.

        .. warning::

           This operation is only available in PostgreSQL 9.4 or later.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' && inet '192.168.1.80/28'

        """
        # network1 contains the queried subnet
        network1 = self.Network(id=1, address='192.168.1/24')
        # network2 is contained by the queried subnet
        network2 = self.Network(id=2, address='192.168.1.81/28')
        # network3 is neither
        network3 = self.Network(id=3, address='192.168.2.1')
        self.session.add_all([network1, network2, network3])
        self.session.commit()
        filters = [dict(name='address', op='&&', val='192.168.1.80/28')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1', '2'] == sorted(network['id'] for network in networks)
<commit_msg>Skips PostgreSQL tests if creating tables fails<commit_after># test_filtering_postgresql.py - filtering tests for PostgreSQL
#
# Copyright 2011 Lincoln de Sousa <lincoln@comum.org>.
# Copyright 2012, 2013, 2014, 2015, 2016 Jeffrey Finkelstein
#           <jeffrey.finkelstein@gmail.com> and contributors.
#
# This file is part of Flask-Restless.
#
# Flask-Restless is distributed under both the GNU Affero General Public
# License version 3 and under the 3-clause BSD license. For more
# information, see LICENSE.AGPL and LICENSE.BSD.
"""Unit tests for PostgreSQL-specific filtering operators."""

# The psycopg2cffi import is required for testing on PyPy. CPython can
# use psycopg2, but PyPy can only use psycopg2cffi.
try:
    import psycopg2  # noqa
except ImportError:
    from psycopg2cffi import compat
    compat.register()
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy.dialects.postgresql import INET
from sqlalchemy.exc import OperationalError

from .helpers import loads
from .test_filtering import SearchTestBase

class TestNetworkOperators(SearchTestBase):
    """Unit tests for the network address operators in PostgreSQL.

    For more information, see `Network Address Functions and Operators`_
    in the PostgreSQL documentation.

    .. _Network Address Functions and Operators:
       http://www.postgresql.org/docs/current/interactive/functions-net.html

    """

    def setUp(self):
        super(TestNetworkOperators, self).setUp()

        class Network(self.Base):
            __tablename__ = 'network'
            id = Column(Integer, primary_key=True)
            address = Column(INET)

        self.Network = Network
        # This try/except skips the tests if we are unable to create the
        # tables in the PostgreSQL database.
        try:
            self.Base.metadata.create_all()
        except OperationalError as e:
            self.skipTest('error creating tables in PostgreSQL database')
        self.manager.create_api(Network)

    def database_uri(self):
        """Return a PostgreSQL connection URI.

        Since this test case is for operators specific to PostgreSQL, we
        return a PostgreSQL connection URI. The particular
        Python-to-PostgreSQL adapter we are using is currently
        `Psycopg`_.

        .. _Psycopg: http://initd.org/psycopg/

        """
        return 'postgresql+psycopg2://postgres@localhost:5432/testdb'

    def test_is_not_equal(self):
        """Test for the ``<>`` ("is not equal") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1.5' <> inet '192.168.1.4'

        """
        network1 = self.Network(id=1, address='192.168.1.5')
        network2 = self.Network(id=2, address='192.168.1.4')
        self.session.add_all([network1, network2])
        self.session.commit()
        filters = [dict(name='address', op='<>', val='192.168.1.4')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1'] == sorted(network['id'] for network in networks)

    def test_is_contained_by(self):
        """Test for the ``<<`` ("is contained by") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1.5' << inet '192.168.1/24'

        """
        network1 = self.Network(id=1, address='192.168.1.5')
        network2 = self.Network(id=2, address='192.168.2.1')
        self.session.add_all([network1, network2])
        self.session.commit()
        filters = [dict(name='address', op='<<', val='192.168.1/24')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1'] == sorted(network['id'] for network in networks)

    def test_is_contained_by_or_equals(self):
        """Test for the ``<<=`` ("is contained by or equals") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' <<= inet '192.168.1/24'

        """
        network1 = self.Network(id=1, address='192.168.1/24')
        network2 = self.Network(id=2, address='192.168.1.5')
        network3 = self.Network(id=3, address='192.168.2.1')
        self.session.add_all([network1, network2, network3])
        self.session.commit()
        filters = [dict(name='address', op='<<=', val='192.168.1/24')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1', '2'] == sorted(network['id'] for network in networks)

    def test_contains(self):
        """Test for the ``>>`` ("contains") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' >> inet '192.168.1.5'

        """
        network1 = self.Network(id=1, address='192.168.1/24')
        network2 = self.Network(id=2, address='192.168.2/24')
        self.session.add_all([network1, network2])
        self.session.commit()
        filters = [dict(name='address', op='>>', val='192.168.1.5')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1'] == sorted(network['id'] for network in networks)

    def test_contains_or_equals(self):
        """Test for the ``>>=`` ("contains or equals") operator.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' >>= inet '192.168.1/24'

        """
        network1 = self.Network(id=1, address='192.168.1/24')
        network2 = self.Network(id=2, address='192.168/16')
        network3 = self.Network(id=3, address='192.168.2/24')
        self.session.add_all([network1, network2, network3])
        self.session.commit()
        filters = [dict(name='address', op='>>=', val='192.168.1/24')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1', '2'] == sorted(network['id'] for network in networks)

    def test_contains_or_is_contained_by(self):
        """Test for the ``&&`` ("contains or is contained by") operator.

        .. warning::

           This operation is only available in PostgreSQL 9.4 or later.

        For example:

        .. sourcecode:: postgresql

           inet '192.168.1/24' && inet '192.168.1.80/28'

        """
        # network1 contains the queried subnet
        network1 = self.Network(id=1, address='192.168.1/24')
        # network2 is contained by the queried subnet
        network2 = self.Network(id=2, address='192.168.1.81/28')
        # network3 is neither
        network3 = self.Network(id=3, address='192.168.2.1')
        self.session.add_all([network1, network2, network3])
        self.session.commit()
        filters = [dict(name='address', op='&&', val='192.168.1.80/28')]
        response = self.search('/api/network', filters)
        document = loads(response.data)
        networks = document['data']
        assert ['1', '2'] == sorted(network['id'] for network in networks)
<|endoftext|>


<commit_before>from django import template
import re

from django.conf.urls import url
from django.urls import reverse

class _Menu:
    parents = []
    childs = []
    models_icon = {}

    def clear(self):
        self.parents = []
        self.childs = []

    def add(self, label, link='', icon='', id='', parent=''):

        if id == '':
            id = label

        if parent != '':
            child = {
                id: {
                    'label': label,
                    'link': link,
                    'icon': icon,
                    'childs': []
                }
            }

            self.childs.append(child)

            for idx, parent_item in enumerate(self.parents):

                if parent in parent_item:
                    self.parents[idx][parent]['childs'].append(child)
                else:
                    for idx, child_item in enumerate(self.childs):
                        if parent in child_item:
                            self.childs[idx][parent]['childs'].append(child)

        else:
            self.parents.append({
                id: {
                    'label': label,
                    'link': link,
                    'icon': icon,
                    'childs': []
                }
            })

    def render(self, context, menus={}):
        r = ''

        if len(menus) <= 0:
            # sorted(self.parents)
            menus = self.parents

            r = '
 Home
'

        for group in menus:
            key = [key for key in group][0]
            icon = ''

            if group[key]['icon'] != '':
                if re.match(r'\<([a-z]*)\b[^\>]*\>(.*?)\<\/\1\>', group[key]['icon']):
                    icon = group[key]['icon']
                else:
                    icon = '' % (group[key]['icon'])

            if len(group[key]['childs']) > 0:
                r += '
%s %s
\n' % (
                    icon, group[key]['label'])

                r += self.render(context, group[key]['childs'])

                r += '

\n'

            else:
                r += '
%s %s
\n' % (
                    group[key]['link'], icon, group[key]['label'])

        return r

    def admin_apps(self, context, r):

        for app in context['available_apps']:
            r += '
 %s
\n' % (
                app['name'])

            for model in app['models']:
                if 'add_url' in model:
                    url = model['add_url']

                if 'change_url' in model:
                    url = model['change_url']

                # if 'delete_url' in model:
                #     url = model['delete_url']

                if 'admin_url' in model:
                    url = model['admin_url']

                icon = ''
                if model['object_name'].title() in self.models_icon:
                    if self.models_icon[model['object_name'].title()] != '':
                        if re.match(r'\<([a-z]*)\b[^\>]*\>(.*?)\<\/\1\>', self.models_icon[model['object_name'].title()]):
                            icon = self.models_icon[model['object_name'].title()]
                        else:
                            icon = '' % (self.models_icon[model['object_name'].title()])

                r += '
%s %s
' % (url, icon, model['name'])

            r += '

\n'

        return r

    def set_model_icon(self, model_name, icon):
        self.models_icon[model_name.title()] = icon

    def get_model_icon(self, context):

        icon = ''
        if context['model']['object_name'].title() in self.models_icon:

            if self.models_icon[context['model']['object_name'].title()] != '':
                if re.match(r'\<([a-z]*)\b[^\>]*\>(.*?)\<\/\1\>', self.models_icon[context['model']['object_name'].title()]):
                    icon = self.models_icon[context['model']['object_name']]
                else:
                    icon = '' % (self.models_icon[context['model']['object_name'].title()])

        return icon

register = template.Library()

Menu = _Menu()

@register.simple_tag(takes_context=True)
def menu(context):
    # user = context['request'].user

    return Menu.admin_apps(context, Menu.render(context))

@register.simple_tag(takes_context=True)
def icon(context):
    return Menu.get_model_icon(context)

<commit_msg>add active menu<commit_after>from django import template
import re

from django.conf.urls import url
from django.urls import reverse

class _Menu:
    parents = []
    childs = []
    models_icon = {}

    def clear(self):
        self.parents = []
        self.childs = []

    def add(self, label, link='', icon='', id='', parent=''):

        if id == '':
            id = label

        if parent != '':
            child = {
                id: {
                    'label': label,
                    'link': link,
                    'icon': icon,
                    'childs': []
                }
            }

            self.childs.append(child)

            for idx, parent_item in enumerate(self.parents):

                if parent in parent_item:
                    self.parents[idx][parent]['childs'].append(child)
                else:
                    for idx, child_item in enumerate(self.childs):
                        if parent in child_item:
                            self.childs[idx][parent]['childs'].append(child)

        else:
            self.parents.append({
                id: {
                    'label': label,
                    'link': link,
                    'icon': icon,
                    'childs': []
                }
            })

    def render(self, context, menus={}):
        r = ''

        if len(menus) <= 0:
            # sorted(self.parents)
            menus = self.parents

            r = '
 Home
'

        for group in menus:
            key = [key for key in group][0]
            icon = ''

            if group[key]['icon'] != '':
                if re.match(r'\<([a-z]*)\b[^\>]*\>(.*?)\<\/\1\>', group[key]['icon']):
                    icon = group[key]['icon']
                else:
                    icon = '' % (group[key]['icon'])

            if len(group[key]['childs']) > 0:
                r += '
%s %s
\n' % (
                    icon, group[key]['label'])

                r += self.render(context, group[key]['childs'])

                r += '

\n'

            else:
                r += '
%s %s
\n' % (
                    group[key]['link'], icon, group[key]['label'])

        return r

    def admin_apps(self, context, r):
        from django.core.urlresolvers import resolve
        current_url = context['request'].path

        for app in context['available_apps']:

            if app['app_url'] in current_url:
                r += '
 %s
\n' % (
                    app['name'])
            else:
                r += '
 %s
\n' % (
                    app['name'])

            for model in app['models']:
                if 'add_url' in model:
                    url = model['add_url']

                if 'change_url' in model:
                    url = model['change_url']

                # if 'delete_url' in model:
                #     url = model['delete_url']

                if 'admin_url' in model:
                    url = model['admin_url']

                icon = ''
                if model['object_name'].title() in self.models_icon:
                    if self.models_icon[model['object_name'].title()] != '':
                        if re.match(r'\<([a-z]*)\b[^\>]*\>(.*?)\<\/\1\>', self.models_icon[model['object_name'].title()]):
                            icon = self.models_icon[model['object_name'].title()]
                        else:
                            icon = '' % (self.models_icon[model['object_name'].title()])

                if model['admin_url'] in current_url:
                    r += '
%s %s
' % (url, icon, model['name'])
                else:
                    r += '
%s %s
' % (url, icon, model['name'])

            r += '

\n'

        return r

    def set_model_icon(self, model_name, icon):
        self.models_icon[model_name.title()] = icon

    def get_model_icon(self, context):

        icon = ''
        if context['model']['object_name'].title() in self.models_icon:

            if self.models_icon[context['model']['object_name'].title()] != '':
                if re.match(r'\<([a-z]*)\b[^\>]*\>(.*?)\<\/\1\>', self.models_icon[context['model']['object_name'].title()]):
                    icon = self.models_icon[context['model']['object_name']]
                else:
                    icon = '' % (self.models_icon[context['model']['object_name'].title()])

        return icon

register = template.Library()

Menu = _Menu()

@register.simple_tag(takes_context=True)
def menu(context):
    # user = context['request'].user

    return Menu.admin_apps(context, Menu.render(context))

@register.simple_tag(takes_context=True)
def icon(context):
    return Menu.get_model_icon(context)

<|endoftext|>