<commit_before>from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import user_passes_test, login_required
from .forms import *

# Checks if user has a profile
def profile_check(user):
    return user.is_authenticated() and hasattr(user, 'profile')

def loginTest(request):
    if request.user.is_authenticated():
        return render(request,'errorView.html',{'error_msg':"You are logged in as: "+str(request.user.username)})
    else:
        return render(request,'errorView.html',{'error_msg':"Not Logged In"})

@login_required(login_url='loginTest')
def profileCreate(request):
    registered = False
    if request.method == 'POST':
        user_form = UserForm(data=request.POST, instance=request.user)
        if hasattr(request.user, 'profile'):
            profile_form = ProfileForm(data=request.POST, instance=request.user.profile, files=request.FILES)
        else:
            profile_form = ProfileForm(data=request.POST, files=request.FILES)

        if user_form.is_valid() and profile_form.is_valid():
            user = user_form.save()
            user.save()

            profile = profile_form.save(commit=False)
            profile.user = user

            profile.save()
            registered = True
        else:
            print(user_form.errors, profile_form.errors)
        return redirect('profileView',uname=user.username)
    else:
        user_form = UserForm(instance=request.user)
        if hasattr(request.user, 'profile'):
            profile_form = ProfileForm(instance=request.user.profile)
        else:
            profile_form = ProfileForm()
    return render(request,'profileCreate.html',{'user_form':user_form,'profile_form':profile_form,'registered':registered})

@user_passes_test(profile_check, login_url='profileCreate')
def profileView(request,uname):
    user = get_object_or_404(User,username=uname)
    project_list = Project.objects.filter(owner=user.profile)
    return render(request, 'profileView.html', {'user':user,'project_list':project_list})

@user_passes_test(profile_check, login_url='profileCreate')
def projectCreate(request):
    if request.method == 'POST':
        project_form = ProjectForm(data=request.POST, files=request.FILES)
        if project_form.is_valid():
            project = project_form.save(commit=False)
            project.owner = request.user.profile
            project.save()
        else:
            print(project_form.errors)
        return redirect('projectView',project_id=project.id)

    else:
        project_form = ProjectForm()
    return render(request,'projectCreate.html',{'project_form':project_form})

@user_passes_test(profile_check, login_url='profileCreate')
def projectEdit(request, project_id):
    project = get_object_or_404(Project, pk=project_id)
    if request.user.profile == project.owner:
        if request.method == 'POST':
            project_form = ProjectForm(data=request.POST, instance=project, files=request.FILES)
            if project_form.is_valid():
                project_form.save()
            else:
                print(project_form.errors)
            return redirect('projectView',project_id=project.id)
        else:
            project_form = ProjectForm(instance=project)
            return render(request,'projectEdit.html',{'project_form':project_form,'project':project})
    else:
        return render(request,'errorView.html',{'error_msg':"Only the project owner can edit a project."})

@user_passes_test(profile_check, login_url='profileCreate')
def projectView(request, project_id):
  project = get_object_or_404(Project, pk=project_id)
  return render(request,'projectView.html',{'project':project})

@user_passes_test(profile_check, login_url='profileCreate')
def index(request):
    project_list = Project.objects.filter(state__in=['C','O']).order_by('-last_update')[:10]
    return render(request,'projectList.html',{'project_list':project_list})

@user_passes_test(profile_check, login_url='profileCreate')
def listAll(request):
    project_list = Project.objects.order_by('-last_update')[:10]
    return render(request,'projectList.html',{'project_list':project_list})

@user_passes_test(profile_check, login_url='profileCreate')
def listActive(request):
    project_list = Project.objects.filter(state__in=['O','D']).order_by('-last_update')
    return render(request,'projectList.html',{'project_list':project_list,'title':'Active Projects'})

@user_passes_test(profile_check, login_url='profileCreate')
def listDone(request):
    project_list = Project.objects.filter(state='D').order_by('-last_update')
    return render(request,'projectList.html',{'project_list':project_list,'title':'Completed Projects'})

@user_passes_test(profile_check, login_url='profileCreate')
def listDead(request):
    project_list = Project.objects.filter(state='A').order_by('last_update')
    return render(request,'projectList.html',{'project_list':project_list,'title':'Abandoned Projects'})<commit_msg>Fixed error when profile had invalid information.<commit_after>from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import user_passes_test, login_required
from .forms import *

# Checks if user has a profile
def profile_check(user):
    return user.is_authenticated() and hasattr(user, 'profile')

def loginTest(request):
    if request.user.is_authenticated():
        return render(request,'errorView.html',{'error_msg':"You are logged in as: "+str(request.user.username)})
    else:
        return render(request,'errorView.html',{'error_msg':"Not Logged In"})

@login_required(login_url='loginTest')
def profileCreate(request):
    registered = False
    if request.method == 'POST':
        user_form = UserForm(data=request.POST, instance=request.user)
        if hasattr(request.user, 'profile'):
            profile_form = ProfileForm(data=request.POST, instance=request.user.profile, files=request.FILES)
        else:
            profile_form = ProfileForm(data=request.POST, files=request.FILES)

        if user_form.is_valid() and profile_form.is_valid():
            user = user_form.save()
            user.save()

            profile = profile_form.save(commit=False)
            profile.user = user

            profile.save()
            registered = True
            return redirect('profileView',uname=user.username)
        else:
            print(user_form.errors, profile_form.errors)
    else:
        user_form = UserForm(instance=request.user)
        if hasattr(request.user, 'profile'):
            profile_form = ProfileForm(instance=request.user.profile)
        else:
            profile_form = ProfileForm()
    return render(request,'profileCreate.html',{'user_form':user_form,'profile_form':profile_form,'registered':registered})

@user_passes_test(profile_check, login_url='profileCreate')
def profileView(request,uname):
    user = get_object_or_404(User,username=uname)
    project_list = Project.objects.filter(owner=user.profile)
    return render(request, 'profileView.html', {'user':user,'project_list':project_list})

@user_passes_test(profile_check, login_url='profileCreate')
def projectCreate(request):
    if request.method == 'POST':
        project_form = ProjectForm(data=request.POST, files=request.FILES)
        if project_form.is_valid():
            project = project_form.save(commit=False)
            project.owner = request.user.profile
            project.save()
        else:
            print(project_form.errors)
        return redirect('projectView',project_id=project.id)

    else:
        project_form = ProjectForm()
    return render(request,'projectCreate.html',{'project_form':project_form})

@user_passes_test(profile_check, login_url='profileCreate')
def projectEdit(request, project_id):
    project = get_object_or_404(Project, pk=project_id)
    if request.user.profile == project.owner:
        if request.method == 'POST':
            project_form = ProjectForm(data=request.POST, instance=project, files=request.FILES)
            if project_form.is_valid():
                project_form.save()
            else:
                print(project_form.errors)
            return redirect('projectView',project_id=project.id)
        else:
            project_form = ProjectForm(instance=project)
            return render(request,'projectEdit.html',{'project_form':project_form,'project':project})
    else:
        return render(request,'errorView.html',{'error_msg':"Only the project owner can edit a project."})

@user_passes_test(profile_check, login_url='profileCreate')
def projectView(request, project_id):
      project = get_object_or_404(Project, pk=project_id)
      return render(request,'projectView.html',{'project':project})

@user_passes_test(profile_check, login_url='profileCreate')
def index(request):
    project_list = Project.objects.filter(state__in=['C','O']).order_by('-last_update')[:10]
    return render(request,'projectList.html',{'project_list':project_list})

@user_passes_test(profile_check, login_url='profileCreate')
def listAll(request):
    project_list = Project.objects.order_by('-last_update')[:10]
    return render(request,'projectList.html',{'project_list':project_list})

@user_passes_test(profile_check, login_url='profileCreate')
def listActive(request):
    project_list = Project.objects.filter(state__in=['O','D']).order_by('-last_update')
    return render(request,'projectList.html',{'project_list':project_list,'title':'Active Projects'})

@user_passes_test(profile_check, login_url='profileCreate')
def listDone(request):
    project_list = Project.objects.filter(state='D').order_by('-last_update')
    return render(request,'projectList.html',{'project_list':project_list,'title':'Completed Projects'})

@user_passes_test(profile_check, login_url='profileCreate')
def listDead(request):
    project_list = Project.objects.filter(state='A').order_by('last_update')
    return render(request,'projectList.html',{'project_list':project_list,'title':'Abandoned Projects'})<|endoftext|>


<commit_before>import os
import operator
import itertools
from datetime import datetime
from models import Paths, PathRow, UserJob, RenderCache
from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound
from sqs import make_SQS_connection, get_queue, build_job_message, send_message
from collections import OrderedDict
import pyramid.httpexceptions as exc
import requests

# Define AWS credentials
AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
REGION = 'us-west-2'

# Requests are passed into appropriate queues, as defined here.

COMPOSITE_QUEUE = 'snapsat_composite_queue'
PREVIEW_QUEUE = 'snapsat_preview_queue'

mailgun_key = os.environ['mailgun_key']
mailgun_url = os.environ['mailgun_url']

"""
Helper functions:
1. add_to_queue - Adds a request to the appropriate queue.

Views available:
1. landing - Landing page.
2. create - Allow a user to define their area of interest.
3. request_scene - Requests both the full and preview renders.
4. request_preview - Requests just the preview render.
5. scene_status - Given a scene ID display available data.
6. ajax - Returns a dictionary with all available scenes.
"""

@view_config(route_name='landing', renderer='templates/landing.jinja2')
def landing(request):
    """
    Landing page.
    No context is passed in, the page is purely static.
    """
    return {}

@view_config(route_name='guide', renderer='templates/guide.jinja2')
def guide(request):
    """
    Guide page.
    """
    return {}

@view_config(route_name='create', renderer='templates/create.jinja2')
def create(request):
    """
    Create page.
    Allows a user to define their area of interest and receive appropriate
    lists of scenes for it.
    """
    return scene_options_ajax(request)

def add_to_queue_composite(request):
    """
    Helper method for adding request to queue and adding to db.
    """
    band1 = request.params.get('band1')
    band2 = request.params.get('band2')
    band3 = request.params.get('band3')
    scene_id = request.matchdict['scene_id']

    if not RenderCache.full_render_availability(scene_id, band1, band2, band3):
        SQSconn = make_SQS_connection(REGION,
                                      AWS_ACCESS_KEY_ID,
                                      AWS_SECRET_ACCESS_KEY)
        current_queue = get_queue(SQSconn, COMPOSITE_QUEUE)
        jobid = UserJob.new_job(entityid=scene_id,
                                band1=band1, band2=band2, band3=band3,
                                rendertype=u'full')
        message = build_job_message(job_id=jobid,
                                    email='test@test.com',
                                    scene_id=scene_id,
                                    band_1=band1, band_2=band2, band_3=band3)
        send_message(SQSconn,
                     current_queue,
                     message['body'],
                     message['attributes'])

def add_to_queue_preview(request):
    """
    Helper method for adding request to queue and adding to db.
    """
    band1 = request.params.get('band1')
    band2 = request.params.get('band2')
    band3 = request.params.get('band3')
    scene_id = request.matchdict['scene_id']

    if not RenderCache.preview_render_availability(
            scene_id,
            band1, band2, band3):

        SQSconn = make_SQS_connection(REGION,
                                      AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)

        current_queue = get_queue(SQSconn, PREVIEW_QUEUE)

        jobid = UserJob.new_job(entityid=scene_id,
                                band1=band1, band2=band2, band3=band3,
                                rendertype=u'preview')

        message = build_job_message(job_id=jobid,
                                    email='test@test.com',
                                    scene_id=scene_id,
                                    band_1=band1, band_2=band2, band_3=band3)

        send_message(SQSconn,
                     current_queue,
                     message['body'], message['attributes'])

def email(request, bands):
    """
    If request contains email_address, send email to user with a link to the
    full render zip file.

    """
    import pdb; pdb.set_trace()
    email_address = request.params.get('email_address')
    print 'email address: {}'.format(email_address)
    if email_address:
        full_render = "http://snapsatcomposites.s3.amazonaws.com/{}_bands_{}.zip".format(request.matchdict['scene_id'], bands)
        scene = request.matchdict['scene_id']
        scene_url = 'http://snapsat.org/scene/{}#{}'.format(scene, bands)
        request_url = 'https://api.mailgun.net/v2/{0}/messages'.format(
                                mailgun_url)
        email_request = requests.post(request_url, auth=('api', mailgun_key),
                                data={
            'from': 'no-reply@snapsat.org',
            'to': email_address,
            'subject': 'Snapsat is rendering your request',
            'text': "Thank you for using Snapsat.\nAfter we've rendered " \
                     "your full composite, it will be available here:\n" \
                     "{}\nScene data can be found here:\n {}".format(
                                                full_render, scene_url)

        })

        print 'Status: {0}'.format(email_request.status_code)
        print 'Body:   {0}'.format(email_request.text)

@view_config(route_name='request_composite', renderer='json')
def request_composite(request):
    """
    Request both the preview and fullsize images for a particular composite.
    Redirect to scene page and goto band requested.
    If incorrect band combo is requested, bad request.

    If request contains email_address, send email to user with a link to the
    full render zip file.

    """
    # Add full render and preview job to apprpriate queues
    if valid_band_combo(request):
        bands = (request.params.get('band1') + request.params.get('band2') +
                 request.params.get('band3'))
        add_to_queue_composite(request)
        add_to_queue_preview(request)
        # If request contains an email_address, send email.
        email(request, bands)
        return HTTPFound(location='/scene/{}#{}'.format(
                         request.matchdict['scene_id'], bands))
    else:
        raise exc.HTTPBadRequest()

@view_config(route_name='request_preview', renderer='json')
def request_preview(request):
    """
    Request the preview image for a particular composite.
    Redirect to scene page and goto band requested.
    If incorrect band combo is requested, bad request.
    """
    if valid_band_combo(request):
        # Add preview render job to apprpriate queues
        bands = (request.params.get('band1') + request.params.get('band2') +
                 request.params.get('band3'))
        add_to_queue_preview(request)
        return HTTPFound(location='/scene/{}#{}'.format(
            request.matchdict['scene_id'], bands))
    else:
        raise exc.HTTPBadRequest()

def valid_band_combo(request):
    """
    Return true if band combo is valid, False if not.
    """
    valid = [1, 2, 3, 4, 5, 6, 7, 9]
    try:
        # handles error if band1, 2 or 3 doesn't exist
        bands = [int(request.params.get('band1')),
                 int(request.params.get('band2')),
                 int(request.params.get('band3'))]
    except:
        return False
    # Check if all bands are unique
    unique = len(set(bands)) == 3
    return all(x in valid for x in bands) and unique

@view_config(route_name='scene', renderer='templates/scene.jinja2')
def scene(request):
    """
    Given sceneID display available previews, rendered photos/links, status of
    jobs in process.
    """

    # Get scene id and list of rendered or rendering previews and full
    # composities from the render_cache table
    scene_id = request.matchdict['scene_id']
    rendered_rendering_composites = RenderCache.get_rendered_rendering(scene_id)

    # Initialize composties dictionary
    composites = {}

    # Populate composites dictionary with one dictionary per band combination
    if rendered_rendering_composites:
        # Loop through list of rendered or rendering composites
        for composite in rendered_rendering_composites:
            # Get band combination and create string for dictionary key
            band_combo = '{}{}{}'.format(composite.band1,
                                         composite.band2,
                                         composite.band3)
            # If band combination dictionary is not in composites dictionary,
            # add it and initialize it with band values
            if band_combo not in composites:
                composites.update({band_combo: {'band1': composite.band1,
                                                'band2': composite.band2,
                                                'band3': composite.band3}})

            # For full render of a band combination that is currently being
            # rendered update dictionary with status and elapsed time.
            if composite.currentlyrend and composite.rendertype == u'full':
                job_status, start_time, last_modified = (
                    UserJob.job_status_and_times(composite.jobid))
                elapsed_time = str(datetime.utcnow() - start_time)
                composites[band_combo].update({'fulljobid': composite.jobid,
                                               'fullurl': False,
                                               'fullstatus': job_status,
                                               'elapsedtime': elapsed_time})

            # For preview render of a band combination that is currently being
            # rendered update dictionary with status.
            if composite.currentlyrend and composite.rendertype == u'preview':
                job_status = UserJob.job_status(composite.jobid)
                composites[band_combo].update({'previewjobid': composite.jobid,
                                               'previewurl': False,
                                               'previewstatus': job_status})

            # For full render of a band combination that has been rendered,
            # update dictionary with status and elapsed time.
            if not composite.currentlyrend and composite.rendertype == u'full':
                job_status, start_time, last_modified = (
                    UserJob.job_status_and_times(composite.jobid))
                elapsed_time = str(datetime.utcnow() - start_time)
                composites[band_combo].update({'fulljobid': composite.jobid,
                                               'fullurl': composite.renderurl,
                                               'fullstatus': job_status,
                                               'elapsedtime': elapsed_time})

            # For preview render of a band combination that has been rendered,
            # update dictionary with status.
            if not composite.currentlyrend and composite.rendertype == u'preview':
                job_status = UserJob.job_status(composite.jobid)
                composites[band_combo].update({'previewjobid': composite.jobid,
                                               'previewurl': composite.renderurl,
                                               'previewstatus': job_status})

    # Order composites by band combination.
    composites = OrderedDict(sorted(composites.items()))

    # Get scene metadata from path_row table
    meta_data_list = PathRow.meta_data(scene_id)
    meta_data = {'scene_id': scene_id,
                 'acquisitiondate':
                 meta_data_list[0].strftime('%Y/%m/%d %H:%M:%S'),
                 'cloudcover': meta_data_list[1],
                 'path': meta_data_list[2],
                 'row': meta_data_list[3],
                 'min_lat': meta_data_list[4],
                 'min_lon': meta_data_list[5],
                 'max_lat': meta_data_list[6],
                 'max_lon': meta_data_list[7],
                 'overview_url':
                 meta_data_list[8][0:-10]+scene_id+'_thumb_small.jpg'}

    return {'meta_data': meta_data, 'composites': composites}

@view_config(route_name='scene_options_ajax', renderer='json')
def scene_options_ajax(request):
    """
    Returns a dictionary with all available scenes around the map's center.
    """
    # Lat/lng values default to Seattle, otherwise from Leaflet .getcenter().
    lat = float(request.params.get('lat', 47.614848))
    lng = float(request.params.get('lng', -122.3359059))

    # Filter all available scenes to those which encompass the
    # lat/lng provided from the user. Then, populate a list with
    # the information relevant to our view.

    path_row_list = Paths.pathandrow(lat, lng)

    # Check for zero length path row list to prevent return of all path row
    # combinations n ithe world.
    if not path_row_list:
        return {'scenes': []}

    scenes = PathRow.scenelist(path_row_list)
    sceneList = []
    for i, scene in enumerate(scenes):
        sceneList.append({
            'acquisitiondate': scene.acquisitiondate.strftime('%Y %m %d'),
            'cloudcover': scene.cloudcover,
            'download_url': scene.download_url,
            'entityid': scene.entityid,
            'sliced': scene.entityid[3:9],
            'path': scene.path,
            'row': scene.row})

    # This line may not be necessary.
    sort = sorted(sceneList, key=operator.itemgetter('sliced'), reverse=False)

    # Sort the available scenes based on their Path, then Row.
    outputList = []
    for key, items in itertools.groupby(sort, operator.itemgetter('sliced')):
        outputList.append(list(items))

    # Sort the vailable scenes in each group by date in reverse.
    for group in outputList:
        group.sort(key=operator.itemgetter('acquisitiondate'), reverse=True)

    print 'outputList length: {}'.format(len(outputList))
    return {'scenes': outputList}

@view_config(route_name='status_poll', renderer='json')
def status_poll(request):
    """
    Poll database for full render job status.
    """

    # Get jobid from request
    jobid = request.params.get('jobid')
    # Query the database for job status, start time, last modified time
    job_status, start_time, last_modified = (
        UserJob.job_status_and_times(jobid))
    # Calcuate elapsed time
    elapsed_time = str(datetime.utcnow() - start_time)

    # Get render url when job is done
    if job_status == 'Done':
        render_url = RenderCache.get_renderurl(jobid)
    else:
        render_url = None

    # Create job info json output
    job_info = {'jobstatus': job_status,
                'elapsedtime': elapsed_time,
                'renderurl': render_url}

    return {'job_info': job_info}

@view_config(route_name='preview_poll', renderer='json')
def preview_poll(request):
    """
    Poll database for preview render job status.
    """

    # Get jobid from request
    jobid = request.params.get('jobid')
    # Query the database for job status
    job_status = UserJob.job_status(jobid)

    # Get render url when job is done
    if job_status == 'Done':
        render_url = RenderCache.get_renderurl(jobid)
    else:
        render_url = None

    # Create job info json output
    job_info = {'jobstatus': job_status,
                'renderurl': render_url}

    return {'job_info': job_info}
<commit_msg>#122 remove pdb.<commit_after>import os
import operator
import itertools
from datetime import datetime
from models import Paths, PathRow, UserJob, RenderCache
from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound
from sqs import make_SQS_connection, get_queue, build_job_message, send_message
from collections import OrderedDict
import pyramid.httpexceptions as exc
import requests

# Define AWS credentials
AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
REGION = 'us-west-2'

# Requests are passed into appropriate queues, as defined here.

COMPOSITE_QUEUE = 'snapsat_composite_queue'
PREVIEW_QUEUE = 'snapsat_preview_queue'

mailgun_key = os.environ['mailgun_key']
mailgun_url = os.environ['mailgun_url']

"""
Helper functions:
1. add_to_queue - Adds a request to the appropriate queue.

Views available:
1. landing - Landing page.
2. create - Allow a user to define their area of interest.
3. request_scene - Requests both the full and preview renders.
4. request_preview - Requests just the preview render.
5. scene_status - Given a scene ID display available data.
6. ajax - Returns a dictionary with all available scenes.
"""

@view_config(route_name='landing', renderer='templates/landing.jinja2')
def landing(request):
    """
    Landing page.
    No context is passed in, the page is purely static.
    """
    return {}

@view_config(route_name='guide', renderer='templates/guide.jinja2')
def guide(request):
    """
    Guide page.
    """
    return {}

@view_config(route_name='create', renderer='templates/create.jinja2')
def create(request):
    """
    Create page.
    Allows a user to define their area of interest and receive appropriate
    lists of scenes for it.
    """
    return scene_options_ajax(request)

def add_to_queue_composite(request):
    """
    Helper method for adding request to queue and adding to db.
    """
    band1 = request.params.get('band1')
    band2 = request.params.get('band2')
    band3 = request.params.get('band3')
    scene_id = request.matchdict['scene_id']

    if not RenderCache.full_render_availability(scene_id, band1, band2, band3):
        SQSconn = make_SQS_connection(REGION,
                                      AWS_ACCESS_KEY_ID,
                                      AWS_SECRET_ACCESS_KEY)
        current_queue = get_queue(SQSconn, COMPOSITE_QUEUE)
        jobid = UserJob.new_job(entityid=scene_id,
                                band1=band1, band2=band2, band3=band3,
                                rendertype=u'full')
        message = build_job_message(job_id=jobid,
                                    email='test@test.com',
                                    scene_id=scene_id,
                                    band_1=band1, band_2=band2, band_3=band3)
        send_message(SQSconn,
                     current_queue,
                     message['body'],
                     message['attributes'])

def add_to_queue_preview(request):
    """
    Helper method for adding request to queue and adding to db.
    """
    band1 = request.params.get('band1')
    band2 = request.params.get('band2')
    band3 = request.params.get('band3')
    scene_id = request.matchdict['scene_id']

    if not RenderCache.preview_render_availability(
            scene_id,
            band1, band2, band3):

        SQSconn = make_SQS_connection(REGION,
                                      AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)

        current_queue = get_queue(SQSconn, PREVIEW_QUEUE)

        jobid = UserJob.new_job(entityid=scene_id,
                                band1=band1, band2=band2, band3=band3,
                                rendertype=u'preview')

        message = build_job_message(job_id=jobid,
                                    email='test@test.com',
                                    scene_id=scene_id,
                                    band_1=band1, band_2=band2, band_3=band3)

        send_message(SQSconn,
                     current_queue,
                     message['body'], message['attributes'])

def email(request, bands):
    """
    If request contains email_address, send email to user with a link to the
    full render zip file.

    """
    email_address = request.params.get('email_address')
    if email_address:
        full_render = "http://snapsatcomposites.s3.amazonaws.com/{}_bands_{}.zip".format(request.matchdict['scene_id'], bands)
        scene = request.matchdict['scene_id']
        scene_url = 'http://snapsat.org/scene/{}#{}'.format(scene, bands)
        request_url = 'https://api.mailgun.net/v2/{0}/messages'.format(
                                mailgun_url)
        email_request = requests.post(request_url, auth=('api', mailgun_key),
                                data={
            'from': 'no-reply@snapsat.org',
            'to': email_address,
            'subject': 'Snapsat is rendering your request',
            'text': "Thank you for using Snapsat.\nAfter we've rendered " \
                     "your full composite, it will be available here:\n" \
                     "{}\nScene data can be found here:\n {}".format(
                                                full_render, scene_url)

        })

@view_config(route_name='request_composite', renderer='json')
def request_composite(request):
    """
    Request both the preview and fullsize images for a particular composite.
    Redirect to scene page and goto band requested.
    If incorrect band combo is requested, bad request.

    If request contains email_address, send email to user with a link to the
    full render zip file.

    """
    # Add full render and preview job to apprpriate queues
    if valid_band_combo(request):
        bands = (request.params.get('band1') + request.params.get('band2') +
                 request.params.get('band3'))
        add_to_queue_composite(request)
        add_to_queue_preview(request)
        # If request contains an email_address, send email.
        email(request, bands)
        return HTTPFound(location='/scene/{}#{}'.format(
                         request.matchdict['scene_id'], bands))
    else:
        raise exc.HTTPBadRequest()

@view_config(route_name='request_preview', renderer='json')
def request_preview(request):
    """
    Request the preview image for a particular composite.
    Redirect to scene page and goto band requested.
    If incorrect band combo is requested, bad request.
    """
    if valid_band_combo(request):
        # Add preview render job to apprpriate queues
        bands = (request.params.get('band1') + request.params.get('band2') +
                 request.params.get('band3'))
        add_to_queue_preview(request)
        return HTTPFound(location='/scene/{}#{}'.format(
            request.matchdict['scene_id'], bands))
    else:
        raise exc.HTTPBadRequest()

def valid_band_combo(request):
    """
    Return true if band combo is valid, False if not.
    """
    valid = [1, 2, 3, 4, 5, 6, 7, 9]
    try:
        # handles error if band1, 2 or 3 doesn't exist
        bands = [int(request.params.get('band1')),
                 int(request.params.get('band2')),
                 int(request.params.get('band3'))]
    except:
        return False
    # Check if all bands are unique
    unique = len(set(bands)) == 3
    return all(x in valid for x in bands) and unique

@view_config(route_name='scene', renderer='templates/scene.jinja2')
def scene(request):
    """
    Given sceneID display available previews, rendered photos/links, status of
    jobs in process.
    """

    # Get scene id and list of rendered or rendering previews and full
    # composities from the render_cache table
    scene_id = request.matchdict['scene_id']
    rendered_rendering_composites = RenderCache.get_rendered_rendering(scene_id)

    # Initialize composties dictionary
    composites = {}

    # Populate composites dictionary with one dictionary per band combination
    if rendered_rendering_composites:
        # Loop through list of rendered or rendering composites
        for composite in rendered_rendering_composites:
            # Get band combination and create string for dictionary key
            band_combo = '{}{}{}'.format(composite.band1,
                                         composite.band2,
                                         composite.band3)
            # If band combination dictionary is not in composites dictionary,
            # add it and initialize it with band values
            if band_combo not in composites:
                composites.update({band_combo: {'band1': composite.band1,
                                                'band2': composite.band2,
                                                'band3': composite.band3}})

            # For full render of a band combination that is currently being
            # rendered update dictionary with status and elapsed time.
            if composite.currentlyrend and composite.rendertype == u'full':
                job_status, start_time, last_modified = (
                    UserJob.job_status_and_times(composite.jobid))
                elapsed_time = str(datetime.utcnow() - start_time)
                composites[band_combo].update({'fulljobid': composite.jobid,
                                               'fullurl': False,
                                               'fullstatus': job_status,
                                               'elapsedtime': elapsed_time})

            # For preview render of a band combination that is currently being
            # rendered update dictionary with status.
            if composite.currentlyrend and composite.rendertype == u'preview':
                job_status = UserJob.job_status(composite.jobid)
                composites[band_combo].update({'previewjobid': composite.jobid,
                                               'previewurl': False,
                                               'previewstatus': job_status})

            # For full render of a band combination that has been rendered,
            # update dictionary with status and elapsed time.
            if not composite.currentlyrend and composite.rendertype == u'full':
                job_status, start_time, last_modified = (
                    UserJob.job_status_and_times(composite.jobid))
                elapsed_time = str(datetime.utcnow() - start_time)
                composites[band_combo].update({'fulljobid': composite.jobid,
                                               'fullurl': composite.renderurl,
                                               'fullstatus': job_status,
                                               'elapsedtime': elapsed_time})

            # For preview render of a band combination that has been rendered,
            # update dictionary with status.
            if not composite.currentlyrend and composite.rendertype == u'preview':
                job_status = UserJob.job_status(composite.jobid)
                composites[band_combo].update({'previewjobid': composite.jobid,
                                               'previewurl': composite.renderurl,
                                               'previewstatus': job_status})

    # Order composites by band combination.
    composites = OrderedDict(sorted(composites.items()))

    # Get scene metadata from path_row table
    meta_data_list = PathRow.meta_data(scene_id)
    meta_data = {'scene_id': scene_id,
                 'acquisitiondate':
                 meta_data_list[0].strftime('%Y/%m/%d %H:%M:%S'),
                 'cloudcover': meta_data_list[1],
                 'path': meta_data_list[2],
                 'row': meta_data_list[3],
                 'min_lat': meta_data_list[4],
                 'min_lon': meta_data_list[5],
                 'max_lat': meta_data_list[6],
                 'max_lon': meta_data_list[7],
                 'overview_url':
                 meta_data_list[8][0:-10]+scene_id+'_thumb_small.jpg'}

    return {'meta_data': meta_data, 'composites': composites}

@view_config(route_name='scene_options_ajax', renderer='json')
def scene_options_ajax(request):
    """
    Returns a dictionary with all available scenes around the map's center.
    """
    # Lat/lng values default to Seattle, otherwise from Leaflet .getcenter().
    lat = float(request.params.get('lat', 47.614848))
    lng = float(request.params.get('lng', -122.3359059))

    # Filter all available scenes to those which encompass the
    # lat/lng provided from the user. Then, populate a list with
    # the information relevant to our view.

    path_row_list = Paths.pathandrow(lat, lng)

    # Check for zero length path row list to prevent return of all path row
    # combinations n ithe world.
    if not path_row_list:
        return {'scenes': []}

    scenes = PathRow.scenelist(path_row_list)
    sceneList = []
    for i, scene in enumerate(scenes):
        sceneList.append({
            'acquisitiondate': scene.acquisitiondate.strftime('%Y %m %d'),
            'cloudcover': scene.cloudcover,
            'download_url': scene.download_url,
            'entityid': scene.entityid,
            'sliced': scene.entityid[3:9],
            'path': scene.path,
            'row': scene.row})

    # This line may not be necessary.
    sort = sorted(sceneList, key=operator.itemgetter('sliced'), reverse=False)

    # Sort the available scenes based on their Path, then Row.
    outputList = []
    for key, items in itertools.groupby(sort, operator.itemgetter('sliced')):
        outputList.append(list(items))

    # Sort the vailable scenes in each group by date in reverse.
    for group in outputList:
        group.sort(key=operator.itemgetter('acquisitiondate'), reverse=True)

    print 'outputList length: {}'.format(len(outputList))
    return {'scenes': outputList}

@view_config(route_name='status_poll', renderer='json')
def status_poll(request):
    """
    Poll database for full render job status.
    """

    # Get jobid from request
    jobid = request.params.get('jobid')
    # Query the database for job status, start time, last modified time
    job_status, start_time, last_modified = (
        UserJob.job_status_and_times(jobid))
    # Calcuate elapsed time
    elapsed_time = str(datetime.utcnow() - start_time)

    # Get render url when job is done
    if job_status == 'Done':
        render_url = RenderCache.get_renderurl(jobid)
    else:
        render_url = None

    # Create job info json output
    job_info = {'jobstatus': job_status,
                'elapsedtime': elapsed_time,
                'renderurl': render_url}

    return {'job_info': job_info}

@view_config(route_name='preview_poll', renderer='json')
def preview_poll(request):
    """
    Poll database for preview render job status.
    """

    # Get jobid from request
    jobid = request.params.get('jobid')
    # Query the database for job status
    job_status = UserJob.job_status(jobid)

    # Get render url when job is done
    if job_status == 'Done':
        render_url = RenderCache.get_renderurl(jobid)
    else:
        render_url = None

    # Create job info json output
    job_info = {'jobstatus': job_status,
                'renderurl': render_url}

    return {'job_info': job_info}
<|endoftext|>


<commit_before>
import datetime
from tornado import web

import base
import models

class DashboardHandler(base.BaseHandler):
    @web.authenticated
    @web.asynchronous
    def get(self):
        user = self.get_current_user()
        recent_runs = models.Run.objects(user=user).order_by('date')[:10]
        week = models.Week.this_week(user)
        miles_this_week = models.Run.this_week_mileage(user)
        self.render('dashboard.html', page_title='Dashboard', user=user, recent_runs=recent_runs, today=datetime.date.today().strftime("%x"), error='', miles_this_week=miles_this_week, week=week)
<commit_msg>more recent runs on top<commit_after>
import datetime
from tornado import web

import base
import models

class DashboardHandler(base.BaseHandler):
    @web.authenticated
    @web.asynchronous
    def get(self):
        user = self.get_current_user()
        recent_runs = models.Run.objects(user=user).order_by('-date')[:10]
        week = models.Week.this_week(user)
        miles_this_week = models.Run.this_week_mileage(user)
        self.render('dashboard.html', page_title='Dashboard', user=user, recent_runs=recent_runs, today=datetime.date.today().strftime("%x"), error='', miles_this_week=miles_this_week, week=week)
<|endoftext|>


<commit_before>#! /usr/bin/env python
# Square script
# Executed when asked to draw a square by the user
# Draws a 12 inch square

import serial
import create
from time import strftime

# Create robot
robot = create.Create("/dev/ttyUSB0")
robot.toFullMode()

# Record current position, at start of drawing
pose = robot.getPose()
now = strftime("%H:%M:%S %m-%d-%Y")
line = "On %s I started drawing a SQUARE at:\n" % now
line += "X: %s\n" % pose[0]
line += "Y: %s\n" % pose[1]
line += "Theta: %s\n" % pose[2]
#with open('positions.txt','a') as f:
#  f.write(line)
#f.closed

# Draw square
robot.move(45, 30) #12.5" equivilent in millimeters, rounded up, 30cm/s
robot.turn(-90, 60) # 90 degrees clockwise, 60 degrees/s
robot.move(45, 30)
robot.turn(-90, 60)
robot.move(45, 30)
robot.turn(-90, 60)
robot.move(45, 30)

# Record position now, at end of drawing
new_pose = robot.getPose()
new_now = strftime("%H:%M:%S %m-%d-%Y")
line = "On %s I finished drawing a SQUARE at:\n" % new_now
line += "X: %s\n" % new_pose[0]
line += "Y: %s\n" % new_pose[1]
line += "Theta: %s\n" % new_pose[2]
#with open('positions.txt','a') as f:
#  f.write(line)
#f.closed
<commit_msg>Update square.py<commit_after>#! /usr/bin/env python
# Square script
# Executed when asked to draw a square by the user
# Draws a 45cm square

import serial
import create
from time import strftime

# Create robot
robot = create.Create("/dev/ttyUSB0")
robot.toFullMode()

# Record current position, at start of drawing
pose = robot.getPose()
now = strftime("%H:%M:%S %m-%d-%Y")
line = "On %s I started drawing a SQUARE at:\n" % now
line += "X: %s\n" % pose[0]
line += "Y: %s\n" % pose[1]
line += "Theta: %s\n" % pose[2]
#with open('positions.txt','a') as f:
#  f.write(line)
#f.closed

# Draw square
robot.move(45, 30) # ~12.5" equivilent in cm, rounded up; at 30cm/s
robot.turn(-90, 60) # 90 degrees clockwise, 60 degrees/s
robot.move(45, 30)
robot.turn(-90, 60)
robot.move(45, 30)
robot.turn(-90, 60)
robot.move(45, 30)

# Record position now, at end of drawing
new_pose = robot.getPose()
new_now = strftime("%H:%M:%S %m-%d-%Y")
line = "On %s I finished drawing a SQUARE at:\n" % new_now
line += "X: %s\n" % new_pose[0]
line += "Y: %s\n" % new_pose[1]
line += "Theta: %s\n" % new_pose[2]
#with open('positions.txt','a') as f:
#  f.write(line)
#f.closed
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
This module countains all logic necessary to decipher the signature.

YouTube's strategy to restrict downloading videos is to send a ciphered version
of the signature to the client, along with the decryption algorithm obfuscated
in JavaScript. For the clients to play the videos, JavaScript must take the
ciphered version, pass it through a series of "transform functions," and then
signs the media URL with the output.

This module is responsible for (1) finding and extracting those "transform
functions" (2) maps them to Python equivalents and (3) taking the ciphered
signature and decoding it.

"""
from __future__ import absolute_import

import logging
import pprint
import re
from itertools import chain

from pytube.exceptions import RegexMatchError
from pytube.helpers import regex_search

logger = logging.getLogger(__name__)

def get_initial_function_name(js):
    """Extract the name of the function responsible for computing the signature.

    :param str js:
        The contents of the base.js asset file.

    """
    # c&&d.set("signature", EE(c));
    pattern = r'"signature",\s?([a-zA-Z0-9$]+)\('
    logger.debug('finding initial function name')
    return regex_search(pattern, js, group=1)

def get_transform_plan(js):
    """Extract the "transform plan".

    The "transform plan" is the functions the ciphered signature is passed
    through to obtain the actual signature.

    :param str js:
        The contents of the base.js asset file.

    **Example**:

    >>> get_transform_plan(js)
    ['DE.AJ(a,15)',
    'DE.VR(a,3)',
    'DE.AJ(a,51)',
    'DE.VR(a,3)',
    'DE.kT(a,51)',
    'DE.kT(a,8)',
    'DE.VR(a,3)',
    'DE.kT(a,21)']
    """
    name = re.escape(get_initial_function_name(js))
    pattern = r'%s=function\(\w\){[a-z=\.\(\"\)]*;(.*);(?:.+)}' % name
    logger.debug('getting transform plan')
    return regex_search(pattern, js, group=1).split(';')

def get_transform_object(js, var):
    """Extract the "transform object".

    The "transform object" contains the function definitions referenced in the
    "transform plan". The ``var`` argument is the obfuscated variable name
    which contains these functions, for example, given the function call
    ``DE.AJ(a,15)`` returned by the transform plan, "DE" would be the var.

    :param str js:
        The contents of the base.js asset file.
    :param str var:
        The obfuscated variable name that stores an object with all functions
        that descrambles the signature.

    **Example**:

    >>> get_transform_object(js, 'DE')
    ['AJ:function(a){a.reverse()}',
    'VR:function(a,b){a.splice(0,b)}',
    'kT:function(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c}']

    """
    pattern = r'var %s={(.*?)};' % re.escape(var)
    logger.debug('getting transform object')
    return (
        regex_search(pattern, js, group=1, flags=re.DOTALL)
        .replace('\n', ' ')
        .split(', ')
    )

def get_transform_map(js, var):
    """Build a transform function lookup.

    Build a lookup table of obfuscated JavaScript function names to the
    Python equivalents.

    :param str js:
        The contents of the base.js asset file.
    :param str var:
        The obfuscated variable name that stores an object with all functions
        that descrambles the signature.

    """
    transform_object = get_transform_object(js, var)
    mapper = {}
    for obj in transform_object:
        # AJ:function(a){a.reverse()} => AJ, function(a){a.reverse()}
        name, function = obj.split(':', 1)
        fn = map_functions(function)
        mapper[name] = fn
    return mapper

def reverse(arr, b):
    """Reverse elements in a list.

    This function is equivalent to:

    .. code-block:: javascript

       function(a, b) { a.reverse() }

    This method takes an unused ``b`` variable as their transform functions
    universally sent two arguments.

    **Example**:

    >>> reverse([1, 2, 3, 4])
    [4, 3, 2, 1]
    """
    return arr[::-1]

def splice(arr, b):
    """Add/remove items to/from a list.

    This function is equivalent to:

    .. code-block:: javascript

       function(a, b) { a.splice(0, b) }

    **Example**:

    >>> splice([1, 2, 3, 4], 2)
    [1, 2]
    """
    return arr[:b] + arr[b * 2:]

def swap(arr, b):
    """Swap positions at b modulus the list length.

    This function is equivalent to:

    .. code-block:: javascript

       function(a, b) { var c=a[0];a[0]=a[b%a.length];a[b]=c }

    **Example**:

    >>> swap([1, 2, 3, 4], 2)
    [3, 2, 1, 4]
    """
    r = b % len(arr)
    return list(chain([arr[r]], arr[1:r], [arr[0]], arr[r + 1:]))

def map_functions(js_func):
    """For a given JavaScript transform function, return the Python equivalent.

    :param str js_func:
        The JavaScript version of the transform function.

    """
    mapper = (
        # function(a){a.reverse()}
        ('{\w\.reverse\(\)}', reverse),
        # function(a,b){a.splice(0,b)}
        ('{\w\.splice\(0,\w\)}', splice),
        # function(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c}
        ('{var\s\w=\w\[0\];\w\[0\]=\w\[\w\%\w.length\];\w\[\w\]=\w}', swap),
    )

    for pattern, fn in mapper:
        if re.search(pattern, js_func):
            return fn
    raise RegexMatchError(
        'could not find python equivalent function for: ',
        js_func,
    )

def parse_function(js_func):
    """Parse the Javascript transform function.

    Break a JavaScript transform function down into a two element ``tuple``
    containing the function name and some integer-based argument.

    :param str js_func:
        The JavaScript version of the transform function.
    :rtype: tuple
    :returns:
        two element tuple containing the function name and an argument.

    **Example**:

    >>> parse_function('DE.AJ(a,15)')
    ('AJ', 15)

    """
    logger.debug('parsing transform function')
    return regex_search(r'\w+\.(\w+)\(\w,(\d+)\)', js_func, groups=True)

def get_signature(js, ciphered_signature):
    """Decipher the signature.

    Taking the ciphered signature, applies the transform functions.

    :param str js:
        The contents of the base.js asset file.
    :param str ciphered_signature:
        The ciphered signature sent in the ``player_config``.
    :rtype: str
    :returns:
       Decrypted signature required to download the media content.

    """
    tplan = get_transform_plan(js)
    # DE.AJ(a,15) => DE, AJ(a,15)
    var, _ = tplan[0].split('.')
    tmap = get_transform_map(js, var)
    signature = [s for s in ciphered_signature]

    for js_func in tplan:
        name, argument = parse_function(js_func)
        signature = tmap[name](signature, int(argument))
        logger.debug(
            'applied transform function\n%s', pprint.pformat(
                {
                    'output': ''.join(signature),
                    'js_function': name,
                    'argument': int(argument),
                    'function': tmap[name],
                }, indent=2,
            ),
        )
    return ''.join(signature)
<commit_msg>Update cipher.py<commit_after># -*- coding: utf-8 -*-
"""
This module countains all logic necessary to decipher the signature.

YouTube's strategy to restrict downloading videos is to send a ciphered version
of the signature to the client, along with the decryption algorithm obfuscated
in JavaScript. For the clients to play the videos, JavaScript must take the
ciphered version, pass it through a series of "transform functions," and then
signs the media URL with the output.

This module is responsible for (1) finding and extracting those "transform
functions" (2) maps them to Python equivalents and (3) taking the ciphered
signature and decoding it.

"""
from __future__ import absolute_import

import logging
import pprint
import re
from itertools import chain

from pytube.exceptions import RegexMatchError
from pytube.helpers import regex_search

logger = logging.getLogger(__name__)

def get_initial_function_name(js):
    """Extract the name of the function responsible for computing the signature.

    :param str js:
        The contents of the base.js asset file.

    """
    # c&&d.set("signature", EE(c));
    pattern = r'"signature",\s?([a-zA-Z0-9$]+)\('
    logger.debug('finding initial function name')
    return regex_search(pattern, js, group=1)

def get_transform_plan(js):
    """Extract the "transform plan".

    The "transform plan" is the functions that the ciphered signature is
    cycled through to obtain the actual signature.

    :param str js:
        The contents of the base.js asset file.

    **Example**:

    >>> get_transform_plan(js)
    ['DE.AJ(a,15)',
    'DE.VR(a,3)',
    'DE.AJ(a,51)',
    'DE.VR(a,3)',
    'DE.kT(a,51)',
    'DE.kT(a,8)',
    'DE.VR(a,3)',
    'DE.kT(a,21)']
    """
    name = re.escape(get_initial_function_name(js))
    pattern = r'%s=function\(\w\){[a-z=\.\(\"\)]*;(.*);(?:.+)}' % name
    logger.debug('getting transform plan')
    return regex_search(pattern, js, group=1).split(';')

def get_transform_object(js, var):
    """Extract the "transform object".

    The "transform object" contains the function definitions referenced in the
    "transform plan". The ``var`` argument is the obfuscated variable name
    which contains these functions, for example, given the function call
    ``DE.AJ(a,15)`` returned by the transform plan, "DE" would be the var.

    :param str js:
        The contents of the base.js asset file.
    :param str var:
        The obfuscated variable name that stores an object with all functions
        that descrambles the signature.

    **Example**:

    >>> get_transform_object(js, 'DE')
    ['AJ:function(a){a.reverse()}',
    'VR:function(a,b){a.splice(0,b)}',
    'kT:function(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c}']

    """
    pattern = r'var %s={(.*?)};' % re.escape(var)
    logger.debug('getting transform object')
    return (
        regex_search(pattern, js, group=1, flags=re.DOTALL)
        .replace('\n', ' ')
        .split(', ')
    )

def get_transform_map(js, var):
    """Build a transform function lookup.

    Build a lookup table of obfuscated JavaScript function names to the
    Python equivalents.

    :param str js:
        The contents of the base.js asset file.
    :param str var:
        The obfuscated variable name that stores an object with all functions
        that descrambles the signature.

    """
    transform_object = get_transform_object(js, var)
    mapper = {}
    for obj in transform_object:
        # AJ:function(a){a.reverse()} => AJ, function(a){a.reverse()}
        name, function = obj.split(':', 1)
        fn = map_functions(function)
        mapper[name] = fn
    return mapper

def reverse(arr, b):
    """Reverse elements in a list.

    This function is equivalent to:

    .. code-block:: javascript

       function(a, b) { a.reverse() }

    This method takes an unused ``b`` variable as their transform functions
    universally sent two arguments.

    **Example**:

    >>> reverse([1, 2, 3, 4])
    [4, 3, 2, 1]
    """
    return arr[::-1]

def splice(arr, b):
    """Add/remove items to/from a list.

    This function is equivalent to:

    .. code-block:: javascript

       function(a, b) { a.splice(0, b) }

    **Example**:

    >>> splice([1, 2, 3, 4], 2)
    [1, 2]
    """
    return arr[:b] + arr[b * 2:]

def swap(arr, b):
    """Swap positions at b modulus the list length.

    This function is equivalent to:

    .. code-block:: javascript

       function(a, b) { var c=a[0];a[0]=a[b%a.length];a[b]=c }

    **Example**:

    >>> swap([1, 2, 3, 4], 2)
    [3, 2, 1, 4]
    """
    r = b % len(arr)
    return list(chain([arr[r]], arr[1:r], [arr[0]], arr[r + 1:]))

def map_functions(js_func):
    """For a given JavaScript transform function, return the Python equivalent.

    :param str js_func:
        The JavaScript version of the transform function.

    """
    mapper = (
        # function(a){a.reverse()}
        ('{\w\.reverse\(\)}', reverse),
        # function(a,b){a.splice(0,b)}
        ('{\w\.splice\(0,\w\)}', splice),
        # function(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c}
        ('{var\s\w=\w\[0\];\w\[0\]=\w\[\w\%\w.length\];\w\[\w\]=\w}', swap),
    )

    for pattern, fn in mapper:
        if re.search(pattern, js_func):
            return fn
    raise RegexMatchError(
        'could not find python equivalent function for: ',
        js_func,
    )

def parse_function(js_func):
    """Parse the Javascript transform function.

    Break a JavaScript transform function down into a two element ``tuple``
    containing the function name and some integer-based argument.

    :param str js_func:
        The JavaScript version of the transform function.
    :rtype: tuple
    :returns:
        two element tuple containing the function name and an argument.

    **Example**:

    >>> parse_function('DE.AJ(a,15)')
    ('AJ', 15)

    """
    logger.debug('parsing transform function')
    return regex_search(r'\w+\.(\w+)\(\w,(\d+)\)', js_func, groups=True)

def get_signature(js, ciphered_signature):
    """Decipher the signature.

    Taking the ciphered signature, applies the transform functions.

    :param str js:
        The contents of the base.js asset file.
    :param str ciphered_signature:
        The ciphered signature sent in the ``player_config``.
    :rtype: str
    :returns:
       Decrypted signature required to download the media content.

    """
    tplan = get_transform_plan(js)
    # DE.AJ(a,15) => DE, AJ(a,15)
    var, _ = tplan[0].split('.')
    tmap = get_transform_map(js, var)
    signature = [s for s in ciphered_signature]

    for js_func in tplan:
        name, argument = parse_function(js_func)
        signature = tmap[name](signature, int(argument))
        logger.debug(
            'applied transform function\n%s', pprint.pformat(
                {
                    'output': ''.join(signature),
                    'js_function': name,
                    'argument': int(argument),
                    'function': tmap[name],
                }, indent=2,
            ),
        )
    return ''.join(signature)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
    pyvisa.events
    ~~~~~~~~~~~~~

    VISA events with convenient access to the available attributes.

    This file is part of PyVISA.

    :copyright: 2020 by PyVISA Authors, see AUTHORS for more details.
    :license: MIT, see LICENSE for more details.
"""
from contextlib import contextmanager
from typing import Optional

from . import constants, highlevel, errors
from .typing import VISAEventContext
from .attributes import AttrVI_ATTR_STATUS, AttrVI_ATTR_OPER_NAME

# XXX manually set all attributes (all attributes should be cached)

class VisaEvent:
    """Event that lead to the call of an event handler.

    Do not instantiate directly use the visa_event context manager of the
    Resource object passed to the handler.

    """

    #: Reference to the visa library
    visalib: highlevel.VisaLibraryBase

    #: Type of the event.
    event_type: constants.EventType

    #: Context use to query the event attributes.
    _context: Optional[VISAEventContext]

    @classmethod
    def register(cls,):
        """[summary]
        """

    def __init__(self, visalib, event_type, context):
        self.visalib = visalib
        self.event_type = event_type
        self._context = context

    @property
    def context(self) -> VISAEventContext:
        c = self._context
        if c is None:
            raise errors.InvalidSession()
        return c

    def get_visa_attribute(self, attribute_id: constants.EventAttribute) -> Any:
        """Get the specified VISA attribute.

        """
        return self.visalib.get_attribute(self.context, attribute_id)

class VisaExceptionEvent(VisaEvent):
    """Event corresponding to an exception

    """

    #: Status code of the opertion that generated the exception
    status = AttrVI_ATTR_STATUS()

    #: Name of the operation that led to the exception
    operation_name = AttrVI_ATTR_OPER_NAME()

class VisaGPIBCICEvent(VisaEvent):
    """GPIB Controller in Charge event.

    The event is emitted if the status is gained or lost.

    """

    #:
    cic_state

class VisaIOCompletionEvent(VisaEvent):
    """Event marking the completion of an IO operation.

    """

    #:
    status

    #:
    job_id

    #:
    buffer

    #:
    return_count

    #:
    operation_name

class VisaTrigEvent(VisaEvent):
    """Trigger event.

    """

    #:
    trigger_id

class VisaUSBInteruptEvent(VisaEvent):
    """USB interruption event.

    """

    #:
    status

    #:
    size

    #:
    data

class VisaVXISignalEvent(VisaEvent):
    """VXI signal event.

    """

    #:
    status

class VisaVXIInterruptEvent(VisaEvent):
    """VXI interrupt event.

    """

    #:
    status

    #:
    interrupt_level
<commit_msg>events: add attributes<commit_after># -*- coding: utf-8 -*-
"""
    pyvisa.events
    ~~~~~~~~~~~~~

    VISA events with convenient access to the available attributes.

    This file is part of PyVISA.

    :copyright: 2020 by PyVISA Authors, see AUTHORS for more details.
    :license: MIT, see LICENSE for more details.
"""
from contextlib import contextmanager
from typing import Callable, Optional, Type, TYPE_CHECKING

from . import attributes, constants, errors
from .attributes import Attribute
from .typing import Any, VISAEventContext, VISAJobID
from .resources import Resource

if TYPE_CHECKING:
    from . import highlevel

class Event:
    """Event that lead to the call of an event handler.

    Do not instantiate directly use the visa_event context manager of the
    Resource object passed to the handler.

    """

    #: Reference to the visa library
    visalib: highlevel.VisaLibraryBase

    #: Type of the event.
    event_type: constants.EventType

    #: Context use to query the event attributes.
    _context: Optional[VISAEventContext]

    @classmethod
    def register(
        cls, event_type: constants.EventType,
    ) -> Callable[[Type["Event"]], Type["Event"]]:
        def _internal(python_class: Type["Event"]) -> Type["Event"]:
            Resource.register_event_class(event_type, python_class)

            for attr in attributes.AttributesPerResource[event_type]:
                if not hasattr(python_class, attr.py_name):
                    raise TypeError(
                        "%s is expected to have an attribute %s"
                        % (python_class, attr.py_name)
                    )

            return python_class

        return _internal

    def __init__(
        self,
        visalib: highlevel.VisaLibraryBase,
        event_type: constants.EventType,
        context: VISAEventContext,
    ) -> None:
        self.visalib = visalib
        self.event_type = event_type
        self._context = context

    @property
    def context(self) -> VISAEventContext:
        c = self._context
        if c is None:
            raise errors.InvalidSession()
        return c

    def get_visa_attribute(self, attribute_id: constants.EventAttribute) -> Any:
        """Get the specified VISA attribute.

        """
        return self.visalib.get_attribute(self.context, attribute_id)

# Those events do not have any payload beyond their type, for those use the base class
for event in (
    constants.EventType.clear,
    constants.EventType.service_request,
    constants.EventType.gpib_listen,
    constants.EventType.gpib_talk,
    constants.EventType.vxi_vme_sysfail,
    constants.EventType.vxi_vme_sysreset,
):
    Event.register(event)(Event)

@Event.register(constants.EventType.exception)
class ExceptionEvent(Event):
    """Event corresponding to an exception

    """

    #: Status code of the opertion that generated the exception
    status: Attribute[constants.StatusCode] = attributes.AttrVI_ATTR_STATUS()

    #: Name of the operation that led to the exception
    operation_name: Attribute[str] = attributes.AttrVI_ATTR_OPER_NAME()

@Event.register(constants.EventType.gpib_controller_in_charge)
class GPIBCICEvent(Event):
    """GPIB Controller in Charge event.

    The event is emitted if the status is gained or lost.

    """

    #: New state of the controller in charge status
    cic_state: Attribute[
        constants.LineState
    ] = attributes.AttrVI_ATTR_GPIB_RECV_CIC_STATE()

@Event.register(constants.EventType.io_completion)
class IOCompletionEvent(Event):
    """Event marking the completion of an IO operation.

    """

    #: Status code of the asynchronous I/O operation that has completed.
    status: Attribute[constants.StatusCode] = attributes.AttrVI_ATTR_STATUS()

    #: Buffer that was used in an asynchronous operation.
    buffer: Attribute[bytes] = attributes.AttrVI_ATTR_BUFFER()

    #: Actual number of elements that were asynchronously transferred.
    return_count: Attribute[int] = attributes.AttrVI_ATTR_RET_COUNT()

    #: Name of the operation generating the event.
    operation_name: Attribute[str] = attributes.AttrVI_ATTR_OPER_NAME()

    #: Job ID of the asynchronous operation that has completed.
    job_id: Attribute[VISAJobID] = attributes.AttrVI_ATTR_JOB_ID()

@Event.register(constants.EventType.trig)
class TrigEvent(Event):
    """Trigger event.

    """

    #: Identifier of the triggering mechanism on which the specified trigger event
    #: was received.
    trigger_id: Attribute[constants.TriggerID] = attributes.AttrVI_ATTR_TRIG_ID()

@Event.register(constants.EventType.usb_interrupt)
class USBInteruptEvent(Event):
    """USB interruption event.

    """

    #: Status of the read operation from the USB interrupt-IN pipe.
    status: Attribute[constants.StatusCode] = attributes.AttrVI_ATTR_STATUS()

    #: Size of the data that was received from the USB interrupt-IN pipe.
    size: Attribute[int] = attributes.AttrVI_ATTR_USB_RECV_INTR_SIZE()

    #: Actual data that was received from the USB interrupt-IN pipe.
    data = attributes.AttrVI_ATTR_USB_RECV_INTR_DATA()

@Event.register(constants.EventType.vxi_signal_interrupt)
class VXISignalInteruptEvent(Event):
    """VXI signal event.

    """

    #: 16-bit Status/ID value retrieved during the IACK cycle or
    #: from the Signal register.
    signal_register_status_id: Attribute[int] = attributes.AttrVI_ATTR_SIGP_STATUS_ID()

@Event.register(constants.EventType.vxi_vme_interrupt)
class VXIInterruptEvent(Event):
    """VXI interrupt event.

    """

    #: 32-bit status/ID retrieved during the IACK cycle.
    status_id: Attribute[int] = attributes.AttrVI_ATTR_INTR_STATUS_ID()

    #: VXI interrupt level on which the interrupt was received.
    level: Attribute[int] = attributes.AttrVI_ATTR_RECV_INTR_LEVEL()

@Event.register(constants.EventType.pxi_interrupt)
class PXIInteruptEvent(Event):
    """PXI interruption event.

    """

    #: Index of the interrupt sequence that detected the interrupt condition.
    sequence: Attribute[int] = attributes.AttrVI_ATTR_PXI_RECV_INTR_SEQ()

    #: First PXI/PCI register read in the successful interrupt detection sequence.
    data: Attribute[int] = attributes.AttrVI_ATTR_PXI_RECV_INTR_DATA()
<|endoftext|>


<commit_before>#!/usr/bin/python
'''
The MIT License (MIT)

Copyright (c) 2013 Quentin Gibert

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.

This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com
'''

from gi.repository import Gtk, Gdk, GLib
import threading, subprocess, re, os, time, Image
import geoip2.database
import geoip2.models
import geoip2.errors

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Traceroute")

        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(self.vbox)

        self.img = Gtk.Image.new_from_file("default.jpg")

        self.frame_rgb = Gtk.Frame(label='Map')
        self.frame_rgb.set_label_align(0.5, 0.5)
        self.frame_rgb.set_shadow_type(Gtk.ShadowType.IN)
        self.frame_rgb.add(self.img)

        self.vbox.pack_start(self.frame_rgb, True, True, 0)

        self.hbox = Gtk.Box(spacing=6)
        self.vbox.pack_start(self.hbox, True, True, 0)

        self.entry = Gtk.Entry()
        self.entry.set_text("www.example.com")
        self.hbox.pack_start(self.entry, True, True, 0)

        self.button1 = Gtk.Button(label="Trace")
        self.button1.connect("clicked", self.on_button_clicked)
        self.hbox.pack_start(self.button1, True, True, 0)

        self.statusbar = Gtk.Statusbar()
        self.vbox.pack_start(self.statusbar, True, True, 0)

    def on_button_clicked(self, widget):
        text = str(self.entry.get_text())
        threading.Thread(target=self.worker_trace, args=(text, )).start()

    def worker_trace(self, text):
        status_msg = "tracing " + str(text) + "..."
        print status_msg
        self.statusbar.push(self.statusbar.get_context_id("statusbar"), status_msg)
        ip_list = trace_route(str(text))
        locate_nodes(ip_list)
        trace_map()
        status_msg = "done tracing " + str(text) + "   "
        time.sleep(1)
        print status_msg
        self.statusbar.push(self.statusbar.get_context_id("statusbar"), status_msg)
        self.img.set_from_file("result.jpg")
        return

def trace_route(host):
    output = subprocess.check_output(['traceroute', host])
    pattern = re.compile("\((\d+\.\d+\.\d+\.\d+)\)")
    ip_list = pattern.findall(output)
    del ip_list[0]
    del ip_list[0]
    return ip_list

def locate_nodes(ip_list):
    points = open("points.dat", "w")
    start_stop = open("start_stop.dat", "w")
    points_list = []
    reader = geoip2.database.Reader('GeoLite2-City.mmdb')
    for ip in ip_list:
        response = reader.city(ip)
        if response != None:
            print ip
            output = '''    Country: %s
    City: %s
    Latitude: %s
    Longitude: %s
        ''' % (response.country.iso_code,
            response.city.name,
            response.location.latitude,
            response.location.longitude)
            pts_output = '''%s %s 0.1\n''' % (response.location.longitude, response.location.latitude)
            points.write(pts_output)
            points_list.append(pts_output)
            print output
    stop = points_list.pop()
    start = points_list.pop(0)
    start_stop.write(str(start) + "\n" + str(stop))
    start_stop.close()
    points.close()

def trace_map():
    ps_file = open("map.ps", "w")
    os.environ['PATH'] = "/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/gmt/bin"
    ps_map = subprocess.check_output(['pscoast', '-Rd', '-JN0/20c', '-Bg30', '-Dc', '-A10000', '-Ggray', '-P', '-X0.5c', '-Y10c', '-K'])
    ps_points = subprocess.check_output(['psxy', 'points.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc', '-G0', '-K'])
    ps_start_stop = subprocess.check_output(['psxy', 'start_stop.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc0.05', '-G255/0/0'])
    ps_file.write(ps_map)
    ps_file.write(ps_points)
    ps_file.write(ps_start_stop)
    ps_file.close()
    subprocess.call(['ps2raster', 'map.ps', '-Tj', '-A'])
    image = Image.open("map.jpg")
    width = 1024
    height = 520
    resized_img = image.resize((width, height), Image.ANTIALIAS)
    resized_img.save("result.jpg")

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
<commit_msg>ui improvements<commit_after>#!/usr/bin/python
'''
The MIT License (MIT)

Copyright (c) 2013 Quentin Gibert

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.

This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com
'''

from gi.repository import Gtk, Gdk, GLib
import threading, subprocess, re, os, time, Image
import geoip2.database
import geoip2.models
import geoip2.errors

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Traceroute")

        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(self.vbox)

        self.img = Gtk.Image.new_from_file("default.jpg")

        self.frame_rgb = Gtk.Frame(label='Map')
        self.frame_rgb.set_label_align(0.5, 0.5)
        self.frame_rgb.set_shadow_type(Gtk.ShadowType.IN)
        self.frame_rgb.add(self.img)

        self.vbox.pack_start(self.frame_rgb, True, True, 0)

        self.hbox = Gtk.Box(spacing=0)
        self.vbox.pack_start(self.hbox, False, False, 0)

        self.entry = Gtk.Entry()
        self.entry.set_text("www.example.com")
        self.hbox.pack_start(self.entry, True, True, 6)

        self.button1 = Gtk.Button(label="Trace")
        self.button1.connect("clicked", self.on_button_clicked)
        self.hbox.pack_start(self.button1, False, False, 6)

        self.statusbar = Gtk.Statusbar()
        self.vbox.pack_start(self.statusbar, False, False, 0)

    def on_button_clicked(self, widget):
        text = str(self.entry.get_text())
        threading.Thread(target=self.worker_trace, args=(text, )).start()

    def worker_trace(self, text):
        status_msg = "tracing " + str(text) + "..."
        print status_msg
        self.statusbar.push(self.statusbar.get_context_id("statusbar"), status_msg)
        ip_list = trace_route(str(text))
        locate_nodes(ip_list)
        trace_map()
        status_msg = "done tracing " + str(text) + "   "
        time.sleep(1)
        print status_msg
        self.statusbar.push(self.statusbar.get_context_id("statusbar"), status_msg)
        self.img.set_from_file("result.jpg")

def trace_route(host):
    output = subprocess.check_output(['traceroute', host])
    pattern = re.compile("\((\d+\.\d+\.\d+\.\d+)\)")
    ip_list = pattern.findall(output)
    del ip_list[0]
    del ip_list[0]
    return ip_list

def locate_nodes(ip_list):
    points = open("points.dat", "w")
    start_stop = open("start_stop.dat", "w")
    points_list = []
    reader = geoip2.database.Reader('GeoLite2-City.mmdb')
    for ip in ip_list:
        response = reader.city(ip)
        if response != None:
            print ip
            output = '''    Country: %s
    City: %s
    Latitude: %s
    Longitude: %s
        ''' % (response.country.iso_code,
            response.city.name,
            response.location.latitude,
            response.location.longitude)
            pts_output = '''%s %s 0.1\n''' % (response.location.longitude, response.location.latitude)
            points.write(pts_output)
            points_list.append(pts_output)
            print output
    stop = points_list.pop()
    start = points_list.pop(0)
    start_stop.write(str(start) + "\n" + str(stop))
    start_stop.close()
    points.close()

def trace_map():
    ps_file = open("map.ps", "w")
    os.environ['PATH'] = "/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/gmt/bin"
    ps_map = subprocess.check_output(['pscoast', '-Rd', '-JN0/20c', '-Bg30', '-Dc', '-A10000', '-Ggray', '-P', '-X0.5c', '-Y10c', '-K'])
    ps_points = subprocess.check_output(['psxy', 'points.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc', '-G0', '-K'])
    ps_start_stop = subprocess.check_output(['psxy', 'start_stop.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc0.05', '-G255/0/0'])
    ps_file.write(ps_map)
    ps_file.write(ps_points)
    ps_file.write(ps_start_stop)
    ps_file.close()
    subprocess.call(['ps2raster', 'map.ps', '-Tj', '-A'])
    image = Image.open("map.jpg")
    width = 1024
    height = 520
    resized_img = image.resize((width, height), Image.ANTIALIAS)
    resized_img.save("result.jpg")

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
<|endoftext|>


<commit_before>"""A set of tools for use in integration tests."""
import os
import tempfile
import subprocess
from hashlib import sha1
import numpy as np
import tables
from nose.tools import assert_equal

def hasher(x):
    return int(sha1(x.encode()).hexdigest(), 16)

def idx(h):
    ind = [None] * 5
    for i in range(4, -1, -1):
        h, ind[i] = divmod(h, 2**32)
    return tuple(ind)

sha1array = lambda x: np.array(idx(hasher(x)), np.uint32)

def table_exist(db, tables):
    """Checks if hdf5 database contains the specified tables.
    """
    return all([t in db.root for t in tables])

def find_ids(data, data_table, id_table):
    """Finds ids of the specified data located in the specified data_table,
    and extracts the corresponding id from the specified id_table.
    """
    ids = []
    for i, d in enumerate(data_table):
        if isinstance(d, np.ndarray) and isinstance(data, np.ndarray):
            if (d == data).all():
                ids.append(id_table[i])
        elif isinstance(d, np.ndarray) and not isinstance(data, np.ndarray):
            if (d == sha1array(data)).all():
                ids.append(id_table[i])
        elif d == data:
            ids.append(id_table[i])
    return ids

def exit_times(agent_id, exit_table):
    """Finds exit times of the specified agent from the exit table.
    """
    i = 0
    exit_times = []
    for index in exit_table["AgentId"]:
        if index == agent_id:
            exit_times.append(exit_table["ExitTime"][i])
        i += 1

    return exit_times

def run_cyclus(cyclus, cwd, in_path, out_path):
    """Runs cyclus with various inputs and creates output databases
    """
    holdsrtn = [1]  # needed because nose does not send() to test generator
    # make sure the output target directory exists
    cmd = [cyclus, "-o", out_path, "--input-file", in_path]
    check_cmd(cmd, cwd, holdsrtn)

def check_cmd(args, cwd, holdsrtn):
    """Runs a command in a subprocess and verifies that it executed properly.
    """
    if not isinstance(args, basestring):
        args = " ".join(args)
    print("TESTING: running command in {0}:\n\n{1}\n".format(cwd, args))
    env = dict(os.environ)
    env['_'] = subprocess.check_output(['which', 'cyclus'], cwd=cwd).strip()
    f = tempfile.NamedTemporaryFile()
    rtn = subprocess.call(args, shell=True, cwd=cwd, stdout=f, stderr=f, env=env)
    if rtn != 0:
        f.seek(0)
        print("STDOUT + STDERR:\n\n" + f.read().decode())
    f.close()
    holdsrtn[0] = rtn
    assert_equal(rtn, 0)
<commit_msg>helper.py comments updated<commit_after>"""A set of tools for use in integration tests."""
import os
import tempfile
import subprocess
import sys
from hashlib import sha1
import numpy as np
import tables
from nose.tools import assert_equal

if sys.version_info[0] > 3:
    str_types = (bytes, str)
else:
    str_types = (str, unicode)

def hasher(x):
    return int(sha1(x.encode()).hexdigest(), 16)

def idx(h):
    ind = [None] * 5
    for i in range(4, -1, -1):
        h, ind[i] = divmod(h, 2**32)
    return tuple(ind)

sha1array = lambda x: np.array(idx(hasher(x)), np.uint32)

def table_exist(db, tables):
    """Checks if hdf5 database contains the specified tables.
    """
    return all([t in db.root for t in tables])

def find_ids(data, data_table, id_table):
    """Finds ids of the specified data located in the specified data_table,
    and extracts the corresponding id from the specified id_table.
    """
    ids = []
    for i, d in enumerate(data_table):
        if isinstance(d, np.ndarray) and isinstance(data, np.ndarray):
            if (d == data).all():
                ids.append(id_table[i])
        elif isinstance(d, np.ndarray) and not isinstance(data, np.ndarray):
            if (d == sha1array(data)).all():
                ids.append(id_table[i])
        elif d == data:
            ids.append(id_table[i])
    return ids

def exit_times(agent_id, exit_table):
    """Finds exit times of the specified agent from the exit table.
    """
    i = 0
    exit_times = []
    for index in exit_table["AgentId"]:
        if index == agent_id:
            exit_times.append(exit_table["ExitTime"][i])
        i += 1

    return exit_times

def run_cyclus(cyclus, cwd, in_path, out_path):
    """Runs cyclus with various inputs and creates output databases
    """
    holdsrtn = [1]  # needed because nose does not send() to test generator
    # make sure the output target directory exists
    cmd = [cyclus, "-o", out_path, "--input-file", in_path]
    check_cmd(cmd, cwd, holdsrtn)

def check_cmd(args, cwd, holdsrtn):
    """Runs a command in a subprocess and verifies that it executed properly.
    """
    if not isinstance(args, str_types):
        args = " ".join(args)
    print("TESTING: running command in {0}:\n\n{1}\n".format(cwd, args))
    env = dict(os.environ)
    env['_'] = subprocess.check_output(['which', 'cyclus'], cwd=cwd).strip()
    with tempfile.NamedTemporaryFile() as f:
        rtn = subprocess.call(args, shell=True, cwd=cwd, stdout=f, stderr=f, env=env)
        if rtn != 0:
            f.seek(0)
            print("STDOUT + STDERR:\n\n" + f.read().decode())
    holdsrtn[0] = rtn
    assert_equal(rtn, 0)
<|endoftext|>


<commit_before>#!/usr/bin/python2
'''
The MIT License (MIT)

Copyright (c) 2013 Quentin Gibert

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.

This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com
'''

from gi.repository import Gtk, Gdk, GLib
import threading, subprocess, re, os, time, Image
import geoip2.database
import geoip2.models
import geoip2.errors

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Traceroute")

        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(self.vbox)

        self.img = Gtk.Image.new_from_file("default.bmp")

        self.frame_rgb = Gtk.Frame(label='Map')
        self.frame_rgb.set_label_align(0.5, 0.5)
        self.frame_rgb.set_shadow_type(Gtk.ShadowType.IN)
        self.frame_rgb.add(self.img)

        self.vbox.pack_start(self.frame_rgb, True, True, 0)

        self.hbox1 = Gtk.Box(spacing=0)
        self.vbox.pack_start(self.hbox1, False, False, 0)

        self.check_v4 = Gtk.RadioButton(None, "Use ipv4")
        self.check_v6 = Gtk.RadioButton.new_from_widget(self.check_v4)
        self.check_v6.set_label("Use ipv6")

        self.hbox1.pack_start(self.check_v4, False, False, 6)
        self.hbox1.pack_start(self.check_v6, False, False, 0)

        self.hbox = Gtk.Box(spacing=0)
        self.vbox.pack_start(self.hbox, False, False, 0)

        self.spinner = Gtk.Spinner()
        self.hbox.pack_start(self.spinner, False, True, 6)

        self.entry = Gtk.Entry()
        self.entry.set_text("www.example.com")
        self.hbox.pack_start(self.entry, True, True, 6)

        self.button1 = Gtk.Button(label="Trace")
        self.button1.connect("clicked", self.on_button_clicked)
        self.hbox.pack_start(self.button1, False, False, 6)

        self.statusbar = Gtk.Statusbar()
        self.vbox.pack_start(self.statusbar, False, False, 0)

    def on_button_clicked(self, widget):
        if self.check_v6.get_active():
            ipv = 6
        else:
            ipv = 4
        text = str(self.entry.get_text())
        self.button1.set_sensitive(False)
        self.spinner.start()
        self.statusbar.push(self.statusbar.get_context_id("statusbar"), "tracing " + str(text) + "... (IPv" + str(ipv) + ")")
        threading.Thread(target=self.worker_trace, args=(text, ipv)).start()

    def worker_trace(self, text, ipv):
        try:
            ip_list = trace_route(str(text), ipv)
            locate_nodes(ip_list)
            trace_map()
            time.sleep(1)
            self.statusbar.push(self.statusbar.get_context_id("statusbar"), "done tracing " + str(text) + "   ")
            self.img.set_from_file("result.bmp")
            self.button1.set_sensitive(True)
            self.spinner.stop()
        except Exception:
            self.statusbar.push(self.statusbar.get_context_id("statusbar"), "Failed to trace " + str(text))
            self.button1.set_sensitive(True)
            self.spinner.stop()
            return

def trace_route(host, ipv):
    if ipv == 6:
        pattern = "\((.*:.*)\)"
        traceroute = "traceroute6"
    else:
        pattern = "\((\d+\.\d+\.\d+\.\d+)\)"
        traceroute = "traceroute"
    output = subprocess.check_output([traceroute, host])
    regexp = re.compile(pattern)
    ip_list = regexp.findall(output)
    del ip_list[0]
    del ip_list[0]
    return ip_list

def locate_nodes(ip_list):
    points = open("points.dat", "w")
    start_stop = open("start_stop.dat", "w")
    points_list = []
    reader = geoip2.database.Reader('GeoLite2-City.mmdb')
    for ip in ip_list:
        response = reader.city(ip)
        if response != None:
            print ip
            output = '''    Country: %s
    City: %s
    Latitude: %s
    Longitude: %s
        ''' % (response.country.iso_code,
            response.city.name,
            response.location.latitude,
            response.location.longitude)
            pts_output = '''%s %s 0.1\n''' % (response.location.longitude, response.location.latitude)
            points.write(pts_output)
            points_list.append(pts_output)
            print output
    stop = points_list.pop()
    start = points_list.pop(0)
    start_stop.write(str(start) + "\n" + str(stop))
    start_stop.close()
    points.close()

def trace_map():
    ps_file = open("map.ps", "w")
    os.environ['PATH'] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/gmt/bin"
    ps_map = subprocess.check_output(['pscoast', '-Rd', '-JN0/20c', '-Bg30', '-Dc', '-A10000', '-Ggray', '-P', '-X0.5c', '-Y10c', '-K'])
    ps_lines = subprocess.check_output(['psxy', 'points.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Wthick', '-K'])
    ps_points = subprocess.check_output(['psxy', 'points.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc', '-G0', '-K'])
    ps_start_stop = subprocess.check_output(['psxy', 'start_stop.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc0.05', '-G255/0/0'])
    ps_file.write(ps_map)
    ps_file.write(ps_lines)
    ps_file.write(ps_points)
    ps_file.write(ps_start_stop)
    ps_file.close()
    subprocess.call(['ps2raster', 'map.ps', '-Tb', '-A'])
    image = Image.open("map.bmp")
    resized_img = image.resize((1024, 520), Image.ANTIALIAS)
    resized_img.save("result.bmp")

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
<commit_msg>handle unknown addresses<commit_after>#!/usr/bin/python2
'''
The MIT License (MIT)

Copyright (c) 2013 Quentin Gibert

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.

This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com
'''

from gi.repository import Gtk, Gdk, GLib
import threading, subprocess, re, os, time, Image
import geoip2.database
import geoip2.models
import geoip2.errors

class MyWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Traceroute")

        self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(self.vbox)

        self.img = Gtk.Image.new_from_file("default.bmp")

        self.frame_rgb = Gtk.Frame(label='Map')
        self.frame_rgb.set_label_align(0.5, 0.5)
        self.frame_rgb.set_shadow_type(Gtk.ShadowType.IN)
        self.frame_rgb.add(self.img)

        self.vbox.pack_start(self.frame_rgb, True, True, 0)

        self.hbox1 = Gtk.Box(spacing=0)
        self.vbox.pack_start(self.hbox1, False, False, 0)

        self.check_v4 = Gtk.RadioButton(None, "Use ipv4")
        self.check_v6 = Gtk.RadioButton.new_from_widget(self.check_v4)
        self.check_v6.set_label("Use ipv6")

        self.hbox1.pack_start(self.check_v4, False, False, 6)
        self.hbox1.pack_start(self.check_v6, False, False, 0)

        self.hbox = Gtk.Box(spacing=0)
        self.vbox.pack_start(self.hbox, False, False, 0)

        self.spinner = Gtk.Spinner()
        self.hbox.pack_start(self.spinner, False, True, 6)

        self.entry = Gtk.Entry()
        self.entry.set_text("www.example.com")
        self.hbox.pack_start(self.entry, True, True, 6)

        self.button1 = Gtk.Button(label="Trace")
        self.button1.connect("clicked", self.on_button_clicked)
        self.hbox.pack_start(self.button1, False, False, 6)

        self.statusbar = Gtk.Statusbar()
        self.vbox.pack_start(self.statusbar, False, False, 0)

    def on_button_clicked(self, widget):
        if self.check_v6.get_active():
            ipv = 6
        else:
            ipv = 4
        text = str(self.entry.get_text())
        self.button1.set_sensitive(False)
        self.spinner.start()
        self.statusbar.push(self.statusbar.get_context_id("statusbar"), "tracing " + str(text) + "... (IPv" + str(ipv) + ")")
        threading.Thread(target=self.worker_trace, args=(text, ipv)).start()

    def worker_trace(self, text, ipv):
        try:
            ip_list = trace_route(str(text), ipv)
            locate_nodes(ip_list)
            trace_map()
            time.sleep(1)
            self.statusbar.push(self.statusbar.get_context_id("statusbar"), "done tracing " + str(text) + "   ")
            self.img.set_from_file("result.bmp")
            self.button1.set_sensitive(True)
            self.spinner.stop()
        except Exception:
            self.statusbar.push(self.statusbar.get_context_id("statusbar"), "Failed to trace " + str(text))
            self.button1.set_sensitive(True)
            self.spinner.stop()
            return

def trace_route(host, ipv):
    if ipv == 6:
        pattern = "\((.*:.*)\)"
        traceroute = "traceroute6"
    else:
        pattern = "\((\d+\.\d+\.\d+\.\d+)\)"
        traceroute = "traceroute"
    output = subprocess.check_output([traceroute, host])
    regexp = re.compile(pattern)
    ip_list = regexp.findall(output)
    del ip_list[0]
    del ip_list[0]
    return ip_list

def locate_nodes(ip_list):
    points = open("points.dat", "w")
    start_stop = open("start_stop.dat", "w")
    points_list = []
    reader = geoip2.database.Reader('GeoLite2-City.mmdb')
    for ip in ip_list:
        try:
            response = reader.city(ip)
        except Exception, e:
            print str(e)
        if response != None:
            print ip
            output = '''    Country: %s
    City: %s
    Latitude: %s
    Longitude: %s
        ''' % (response.country.iso_code,
            response.city.name,
            response.location.latitude,
            response.location.longitude)
            pts_output = '''%s %s 0.1\n''' % (response.location.longitude, response.location.latitude)
            points.write(pts_output)
            points_list.append(pts_output)
            print output
    stop = points_list.pop()
    start = points_list.pop(0)
    start_stop.write(str(start) + "\n" + str(stop))
    start_stop.close()
    points.close()

def trace_map():
    ps_file = open("map.ps", "w")
    os.environ['PATH'] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/gmt/bin"
    ps_map = subprocess.check_output(['pscoast', '-Rd', '-JN0/20c', '-Bg30', '-Dc', '-A10000', '-Ggray', '-P', '-X0.5c', '-Y10c', '-K'])
    ps_lines = subprocess.check_output(['psxy', 'points.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Wthick', '-K'])
    ps_points = subprocess.check_output(['psxy', 'points.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc', '-G0', '-K'])
    ps_start_stop = subprocess.check_output(['psxy', 'start_stop.dat', '-O', '-Rd', '-JN', '-Dc', '-A10000', '-P', '-Sc0.05', '-G255/0/0'])
    ps_file.write(ps_map)
    ps_file.write(ps_lines)
    ps_file.write(ps_points)
    ps_file.write(ps_start_stop)
    ps_file.close()
    subprocess.call(['ps2raster', 'map.ps', '-Tb', '-A'])
    image = Image.open("map.bmp")
    resized_img = image.resize((1024, 520), Image.ANTIALIAS)
    resized_img.save("result.bmp")

win = MyWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
GLib.threads_init()
Gdk.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
<|endoftext|>