<commit_before>#!/usr/bin/env python
# Copyright (c) 2015, Job Snijders
#
# This file is part of IRR Explorer
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from irrexplorer import config
from irrexplorer import nrtm
from irrexplorer import ripe
from irrexplorer import bgp
from irrexplorer import utils

import threading
import multiprocessing
import radix

from flask import Flask, render_template, request, flash, redirect, \
    url_for
from flask_bootstrap import Bootstrap
from flask_wtf import Form
from wtforms import TextField, SubmitField
from wtforms.validators import Required

class LookupWorker(threading.Thread):
    def __init__(self, tree, asn_prefix_map, assets,
                 lookup_queue, result_queue):
        threading.Thread.__init__(self)
        self.tree = tree
        self.lookup_queue = lookup_queue
        self.result_queue = result_queue
        self.asn_prefix_map = asn_prefix_map
        self.assets = assets

    def run(self):
        while True:
            lookup, target = self.lookup_queue.get()
            results = {}
            if not lookup:
                continue
            if lookup == "search_specifics":
                data = None
                # cheat a little by simple sharding!
                # split all prefixes in 6 chunks, have each list worked
                # on by a Proces()
                pool = multiprocessing.Pool(6)
                parts = [self.tree.prefixes()[i::6] for i in range(6)]  # split all pfx in 4 lists
                job_args = [(target, p) for p in parts]  # workaround pool() only accepts 1 arg
                specifics = pool.map(utils.find_more_sp_helper, job_args)
                # next line flattens the list of lists
                for prefix in [item for sublist in specifics for item in sublist]:
                    data = self.tree.search_exact(prefix).data
                    results[prefix] = {}
                    results[prefix]['origins'] = data['origins']
                self.result_queue.put(results)

            elif lookup == "search_aggregate":
                rnode = self.tree.search_worst(target)
                if not rnode:
                    self.result_queue.put(None)
                else:
                    prefix = rnode.prefix
                    data = rnode.data
                    self.result_queue.put((prefix, data))

            elif lookup == "inverseasn":
                if target in self.asn_prefix_map:
                    self.result_queue.put(self.asn_prefix_map[target])
                else:
                    self.result_queue.put([])

            elif lookup == "asset_search":
                if target in self.assets:
                    self.result_queue.put(self.assets[target])
                else:
                    self.result_queue.put([])

            self.lookup_queue.task_done()

class NRTMWorker(multiprocessing.Process):
    """
    Launches an nrtm.client() instance and feeds the output in to a
    radix tree. Somehow allow other processes to lookup entries in the
    radix tree. Destroy & rebuild radix tree when serial overruns and
    a new connection must be established with the NRTM host.
    """
    def __init__(self, feedconfig, lookup_queue, result_queue):
        """
        Constructor.
        @param config dict() with NRTM host information
        @param nrtm_queue Queue() where NRTM output goes
        """
        multiprocessing.Process.__init__(self)
        self.feedconfig = feedconfig
        self.lookup_queue = lookup_queue
        self.result_queue = result_queue
        self.tree = radix.Radix()
        self.dbname = feedconfig['dbname']
        self.asn_prefix_map = {}
        self.assets = {}
        self.lookup = LookupWorker(self.tree, self.asn_prefix_map, self.assets,
                                   self.lookup_queue, self.result_queue)

# TODO
# add completly new rnode from irr
# add completly new rnode from bgp
# add more data to existing rnode
# remove data from existing rnode
# remove existing rnode (last bgp or irr withdraw)

    def run(self):
        """
        Process run method, fetch NRTM updates and put them in the
        a radix tree.
        """
        self.lookup.setDaemon(True)
        self.lookup.start()

        self.feed = nrtm.client(**self.feedconfig)
        while True:
            for cmd, serial, obj in self.feed.get():
                if not obj:
                    continue
                try:
                    if not self.dbname == obj['source']:
                        """ ignore updates for which the source does not
                        match the configured/expected database """
                        continue
                except:
                    print "ERROR: weird object: %s" % obj
                    continue

                if obj['kind'] in ["route", "route6"]:
                    if cmd == "ADD":
                        if not self.tree.search_exact(obj['name']):
                            # FIXME does sometimes fails in the pure python
                            # py-radix
                            rnode = self.tree.add(obj['name'])
                            rnode.data['origins'] = [obj['origin']]
                        else:
                            rnode = self.tree.search_exact(obj['name'])
                            rnode.data['origins'] = set([obj['origin']] + list(rnode.data['origins']))

                        # add prefix to the inverse ASN map
                        if obj['origin'] not in self.asn_prefix_map:
                            self.asn_prefix_map[obj['origin']] = [obj['name']]
                        else:
                            self.asn_prefix_map[obj['origin']].append(obj['name'])
                    else:
                        try:
                            self.tree.delete(obj['name'])
                            self.asn_prefix_map[obj['origin']].remove(obj['name'])
                        except KeyError:
                            print "ERROR: could not remove this object from the tree in %s" % self.dbname
                            print obj

                if obj['kind'] == "as-set":
                    if cmd == "ADD":
                        self.assets[obj['name']] = obj['members']
                    else:
                        del self.assets[obj['name']]

databases = config('irrexplorer_config.yml').databases
lookup_queues = {}
result_queues = {}
for dbase in databases:
    name = dbase.keys()[0]
    feedconfig = dbase[name]
    feedconfig = dict(d.items()[0] for d in feedconfig)
    lookup_queues[name] = multiprocessing.JoinableQueue()
    result_queues[name] = multiprocessing.JoinableQueue()
    worker = NRTMWorker(feedconfig, lookup_queues[name], result_queues[name])
    worker.start()

# Launch helper processes for BGP & RIPE managed space lookups
for q in ['RIPE-AUTH', 'BGP']:
    lookup_queues[q] = multiprocessing.JoinableQueue()
    result_queues[q] = multiprocessing.JoinableQueue()
worker = bgp.BGPWorker(lookup_queues['BGP'], result_queues['BGP'])
worker.start()
worker = ripe.RIPEWorker(lookup_queues['RIPE-AUTH'],
                         result_queues['RIPE-AUTH'])
worker.start()

import time
for i in range(0, 120):
    print i
    time.sleep(1)

def irr_query(query_type, target):
    global lookup_queues
    global result_queues
    for i in lookup_queues:
        if i in ['BGP', 'RIPE-AUTH']:
            continue
        print "doing lookup for %s in %s" % (target, i)
        lookup_queues[i].put((query_type, target))
    for i in lookup_queues:
        if i in ['BGP', 'RIPE-AUTH']:
            continue
        lookup_queues[i].join()
    result = {}
    for i in result_queues:
        if i in ['BGP', 'RIPE-AUTH']:
            continue
        result[i] = result_queues[i].get()
        result_queues[i].task_done()
    return result

def other_query(data_source, query_type, target):
    global lookup_queues
    global result_queues
    lookup_queues[data_source].put((query_type, target))
    lookup_queues[data_source].join()
    result = result_queues[data_source].get()
    result_queues[data_source].task_done()
    return result

def bgp_query():
    pass

def ripe_query():
    pass

def prefix_report(prefix):
    """
        - find least specific
        - search in BGP for more specifics
        - search in IRR for more specifics
        - check all prefixes whether they are RIPE managed or not
        - return dict
    """
    tree = radix.Radix()
    bgp_aggregate = other_query("BGP", "search_aggregate", prefix)
    if bgp_aggregate:
        tree.add(bgp_aggregate)
    irr_aggregate = irr_query("search_aggregate", prefix)
    for r in irr_aggregate:
        if irr_aggregate[r]:
            tree.add(irr_aggregate[r][0])
    aggregate = tree.search_worst(prefix)
    if not aggregate:
        return """Could not find prefix in IRR or BGP tables: %s""" \
            % tree.prefixes()

    else:
        aggregate = aggregate.prefix
    bgp_specifics = other_query("BGP", "search_specifics", aggregate)
    irr_specifics = irr_query("search_specifics", aggregate)
    prefixes = {}
    for p in bgp_specifics:
        if p not in prefixes:
            prefixes[p] = {'bgp_origin': bgp_specifics[p]['origins']}
        else:
            prefixes[p]['bgp_origin'] = bgp_specifics[p]['origins']

    for db in irr_specifics:
        if not irr_specifics[db]:
            for p in prefixes:
                prefixes[p][db] = False
            continue
        for p in irr_specifics[db]:
            if p not in prefixes:
                prefixes[p] = {}
                prefixes[p][db] = irr_specifics[db][p]['origins']
            else:
                prefixes[p][db] = irr_specifics[db][p]['origins']

    for p in prefixes:
#        if p not in bgp_specifics:
#            prefixes[p]['bgp_origin'] = False
        if other_query("RIPE-AUTH", "is_covered", p):
            prefixes[p]['ripe_managed'] = True
        else:
            prefixes[p]['ripe_managed'] = False

    return str(prefixes)

class InputForm(Form):
    field2 = TextField('Data', description='Input ASN, AS-SET or Prefix.',
                       validators=[Required()])
    submit_button = SubmitField('Submit')

def create_app(configfile=None):
    app = Flask(__name__)
    app.config.from_pyfile('appconfig.cfg')
    Bootstrap(app)

    @app.route('/', methods=['GET', 'POST'])
    def index():
        form = InputForm()
        if request.method == 'GET':
            return render_template('index.html', form=form)

        if request.method == 'POST':
            data = form.field2.data
            try:
                int(data)
                data = "AS%s" % data
            except ValueError:
                pass

            if utils.is_autnum(data):
                return redirect(url_for('autnum', autnum=data))

            elif utils.is_ipnetwork(data):
                flash('Just one field is required, fill it in!')
                return redirect(url_for('prefix', prefix=data))

#FIXME no support for as-set digging for now
#            elif data.startswith('AS'):
#                return redirect(url_for('asset', asset=data))

            else:
                return render_template('index.html', form=form)

    @app.route('/autnum/<autnum>')
    def autnum(autnum):
        return str(irr_query("inverseasn", autnum))

    @app.route('/prefix/<path:prefix>')
    def prefix(prefix):
        return prefix_report(prefix)
#        return str(query("search_specifics", prefix))

#    @app.route('/asset/<asset>')
#    def asset(asset):
#        return str(utils.lookup_assets(asset))

    return app

if __name__ == '__main__':
    create_app().run(host="0.0.0.0", debug=True, use_reloader=False)
<commit_msg>enable BGP origins debugging<commit_after>#!/usr/bin/env python
# Copyright (c) 2015, Job Snijders
#
# This file is part of IRR Explorer
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from irrexplorer import config
from irrexplorer import nrtm
from irrexplorer import ripe
from irrexplorer import bgp
from irrexplorer import utils

import threading
import multiprocessing
import radix

from flask import Flask, render_template, request, flash, redirect, \
    url_for
from flask_bootstrap import Bootstrap
from flask_wtf import Form
from wtforms import TextField, SubmitField
from wtforms.validators import Required

class LookupWorker(threading.Thread):
    def __init__(self, tree, asn_prefix_map, assets,
                 lookup_queue, result_queue):
        threading.Thread.__init__(self)
        self.tree = tree
        self.lookup_queue = lookup_queue
        self.result_queue = result_queue
        self.asn_prefix_map = asn_prefix_map
        self.assets = assets

    def run(self):
        while True:
            lookup, target = self.lookup_queue.get()
            results = {}
            if not lookup:
                continue
            if lookup == "search_specifics":
                data = None
                # cheat a little by simple sharding!
                # split all prefixes in 6 chunks, have each list worked
                # on by a Proces()
                pool = multiprocessing.Pool(6)
                parts = [self.tree.prefixes()[i::6] for i in range(6)]  # split all pfx in 4 lists
                job_args = [(target, p) for p in parts]  # workaround pool() only accepts 1 arg
                specifics = pool.map(utils.find_more_sp_helper, job_args)
                # next line flattens the list of lists
                for prefix in [item for sublist in specifics for item in sublist]:
                    data = self.tree.search_exact(prefix).data
                    results[prefix] = {}
                    results[prefix]['origins'] = data['origins']
                self.result_queue.put(results)

            elif lookup == "search_aggregate":
                rnode = self.tree.search_worst(target)
                if not rnode:
                    self.result_queue.put(None)
                else:
                    prefix = rnode.prefix
                    data = rnode.data
                    self.result_queue.put((prefix, data))

            elif lookup == "inverseasn":
                if target in self.asn_prefix_map:
                    self.result_queue.put(self.asn_prefix_map[target])
                else:
                    self.result_queue.put([])

            elif lookup == "asset_search":
                if target in self.assets:
                    self.result_queue.put(self.assets[target])
                else:
                    self.result_queue.put([])

            self.lookup_queue.task_done()

class NRTMWorker(multiprocessing.Process):
    """
    Launches an nrtm.client() instance and feeds the output in to a
    radix tree. Somehow allow other processes to lookup entries in the
    radix tree. Destroy & rebuild radix tree when serial overruns and
    a new connection must be established with the NRTM host.
    """
    def __init__(self, feedconfig, lookup_queue, result_queue):
        """
        Constructor.
        @param config dict() with NRTM host information
        @param nrtm_queue Queue() where NRTM output goes
        """
        multiprocessing.Process.__init__(self)
        self.feedconfig = feedconfig
        self.lookup_queue = lookup_queue
        self.result_queue = result_queue
        self.tree = radix.Radix()
        self.dbname = feedconfig['dbname']
        self.asn_prefix_map = {}
        self.assets = {}
        self.lookup = LookupWorker(self.tree, self.asn_prefix_map, self.assets,
                                   self.lookup_queue, self.result_queue)

# TODO
# add completly new rnode from irr
# add completly new rnode from bgp
# add more data to existing rnode
# remove data from existing rnode
# remove existing rnode (last bgp or irr withdraw)

    def run(self):
        """
        Process run method, fetch NRTM updates and put them in the
        a radix tree.
        """
        self.lookup.setDaemon(True)
        self.lookup.start()

        self.feed = nrtm.client(**self.feedconfig)
        while True:
            for cmd, serial, obj in self.feed.get():
                if not obj:
                    continue
                try:
                    if not self.dbname == obj['source']:
                        """ ignore updates for which the source does not
                        match the configured/expected database """
                        continue
                except:
                    print "ERROR: weird object: %s" % obj
                    continue

                if obj['kind'] in ["route", "route6"]:
                    if cmd == "ADD":
                        if not self.tree.search_exact(obj['name']):
                            # FIXME does sometimes fails in the pure python
                            # py-radix
                            rnode = self.tree.add(obj['name'])
                            rnode.data['origins'] = [obj['origin']]
                        else:
                            rnode = self.tree.search_exact(obj['name'])
                            rnode.data['origins'] = set([obj['origin']] + list(rnode.data['origins']))

                        # add prefix to the inverse ASN map
                        if obj['origin'] not in self.asn_prefix_map:
                            self.asn_prefix_map[obj['origin']] = [obj['name']]
                        else:
                            self.asn_prefix_map[obj['origin']].append(obj['name'])
                    else:
                        try:
                            self.tree.delete(obj['name'])
                            self.asn_prefix_map[obj['origin']].remove(obj['name'])
                        except KeyError:
                            print "ERROR: could not remove this object from the tree in %s" % self.dbname
                            print obj

                if obj['kind'] == "as-set":
                    if cmd == "ADD":
                        self.assets[obj['name']] = obj['members']
                    else:
                        del self.assets[obj['name']]

databases = config('irrexplorer_config.yml').databases
lookup_queues = {}
result_queues = {}
for dbase in databases:
    name = dbase.keys()[0]
    feedconfig = dbase[name]
    feedconfig = dict(d.items()[0] for d in feedconfig)
    lookup_queues[name] = multiprocessing.JoinableQueue()
    result_queues[name] = multiprocessing.JoinableQueue()
    worker = NRTMWorker(feedconfig, lookup_queues[name], result_queues[name])
    worker.start()

# Launch helper processes for BGP & RIPE managed space lookups
for q in ['RIPE-AUTH', 'BGP']:
    lookup_queues[q] = multiprocessing.JoinableQueue()
    result_queues[q] = multiprocessing.JoinableQueue()
worker = bgp.BGPWorker(lookup_queues['BGP'], result_queues['BGP'])
worker.start()
worker = ripe.RIPEWorker(lookup_queues['RIPE-AUTH'],
                         result_queues['RIPE-AUTH'])
worker.start()

import time
for i in range(0, 120):
    print i
    time.sleep(1)

def irr_query(query_type, target):
    global lookup_queues
    global result_queues
    for i in lookup_queues:
        if i in ['BGP', 'RIPE-AUTH']:
            continue
        print "doing lookup for %s in %s" % (target, i)
        lookup_queues[i].put((query_type, target))
    for i in lookup_queues:
        if i in ['BGP', 'RIPE-AUTH']:
            continue
        lookup_queues[i].join()
    result = {}
    for i in result_queues:
        if i in ['BGP', 'RIPE-AUTH']:
            continue
        result[i] = result_queues[i].get()
        result_queues[i].task_done()
    return result

def other_query(data_source, query_type, target):
    global lookup_queues
    global result_queues
    lookup_queues[data_source].put((query_type, target))
    lookup_queues[data_source].join()
    result = result_queues[data_source].get()
    result_queues[data_source].task_done()
    return result

def bgp_query():
    pass

def ripe_query():
    pass

def prefix_report(prefix):
    """
        - find least specific
        - search in BGP for more specifics
        - search in IRR for more specifics
        - check all prefixes whether they are RIPE managed or not
        - return dict
    """
    tree = radix.Radix()
    bgp_aggregate = other_query("BGP", "search_aggregate", prefix)
    if bgp_aggregate:
        tree.add(bgp_aggregate)
    irr_aggregate = irr_query("search_aggregate", prefix)
    for r in irr_aggregate:
        if irr_aggregate[r]:
            tree.add(irr_aggregate[r][0])
    aggregate = tree.search_worst(prefix)
    if not aggregate:
        return """Could not find prefix in IRR or BGP tables: %s""" \
            % tree.prefixes()

    else:
        aggregate = aggregate.prefix
    bgp_specifics = other_query("BGP", "search_specifics", aggregate)
    print bgp_specifics
    irr_specifics = irr_query("search_specifics", aggregate)
    prefixes = {}
    for p in bgp_specifics:
        if p not in prefixes:
            prefixes[p] = {'bgp_origin': bgp_specifics[p]['origins']}
        else:
            prefixes[p]['bgp_origin'] = bgp_specifics[p]['origins']

    for db in irr_specifics:
        if not irr_specifics[db]:
            for p in prefixes:
                prefixes[p][db] = False
            continue
        for p in irr_specifics[db]:
            if p not in prefixes:
                prefixes[p] = {}
                prefixes[p][db] = irr_specifics[db][p]['origins']
            else:
                prefixes[p][db] = irr_specifics[db][p]['origins']

    for p in prefixes:
        if p not in bgp_specifics:
            prefixes[p]['bgp_origin'] = False
        if other_query("RIPE-AUTH", "is_covered", p):
            prefixes[p]['ripe_managed'] = True
        else:
            prefixes[p]['ripe_managed'] = False

    return str(prefixes)

class InputForm(Form):
    field2 = TextField('Data', description='Input ASN, AS-SET or Prefix.',
                       validators=[Required()])
    submit_button = SubmitField('Submit')

def create_app(configfile=None):
    app = Flask(__name__)
    app.config.from_pyfile('appconfig.cfg')
    Bootstrap(app)

    @app.route('/', methods=['GET', 'POST'])
    def index():
        form = InputForm()
        if request.method == 'GET':
            return render_template('index.html', form=form)

        if request.method == 'POST':
            data = form.field2.data
            try:
                int(data)
                data = "AS%s" % data
            except ValueError:
                pass

            if utils.is_autnum(data):
                return redirect(url_for('autnum', autnum=data))

            elif utils.is_ipnetwork(data):
                flash('Just one field is required, fill it in!')
                return redirect(url_for('prefix', prefix=data))

#FIXME no support for as-set digging for now
#            elif data.startswith('AS'):
#                return redirect(url_for('asset', asset=data))

            else:
                return render_template('index.html', form=form)

    @app.route('/autnum/<autnum>')
    def autnum(autnum):
        return str(irr_query("inverseasn", autnum))

    @app.route('/prefix/<path:prefix>')
    def prefix(prefix):
        return prefix_report(prefix)
#        return str(query("search_specifics", prefix))

#    @app.route('/asset/<asset>')
#    def asset(asset):
#        return str(utils.lookup_assets(asset))

    return app

if __name__ == '__main__':
    create_app().run(host="0.0.0.0", debug=True, use_reloader=False)
<|endoftext|>


<commit_before># Copyright 2016 the Queen's University Biological Station

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

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

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

import datetime, dateutil.parser, pytz

from rest_framework import mixins, generics
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework import permissions
from django.contrib.auth.models import User

from core.models import *
from core.serializers import *

@api_view(["GET"])
def api_root(request, format=None):
    return Response({
        "sensors": reverse("sensor-list", request=request, format=format),
        "stations": reverse("station-list", request=request, format=format),
        "station-sensor-links": reverse("station-sensor-link-list", request=request, format=format),
        "readings": reverse("reading-list", request=request, format=format),
        "messages": reverse("message-list", request=request, format=format),
        "settings": reverse("setting-list", request=request, format=format),
        "users": reverse("user-list", request=request, format=format),
    })

class SensorList(generics.ListCreateAPIView):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SensorDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SensorData(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return Reading.objects.filter(sensor=pk)

class SensorStations(generics.ListAPIView):
    serializer_class = StationSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]

        return Station.objects.filter(
            sensors__id=pk
        )

class StationList(generics.ListCreateAPIView):
    serializer_class = StationSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        queryset = Station.objects.all()

        goes_id = self.request.query_params.get("goes_id", None)
        if goes_id is not None:
            queryset = Station.objects.filter(goes_id=goes_id)

        return queryset

class StationDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Station.objects.all()
    serializer_class = StationSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class StationData(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]

        start_date = self.request.query_params.get("start", None)
        start_date_object = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=7) # Default to a week's worth
        if start_date != None:
            start_date_object = dateutil.parser.parse(start_date)

        end_date = self.request.query_params.get("end", None)
        end_date_object = datetime.datetime.now(pytz.utc)
        if end_date != None:
            end_date_object = dateutil.parser.parse(end_date)

        return Reading.objects.filter(
            station=pk,
            read_time__gte=start_date_object,
            read_time__lte=end_date_object
        )

class StationLatestData(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        latest_message = Message.objects.filter(station=pk).latest("arrival_time")
        start_date_object = latest_message.arrival_time - datetime.timedelta(hours=1)

        return Reading.objects.filter(
            station=pk,
            read_time__gte = start_date_object,
        )

class StationSensors(generics.ListAPIView):
    serializer_class = SensorSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return Sensor.objects.filter(stations__id=pk).order_by("stationsensorlink__station_order")

class StationMessages(generics.ListAPIView):
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return Message.objects.filter(station=pk).order_by("arrival_time")

class StationLatestMessage(generics.RetrieveAPIView):
    queryset = Message.objects.all()
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_object(self):
        pk = self.kwargs["pk"]
        return self.queryset.filter(station_id=pk).latest("arrival_time")

class StationSensorLinkList(generics.ListCreateAPIView):
    queryset = StationSensorLink.objects.all().order_by("created")
    serializer_class = StationSensorLinkSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class StationSensorLinkDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = StationSensorLink.objects.all()
    serializer_class = StationSensorLinkSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class ReadingList(generics.ListCreateAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        start_date = self.request.query_params.get("start", None)
        start_date_object = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=7) # Default to a week's worth
        if start_date != None:
            start_date_object = dateutil.parser.parse(start_date)

        end_date = self.request.query_params.get("end", None)
        end_date_object = datetime.datetime.now(pytz.utc)
        if end_date != None:
            end_date_object = dateutil.parser.parse(end_date)

        start_exclusive = self.request.query_params.get("start_exclusive", False)
        sensors = self.request.query_params.get("sensors", None)

        queryset = Reading.objects.filter(
            read_time__gte=start_date_object,
            read_time__lte=end_date_object
        )

        if start_exclusive == "true":
            queryset = Reading.objects.filter(
                read_time__gt=start_date_object,
                read_time__lte=end_date_object
            )

        if sensors is not None:
            sensor_list = sensors.split(",")
            queryset = queryset.filter(sensor__in=sensor_list)

        queryset = queryset.order_by("read_time")
        return queryset

class ReadingDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Reading.objects.all()
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class ReadingLatest(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        stations = Station.objects.all()
        station_ids = []
        for s in stations:
            station_ids.append(s.id)

        latest_message = Message.objects.all().latest("arrival_time")
        start_date_object = latest_message.arrival_time - datetime.timedelta(hours=1)

        return Reading.objects.filter(
            station__in=station_ids,
            read_time__gte=start_date_object,
        )

class MessageList(generics.ListCreateAPIView):
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        print("--- CREATING MESSAGE ---")
        print(self.request.data)
        print("------------------------")
        serializer.save()

    def get_queryset(self):
        start_date = self.request.query_params.get("start", None)
        start_date_object = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=7) # Default to a week's worth
        if start_date != None:
            start_date_object = dateutil.parser.parse(start_date)

        end_date = self.request.query_params.get("end", None)
        end_date_object = datetime.datetime.now(pytz.utc)
        if end_date != None:
            end_date_object = dateutil.parser.parse(end_date)

        start_exclusive = self.request.query_params.get("start_exclusive", False)

        queryset = Message.objects.filter(
            arrival_time__gte=start_date_object,
            arrival_time__lte=end_date_object
        )

        if start_exclusive == "true":
            queryset = Message.objects.filter(
                arrival_time__gt=start_date_object,
                arrival_time__lte=end_date_object
            )

        queryset = queryset.order_by("arrival_time")

        goes_id = self.request.query_params.get("goes_id", None)
        if goes_id is not None:
            queryset = Message.objects.filter(
                arrival_time__gte=start_date_object,
                arrival_time__lte=end_date_object,

                goes_id=goes_id
            ).order_by("arrival_time")

        return queryset

class MessageDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Message.objects.all()
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class MessageLatest(generics.ListAPIView):
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        latest_message = Message.objects.all().latest("arrival_time")
        start_date_object = latest_message.arrival_time - datetime.timedelta(hours=1)

        return Message.objects.filter(
            arrival_time__gte=start_date_object
        )

class SettingList(generics.ListAPIView):
    queryset = Setting.objects.all()
    serializer_class = SettingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SettingDetail(generics.RetrieveUpdateAPIView):
    queryset = Setting.objects.all()
    serializer_class = SettingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SettingDetailWithName(generics.RetrieveUpdateAPIView):
    queryset = Setting.objects.all()
    serializer_class = SettingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_object(self):
        print(self.kwargs)
        name = self.kwargs["name"]
        return self.queryset.filter(name=name).first()

class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
<commit_msg>Remove an unneeded debug output.<commit_after># Copyright 2016 the Queen's University Biological Station

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

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

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

import datetime, dateutil.parser, pytz

from rest_framework import mixins, generics
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework import permissions
from django.contrib.auth.models import User

from core.models import *
from core.serializers import *

@api_view(["GET"])
def api_root(request, format=None):
    return Response({
        "sensors": reverse("sensor-list", request=request, format=format),
        "stations": reverse("station-list", request=request, format=format),
        "station-sensor-links": reverse("station-sensor-link-list", request=request, format=format),
        "readings": reverse("reading-list", request=request, format=format),
        "messages": reverse("message-list", request=request, format=format),
        "settings": reverse("setting-list", request=request, format=format),
        "users": reverse("user-list", request=request, format=format),
    })

class SensorList(generics.ListCreateAPIView):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SensorDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SensorData(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return Reading.objects.filter(sensor=pk)

class SensorStations(generics.ListAPIView):
    serializer_class = StationSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]

        return Station.objects.filter(
            sensors__id=pk
        )

class StationList(generics.ListCreateAPIView):
    serializer_class = StationSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        queryset = Station.objects.all()

        goes_id = self.request.query_params.get("goes_id", None)
        if goes_id is not None:
            queryset = Station.objects.filter(goes_id=goes_id)

        return queryset

class StationDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Station.objects.all()
    serializer_class = StationSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class StationData(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]

        start_date = self.request.query_params.get("start", None)
        start_date_object = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=7) # Default to a week's worth
        if start_date != None:
            start_date_object = dateutil.parser.parse(start_date)

        end_date = self.request.query_params.get("end", None)
        end_date_object = datetime.datetime.now(pytz.utc)
        if end_date != None:
            end_date_object = dateutil.parser.parse(end_date)

        return Reading.objects.filter(
            station=pk,
            read_time__gte=start_date_object,
            read_time__lte=end_date_object
        )

class StationLatestData(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        latest_message = Message.objects.filter(station=pk).latest("arrival_time")
        start_date_object = latest_message.arrival_time - datetime.timedelta(hours=1)

        return Reading.objects.filter(
            station=pk,
            read_time__gte = start_date_object,
        )

class StationSensors(generics.ListAPIView):
    serializer_class = SensorSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return Sensor.objects.filter(stations__id=pk).order_by("stationsensorlink__station_order")

class StationMessages(generics.ListAPIView):
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return Message.objects.filter(station=pk).order_by("arrival_time")

class StationLatestMessage(generics.RetrieveAPIView):
    queryset = Message.objects.all()
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_object(self):
        pk = self.kwargs["pk"]
        return self.queryset.filter(station_id=pk).latest("arrival_time")

class StationSensorLinkList(generics.ListCreateAPIView):
    queryset = StationSensorLink.objects.all().order_by("created")
    serializer_class = StationSensorLinkSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class StationSensorLinkDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = StationSensorLink.objects.all()
    serializer_class = StationSensorLinkSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class ReadingList(generics.ListCreateAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        start_date = self.request.query_params.get("start", None)
        start_date_object = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=7) # Default to a week's worth
        if start_date != None:
            start_date_object = dateutil.parser.parse(start_date)

        end_date = self.request.query_params.get("end", None)
        end_date_object = datetime.datetime.now(pytz.utc)
        if end_date != None:
            end_date_object = dateutil.parser.parse(end_date)

        start_exclusive = self.request.query_params.get("start_exclusive", False)
        sensors = self.request.query_params.get("sensors", None)

        queryset = Reading.objects.filter(
            read_time__gte=start_date_object,
            read_time__lte=end_date_object
        )

        if start_exclusive == "true":
            queryset = Reading.objects.filter(
                read_time__gt=start_date_object,
                read_time__lte=end_date_object
            )

        if sensors is not None:
            sensor_list = sensors.split(",")
            queryset = queryset.filter(sensor__in=sensor_list)

        queryset = queryset.order_by("read_time")
        return queryset

class ReadingDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Reading.objects.all()
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class ReadingLatest(generics.ListAPIView):
    serializer_class = ReadingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        stations = Station.objects.all()
        station_ids = []
        for s in stations:
            station_ids.append(s.id)

        latest_message = Message.objects.all().latest("arrival_time")
        start_date_object = latest_message.arrival_time - datetime.timedelta(hours=1)

        return Reading.objects.filter(
            station__in=station_ids,
            read_time__gte=start_date_object,
        )

class MessageList(generics.ListCreateAPIView):
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def perform_create(self, serializer):
        print("--- CREATING MESSAGE ---")
        print(self.request.data)
        print("------------------------")
        serializer.save()

    def get_queryset(self):
        start_date = self.request.query_params.get("start", None)
        start_date_object = datetime.datetime.now(pytz.utc) - datetime.timedelta(days=7) # Default to a week's worth
        if start_date != None:
            start_date_object = dateutil.parser.parse(start_date)

        end_date = self.request.query_params.get("end", None)
        end_date_object = datetime.datetime.now(pytz.utc)
        if end_date != None:
            end_date_object = dateutil.parser.parse(end_date)

        start_exclusive = self.request.query_params.get("start_exclusive", False)

        queryset = Message.objects.filter(
            arrival_time__gte=start_date_object,
            arrival_time__lte=end_date_object
        )

        if start_exclusive == "true":
            queryset = Message.objects.filter(
                arrival_time__gt=start_date_object,
                arrival_time__lte=end_date_object
            )

        queryset = queryset.order_by("arrival_time")

        goes_id = self.request.query_params.get("goes_id", None)
        if goes_id is not None:
            queryset = Message.objects.filter(
                arrival_time__gte=start_date_object,
                arrival_time__lte=end_date_object,

                goes_id=goes_id
            ).order_by("arrival_time")

        return queryset

class MessageDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Message.objects.all()
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class MessageLatest(generics.ListAPIView):
    serializer_class = MessageSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_queryset(self):
        latest_message = Message.objects.all().latest("arrival_time")
        start_date_object = latest_message.arrival_time - datetime.timedelta(hours=1)

        return Message.objects.filter(
            arrival_time__gte=start_date_object
        )

class SettingList(generics.ListAPIView):
    queryset = Setting.objects.all()
    serializer_class = SettingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SettingDetail(generics.RetrieveUpdateAPIView):
    queryset = Setting.objects.all()
    serializer_class = SettingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class SettingDetailWithName(generics.RetrieveUpdateAPIView):
    queryset = Setting.objects.all()
    serializer_class = SettingSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get_object(self):
        name = self.kwargs["name"]
        return self.queryset.filter(name=name).first()

class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
<|endoftext|>


<commit_before>import hmac
import json
import urllib
import hashlib

from django.shortcuts import render
from django.http import Http404, HttpResponseRedirect, HttpResponse
from django.conf import settings
from django.core.mail import send_mail
from django.contrib.messages import success
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.vary import vary_on_headers
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage

from wagtail.wagtailcore.models import Page, Site
from wagtail.wagtailadmin.forms import SearchForm

from .models import HomePage, StaticPage
from category.models import Category
from .forms import ContactForm, DonateForm

from core.utils import get_translations_for_page

def home_page(request, slug="home-page"):
    home_page = HomePage.objects.get(slug=slug)
    translations = get_translations_for_page(home_page)
    return render(request, "core/home_page.html", {
        "page": home_page,
        "categories": Category.objects.all()[:9],
        "translations": translations
    })

def static_page(request, slug=None):
    try:
        page = Page.objects.get(slug=slug)
    except Page.DoesNotExist:
        raise Http404
    if page.specific_class == HomePage:
        return home_page(request, page.slug)
    translations = get_translations_for_page(page.specific)
    return render(request, "core/static_page.html", {
        "self": page.specific,
        "translations": translations
    })

def contribute(request, slug=None):
    page = StaticPage.objects.get(slug=slug)
    return render(request, "core/contribute.html", {
        "self": page
    })

def contact_us(request):
    if request.method == "POST":
        form = ContactForm(request.POST)
        if form.is_valid():
            form.save()
            success(request, _("Your query has successfully been sent"))
            form = ContactForm()
    else:
        form = ContactForm()
    return render(request, "core/contact_us.html", {
        "contact_form": form
    })

# TODO: Remove the below two functions when we migrate to wagtail 1.2

DEFAULT_PAGE_KEY = 'p'

def paginate(request, items, page_key=DEFAULT_PAGE_KEY, per_page=20):
    page = request.GET.get(page_key, 1)

    paginator = Paginator(items, per_page)
    try:
        page = paginator.page(page)
    except PageNotAnInteger:
        page = paginator.page(1)
    except EmptyPage:
        page = paginator.page(paginator.num_pages)

    return paginator, page

@vary_on_headers('X-Requested-With')
def search(request):
    pages = []
    q = None

    if 'q' in request.GET:
        form = SearchForm(request.GET)
        if form.is_valid():
            q = form.cleaned_data['q']

            pages = Page.objects.all().prefetch_related('content_type').search(q)
            paginator, pages = paginate(request, pages)
    else:
        form = SearchForm()

    if request.is_ajax():
        return render(request, "wagtailadmin/pages/search_results.html", {
            'pages': pages,
            'query_string': q,
	    'pagination_query_params': ('q=%s' % q) if q else ''
	})
    else:
	return render(request, "wagtailadmin/pages/search.html", {
	    'search_form': form,
	    'pages': pages,
	    'query_string': q,
	    'pagination_query_params': ('q=%s' % q) if q else ''
	})

def donate_form(request):
    form = DonateForm()
    errors = None
    try:
        site = Site.objects.get(hostname=request.get_host())
    except Site.DoesNotExist:
        site = Site.objects.all()[0]
    if request.method == "POST":
        form = DonateForm(request.POST)
        if form.is_valid():
            pg_url = settings.INSTAMOJO["DONATE_URL"]
            params = {
                "data_name": form.cleaned_data["name"],
                "data_email": form.cleaned_data["email"],
                "data_phone": form.cleaned_data["phone"],
                "data_Field_90444": form.cleaned_data["pan"],
            }
            pg_url += "?{0}".format(urllib.urlencode(params))
            request.session["donor_info"] = form.cleaned_data
            return HttpResponseRedirect(pg_url)
    return render(request, 'core/donate_form.html', {
        "form": form,
        "errors": errors,
        "site": site,
    })

def donate_success(request):
    try:
        site = Site.objects.get(hostname=request.get_host())
    except Site.DoesNotExist:
        site = Site.objects.all()[0]
    data = request.session.get("donor_info", {})
    if data:
        data = data.update(request.GET.copy())
        subject = _("Donation received")
        message = ""
        for (kk, vv) in data.items():
            message += kk + " : " + vv + "\r\n"
        send_mail(
            subject, message,
            settings.DEFAULT_FROM_EMAIL,
            settings.DONATE_EMAIL_RECIPIENTS
        )
    return render(request, 'core/donate_success.html', {
        "site": site,
    })

def lower_first_item(item):
    return item[0].lower()

@csrf_exempt
@require_POST
def donate_webhook(request):
    status = 400
    data = request.POST.copy()
    hook_mac = data.pop("mac", [None])[0]
    keys = sorted(data.items(), key=lower_first_item)
    vals = "|".join([ii[1] for ii in keys])
    calc_mac = hmac.new(
        settings.INSTAMOJO["SALT"],
        vals,
        hashlib.sha1).hexdigest()
    if hook_mac == calc_mac:
        if data["status"] == "Credit":
            status = 200
    return HttpResponse("", status=status)
<commit_msg>Fix the get parameter.<commit_after>import hmac
import json
import urllib
import hashlib

from django.shortcuts import render
from django.http import Http404, HttpResponseRedirect, HttpResponse
from django.conf import settings
from django.core.mail import send_mail
from django.contrib.messages import success
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.vary import vary_on_headers
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage

from wagtail.wagtailcore.models import Page, Site
from wagtail.wagtailadmin.forms import SearchForm

from .models import HomePage, StaticPage
from category.models import Category
from .forms import ContactForm, DonateForm

from core.utils import get_translations_for_page

def home_page(request, slug="home-page"):
    home_page = HomePage.objects.get(slug=slug)
    translations = get_translations_for_page(home_page)
    return render(request, "core/home_page.html", {
        "page": home_page,
        "categories": Category.objects.all()[:9],
        "translations": translations
    })

def static_page(request, slug=None):
    try:
        page = Page.objects.get(slug=slug)
    except Page.DoesNotExist:
        raise Http404
    if page.specific_class == HomePage:
        return home_page(request, page.slug)
    translations = get_translations_for_page(page.specific)
    return render(request, "core/static_page.html", {
        "self": page.specific,
        "translations": translations
    })

def contribute(request, slug=None):
    page = StaticPage.objects.get(slug=slug)
    return render(request, "core/contribute.html", {
        "self": page
    })

def contact_us(request):
    if request.method == "POST":
        form = ContactForm(request.POST)
        if form.is_valid():
            form.save()
            success(request, _("Your query has successfully been sent"))
            form = ContactForm()
    else:
        form = ContactForm()
    return render(request, "core/contact_us.html", {
        "contact_form": form
    })

# TODO: Remove the below two functions when we migrate to wagtail 1.2

DEFAULT_PAGE_KEY = 'p'

def paginate(request, items, page_key=DEFAULT_PAGE_KEY, per_page=20):
    page = request.GET.get(page_key, 1)

    paginator = Paginator(items, per_page)
    try:
        page = paginator.page(page)
    except PageNotAnInteger:
        page = paginator.page(1)
    except EmptyPage:
        page = paginator.page(paginator.num_pages)

    return paginator, page

@vary_on_headers('X-Requested-With')
def search(request):
    pages = []
    q = None

    if 'q' in request.GET:
        form = SearchForm(request.GET)
        if form.is_valid():
            q = form.cleaned_data['q']

            pages = Page.objects.all().prefetch_related('content_type').search(q)
            paginator, pages = paginate(request, pages)
    else:
        form = SearchForm()

    if request.is_ajax():
        return render(request, "wagtailadmin/pages/search_results.html", {
            'pages': pages,
            'query_string': q,
	    'pagination_query_params': ('q=%s' % q) if q else ''
	})
    else:
	return render(request, "wagtailadmin/pages/search.html", {
	    'search_form': form,
	    'pages': pages,
	    'query_string': q,
	    'pagination_query_params': ('q=%s' % q) if q else ''
	})

def donate_form(request):
    form = DonateForm()
    errors = None
    try:
        site = Site.objects.get(hostname=request.get_host())
    except Site.DoesNotExist:
        site = Site.objects.all()[0]
    if request.method == "POST":
        form = DonateForm(request.POST)
        if form.is_valid():
            pg_url = settings.INSTAMOJO["DONATE_URL"]
            params = {
                "data_name": form.cleaned_data["name"],
                "data_email": form.cleaned_data["email"],
                "data_phone": form.cleaned_data["phone"],
                "data_Field_90444": form.cleaned_data["pan"],
            }
            pg_url += "?{0}".format(urllib.urlencode(params))
            request.session["donor_info"] = form.cleaned_data
            return HttpResponseRedirect(pg_url)
    return render(request, 'core/donate_form.html', {
        "form": form,
        "errors": errors,
        "site": site,
    })

def donate_success(request):
    try:
        site = Site.objects.get(hostname=request.get_host())
    except Site.DoesNotExist:
        site = Site.objects.all()[0]
    data = request.session.get("donor_info", {})
    if data:
        data.update(request.GET.copy())
        subject = _("Donation received")
        message = ""
        for (kk, vv) in data.items():
            message += kk + " : " + vv + "\r\n"
        send_mail(
            subject, message,
            settings.DEFAULT_FROM_EMAIL,
            settings.DONATE_EMAIL_RECIPIENTS
        )
    return render(request, 'core/donate_success.html', {
        "site": site,
    })

def lower_first_item(item):
    return item[0].lower()

@csrf_exempt
@require_POST
def donate_webhook(request):
    status = 400
    data = request.POST.copy()
    hook_mac = data.pop("mac", [None])[0]
    keys = sorted(data.items(), key=lower_first_item)
    vals = "|".join([ii[1] for ii in keys])
    calc_mac = hmac.new(
        settings.INSTAMOJO["SALT"],
        vals,
        hashlib.sha1).hexdigest()
    if hook_mac == calc_mac:
        if data["status"] == "Credit":
            status = 200
    return HttpResponse("", status=status)
<|endoftext|>


<commit_before>
# the program we're testing:
from rair import air

# stdlib
import sys
import unittest
import tempfile
import argparse
from os.path import basename
from StringIO import StringIO
import contextlib

# installed libraries:
from sh import svnadmin
from sh import svn
from configobj import ConfigObj

#
from rair.subversion import MultipleMatchException

def overwrite(file_object, text):
        if file_object.closed:
            file_object = open(file_object.name, 'w')
        file_object.write(text)
        file_object.close()

def create_svn_repo():

    repo_dir = tempfile.mkdtemp()

    # create repo, with trunk and branches directories
    svnadmin.create(repo_dir)
    repo_url = '{}{}'.format('file://', repo_dir)
    trunk_url = '{}/trunk'.format(repo_url)
    branch_url = '{}/branches'.format(repo_url)
    svn.mkdir(trunk_url, m='trunk dir')
    svn.mkdir(branch_url, m='branches dir')

    return repo_url

def setup_svn():

    # create repo
    repo_url = create_svn_repo()
    trunk_url = '{}/trunk'.format(repo_url)
    branch_url = '{}/branches'.format(repo_url)

    # checkout trunk
    working_dir = tempfile.mkdtemp()
    svn.co(trunk_url, working_dir)

    # create a file
    repo_file = tempfile.NamedTemporaryFile(dir=working_dir, delete=False)
    overwrite(repo_file, '123\n')
    # commit it
    svn.add(repo_file.name, _cwd=working_dir)
    svn.commit(m='message', _cwd=working_dir)

    # create a branch
    new_branch_url = '{}/new-branch'.format(branch_url)
    svn.cp(trunk_url, new_branch_url, m='creating new branch')
    svn.switch(new_branch_url, _cwd=working_dir)
    # change the file and commit
    overwrite(repo_file, '456\n')
    svn.commit(m='message', _cwd=working_dir)

    # create another branch
    new_branch_url = '{}/foo-branch'.format(branch_url)
    svn.cp(trunk_url, new_branch_url, m='creating another new branch')

    return [repo_url, repo_file]

def create_conflict(repo_url, repo_file):

    trunk_url = '{}/trunk'.format(repo_url)

    # checkout trunk
    working_dir = tempfile.mkdtemp()
    svn.co(trunk_url, working_dir)

    # change the same file on trunk
    svn.co(trunk_url, working_dir)
    repo_file = working_dir + '/' + basename(repo_file.name)
    repo_file = open(repo_file, 'w')
    overwrite(repo_file, '789\n')
    svn.commit(m='creating conflict', _cwd=working_dir)

#    svn.up(_cwd=working_dir)
#    svn.merge(new_branch_url, _cwd=working_dir, accept='postpone')

def get_jira_pass():

    with open('./.pass', 'r') as pfile:
        return pfile.readline().rstrip()

class TestMakeBranch(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

        self.summary = "test bug"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)
        self.cmd = air.Commands(self.config)

        self.repo_url, self.repo_file = setup_svn()
        self.config['svn']['root_url'] = self.repo_url
        self.config['svn']['branch_url'] = self.repo_url + '/branches'
        self.config['svn']['trunk_url'] = self.repo_url + '/trunk'

    def test_make_branch(self):
        sys.argv = ['bogus', 'make_branch', self.bug]
        d = air.Dispatcher(self.config)
        out = StringIO()
        d.go(out=out)
        # now that branch should exist in the list of branches:
        branch_name = '{}_{}'.format(self.bug, self.summary.replace(' ', '_'))
        self.assertIn(branch_name, self.cmd.svn.get_branches())

    def tearDown(self):
        self.jira.transition_issue(self.bug, status='Resolve Issue')

class TestSvn(unittest.TestCase):

    def setUp(self):
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()
        self.repo_url, self.repo_file = setup_svn()
        self.arger = argparse.ArgumentParser()
        self.cmd = air.Commands(self.config)

        # use new values for SVN url:
        self.config['svn']['root_url'] = self.repo_url
        self.config['svn']['branch_url'] = self.repo_url + '/branches'
        self.config['svn']['trunk_url'] = self.repo_url + '/trunk'

    def test_get_unique_branch(self):
        expected = 'foo-branch'
        actual = self.cmd.svn.get_unique_branch('foo')
        self.assertEqual(expected, actual)

        with self.assertRaises(MultipleMatchException):
            actual = self.cmd.svn.get_unique_branch('branch')

    def test_get_branches(self):
        expected = [u'foo-branch', u'new-branch']
        actual = self.cmd.svn.get_branches()
        self.assertEqual(expected, actual)

    def test_refresh(self):
        out = StringIO()
        self.cmd.refresh(self.arger, ['new-branch'], out=out)
        output = out.getvalue().strip()
        self.assertRegexpMatches(output, 'Committed revision 7')

    def test_refresh_exception(self):
        create_conflict(self.repo_url, self.repo_file)
        with self.assertRaises(air.MergeException):
            self.cmd.refresh(self.arger, ['new-branch'])

class TestJira(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

    def test_create_bug(self):
        sys.argv = ['bogus', 'create_bug', "this is a test bug"]
        d = air.Dispatcher(self.config)
        out = StringIO()
        d.go(out=out)
        actual = out.getvalue().strip()
#TODO: close this bug via tearDown()
        self.assertRegexpMatches(actual, 'ticket created: MMSANDBOX-\d*')

class TestCloseJiraIssue(unittest.TestCase):

    def setUp(self):
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()
        self.summary = "test bug"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)

    def test_transition_issue(self):
        issue = self.jira.transition_issue(self.bug, status='Resolve Issue')
        expected = 'Resolved'
        self.assertEqual(expected, issue.fields.status.name)

class TestAddComment(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

        self.summary = "test bug for start of work"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)

    def tearDown(self):
        self.jira.transition_issue(self.bug, status='Resolve Issue')

    def test_add_comment(self):
        sys.argv = ['bogus', 'add_comment', '-t', self.bug, "this", "is", "a",
                "test", "comment"]
        d = air.Dispatcher(self.config)
        out = StringIO()
        d.go(out=out)
        output = out.getvalue().strip()
        # TODO: check ticket for comment

class TestStartWork(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

        self.summary = "test bug for start of work"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)
        self.cmd = air.Commands(self.config)

        self.repo_url, self.repo_file = setup_svn()
        self.config['svn']['root_url'] = self.repo_url
        self.config['svn']['branch_url'] = self.repo_url + '/branches'
        self.config['svn']['trunk_url'] = self.repo_url + '/trunk'

    def tearDown(self):
        self.jira.transition_issue(self.bug, status='Stop Progress')
        self.jira.transition_issue(self.bug, status='Resolve Issue')

    def test_start_work(self):
        sys.argv = ['bogus', 'start_work', self.bug]
        d = air.Dispatcher(self.config)
        out = StringIO()
        actual = d.go(out=out)

        # a branch should've been created:
        actual = self.cmd.svn.get_unique_branch('start')
        self.assertTrue(actual)

        # and the associated issue should now be "In Progress":
        expected = 'In Progress'
        actual = self.jira.get_issue(self.bug).fields.status.name
        self.assertEqual(expected, actual)

        #TODO: test that the SVN URL is added

@contextlib.contextmanager
def capture():
    oldout, olderr = sys.stdout, sys.stderr
    try:
        out = [StringIO(), StringIO()]
        sys.stdout, sys.stderr = out
        yield out
    finally:
        sys.stdout, sys.stderr = oldout, olderr
        out[0] = out[0].getvalue()
        out[1] = out[1].getvalue()

class TestMain(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

    def test_aliases(self):
        '''
        Testing that aliases specified in the the config file work.
        '''
        sys.argv = ['bogus', 'jirals']
        d = air.Dispatcher(self.config)
        out = StringIO()
        actual = d.go(out=out)
        output = out.getvalue().strip()
        self.assertEqual(0, actual)
        self.assertGreater(len(output), 0)

    def test_main(self):
        '''
        This is kinda lame and doesn't test much, but it makes sure there's
        test coverage for main().
        '''
        sys.argv = ['bogus', 'list_tickets']
        actual = air.main()
        expected = 0
        self.assertEqual(expected, actual)
<commit_msg>skipping test since I removed main()<commit_after>
# the program we're testing:
from rair import air

# stdlib
import sys
import unittest
import tempfile
import argparse
from os.path import basename
from StringIO import StringIO
import contextlib

# installed libraries:
from sh import svnadmin
from sh import svn
from configobj import ConfigObj

#
from rair.subversion import MultipleMatchException

def overwrite(file_object, text):
        if file_object.closed:
            file_object = open(file_object.name, 'w')
        file_object.write(text)
        file_object.close()

def create_svn_repo():

    repo_dir = tempfile.mkdtemp()

    # create repo, with trunk and branches directories
    svnadmin.create(repo_dir)
    repo_url = '{}{}'.format('file://', repo_dir)
    trunk_url = '{}/trunk'.format(repo_url)
    branch_url = '{}/branches'.format(repo_url)
    svn.mkdir(trunk_url, m='trunk dir')
    svn.mkdir(branch_url, m='branches dir')

    return repo_url

def setup_svn():

    # create repo
    repo_url = create_svn_repo()
    trunk_url = '{}/trunk'.format(repo_url)
    branch_url = '{}/branches'.format(repo_url)

    # checkout trunk
    working_dir = tempfile.mkdtemp()
    svn.co(trunk_url, working_dir)

    # create a file
    repo_file = tempfile.NamedTemporaryFile(dir=working_dir, delete=False)
    overwrite(repo_file, '123\n')
    # commit it
    svn.add(repo_file.name, _cwd=working_dir)
    svn.commit(m='message', _cwd=working_dir)

    # create a branch
    new_branch_url = '{}/new-branch'.format(branch_url)
    svn.cp(trunk_url, new_branch_url, m='creating new branch')
    svn.switch(new_branch_url, _cwd=working_dir)
    # change the file and commit
    overwrite(repo_file, '456\n')
    svn.commit(m='message', _cwd=working_dir)

    # create another branch
    new_branch_url = '{}/foo-branch'.format(branch_url)
    svn.cp(trunk_url, new_branch_url, m='creating another new branch')

    return [repo_url, repo_file]

def create_conflict(repo_url, repo_file):

    trunk_url = '{}/trunk'.format(repo_url)

    # checkout trunk
    working_dir = tempfile.mkdtemp()
    svn.co(trunk_url, working_dir)

    # change the same file on trunk
    svn.co(trunk_url, working_dir)
    repo_file = working_dir + '/' + basename(repo_file.name)
    repo_file = open(repo_file, 'w')
    overwrite(repo_file, '789\n')
    svn.commit(m='creating conflict', _cwd=working_dir)

#    svn.up(_cwd=working_dir)
#    svn.merge(new_branch_url, _cwd=working_dir, accept='postpone')

def get_jira_pass():

    with open('./.pass', 'r') as pfile:
        return pfile.readline().rstrip()

class TestMakeBranch(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

        self.summary = "test bug"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)
        self.cmd = air.Commands(self.config)

        self.repo_url, self.repo_file = setup_svn()
        self.config['svn']['root_url'] = self.repo_url
        self.config['svn']['branch_url'] = self.repo_url + '/branches'
        self.config['svn']['trunk_url'] = self.repo_url + '/trunk'

    def test_make_branch(self):
        sys.argv = ['bogus', 'make_branch', self.bug]
        d = air.Dispatcher(self.config)
        out = StringIO()
        d.go(out=out)
        # now that branch should exist in the list of branches:
        branch_name = '{}_{}'.format(self.bug, self.summary.replace(' ', '_'))
        self.assertIn(branch_name, self.cmd.svn.get_branches())

    def tearDown(self):
        self.jira.transition_issue(self.bug, status='Resolve Issue')

class TestSvn(unittest.TestCase):

    def setUp(self):
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()
        self.repo_url, self.repo_file = setup_svn()
        self.arger = argparse.ArgumentParser()
        self.cmd = air.Commands(self.config)

        # use new values for SVN url:
        self.config['svn']['root_url'] = self.repo_url
        self.config['svn']['branch_url'] = self.repo_url + '/branches'
        self.config['svn']['trunk_url'] = self.repo_url + '/trunk'

    def test_get_unique_branch(self):
        expected = 'foo-branch'
        actual = self.cmd.svn.get_unique_branch('foo')
        self.assertEqual(expected, actual)

        with self.assertRaises(MultipleMatchException):
            actual = self.cmd.svn.get_unique_branch('branch')

    def test_get_branches(self):
        expected = [u'foo-branch', u'new-branch']
        actual = self.cmd.svn.get_branches()
        self.assertEqual(expected, actual)

    def test_refresh(self):
        out = StringIO()
        self.cmd.refresh(self.arger, ['new-branch'], out=out)
        output = out.getvalue().strip()
        self.assertRegexpMatches(output, 'Committed revision 7')

    def test_refresh_exception(self):
        create_conflict(self.repo_url, self.repo_file)
        with self.assertRaises(air.MergeException):
            self.cmd.refresh(self.arger, ['new-branch'])

class TestJira(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

    def test_create_bug(self):
        sys.argv = ['bogus', 'create_bug', "this is a test bug"]
        d = air.Dispatcher(self.config)
        out = StringIO()
        d.go(out=out)
        actual = out.getvalue().strip()
#TODO: close this bug via tearDown()
        self.assertRegexpMatches(actual, 'ticket created: MMSANDBOX-\d*')

class TestCloseJiraIssue(unittest.TestCase):

    def setUp(self):
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()
        self.summary = "test bug"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)

    def test_transition_issue(self):
        issue = self.jira.transition_issue(self.bug, status='Resolve Issue')
        expected = 'Resolved'
        self.assertEqual(expected, issue.fields.status.name)

class TestAddComment(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

        self.summary = "test bug for start of work"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)

    def tearDown(self):
        self.jira.transition_issue(self.bug, status='Resolve Issue')

    def test_add_comment(self):
        sys.argv = ['bogus', 'add_comment', '-t', self.bug, "this", "is", "a",
                "test", "comment"]
        d = air.Dispatcher(self.config)
        out = StringIO()
        d.go(out=out)
        output = out.getvalue().strip()
        # TODO: check ticket for comment

class TestStartWork(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

        self.summary = "test bug for start of work"
        self.jira = air.Jira(self.config['jira'])
        self.bug = self.jira.create_issue(self.summary, self.summary)
        self.cmd = air.Commands(self.config)

        self.repo_url, self.repo_file = setup_svn()
        self.config['svn']['root_url'] = self.repo_url
        self.config['svn']['branch_url'] = self.repo_url + '/branches'
        self.config['svn']['trunk_url'] = self.repo_url + '/trunk'

    def tearDown(self):
        self.jira.transition_issue(self.bug, status='Stop Progress')
        self.jira.transition_issue(self.bug, status='Resolve Issue')

    def test_start_work(self):
        sys.argv = ['bogus', 'start_work', self.bug]
        d = air.Dispatcher(self.config)
        out = StringIO()
        actual = d.go(out=out)

        # a branch should've been created:
        actual = self.cmd.svn.get_unique_branch('start')
        self.assertTrue(actual)

        # and the associated issue should now be "In Progress":
        expected = 'In Progress'
        actual = self.jira.get_issue(self.bug).fields.status.name
        self.assertEqual(expected, actual)

        #TODO: test that the SVN URL is added

@contextlib.contextmanager
def capture():
    oldout, olderr = sys.stdout, sys.stderr
    try:
        out = [StringIO(), StringIO()]
        sys.stdout, sys.stderr = out
        yield out
    finally:
        sys.stdout, sys.stderr = oldout, olderr
        out[0] = out[0].getvalue()
        out[1] = out[1].getvalue()

class TestMain(unittest.TestCase):

    def setUp(self):
        # mock the configuration file:
        self.config = ConfigObj('./tests/config')
        self.config['jira']['password'] = get_jira_pass()

    def test_aliases(self):
        '''
        Testing that aliases specified in the the config file work.
        '''
        sys.argv = ['bogus', 'jirals']
        d = air.Dispatcher(self.config)
        out = StringIO()
        actual = d.go(out=out)
        output = out.getvalue().strip()
        self.assertEqual(0, actual)
        self.assertGreater(len(output), 0)

    @unittest.skip("removed main -- test air command instead")
    def test_main(self):
        '''
        This is kinda lame and doesn't test much, but it makes sure there's
        test coverage for main().
        '''
        sys.argv = ['bogus', 'list_tickets']
        actual = air.main()
        expected = 0
        self.assertEqual(expected, actual)
<|endoftext|>


<commit_before>import numpy as np
import math
import scipy.interpolate as si
import iso_obj as io

class iso_grid_tefflogg:
	'''A class which allows isochrones to be queried for many objects at the same time
		- set up to work in {Teff, logg, feh} space
		- Asumes a regular grid in '''

	def __init__(self, filename, metal_col=0, teff_col=1, logg_col=2, verbose=False):
		self.metal_col=metal_col
		self.teff_col=teff_col
		self.logg_col=logg_col

		self.verbose=verbose

		iso_array=np.loadtxt(filename)
		self.metal_dict={}

		self.metal_interp=None

		self.teff_step=0.
		self.teff_min=0.
		self.teff_gridlen=0.

		self.logg_step=0.
		self.logg_min=0.
		self.logg_gridlen=0.

		self.register(iso_array)

		self.iso_array2=io.iso_objs(iso_array[:,1], iso_array[:,2], iso_array[:,0], iso_array[:,3], iso_array[:,4],
						 iso_array[:,9], iso_array[:,10], iso_array[:,11], iso_array[:,5])

	def register(self, array):

		if self.verbose:
    		print "Registering"

		for i in range(array.shape[0]):

			if array[i,self.metal_col] not in self.metal_dict:
				self.metal_dict[ array[i,self.metal_col] ]=i
#				if self.metal_step==None and i!=0:
#					self.metal_step=i
        if self.verbose:
    		print "metal dict:", self.metal_dict

		self.metal_interp=si.interp1d(sorted(self.metal_dict.keys()), sorted(self.metal_dict.values()), kind='nearest', bounds_error=False)

		self.teff_min=array[0,self.teff_col]
		for i in range(sorted(self.metal_dict.values())[1]):
			if array[i,self.teff_col]!=self.teff_min:
				self.teff_step=array[i,self.teff_col]-self.teff_min
				self.teff_gridlen=i
				break
		if self.verbose:
    		print "Teff grid:", self.teff_min, self.teff_step, self.teff_gridlen

		self.logg_min=array[0,self.logg_col]
		for i in range(self.teff_gridlen):
			if array[i,self.logg_col]!=self.logg_min:
				self.logg_step=array[i,self.logg_col]-self.logg_min
				self.logg_gridlen=i
				break
		if self.verbose:
    		print "logg grid:", self.logg_min, self.logg_step, self.logg_gridlen

	def query(self, feh, teff, logg):

		rows=(self.metal_interp(feh)
			+ ( np.rint((teff-self.teff_min)/self.teff_step)*self.teff_gridlen )
			+ ( np.rint((logg-self.logg_min)/self.logg_step)*self.logg_gridlen )).astype(int)

#		r=self.iso_array[rows, 9]
#		i=self.iso_array[rows, 10]
#		ha=self.iso_array[rows, 11]

#		return r, i, ha
		return self.iso_array2.subset(rows)

<commit_msg>Correcting indentation on previous commit<commit_after>import numpy as np
import math
import scipy.interpolate as si
import iso_obj as io

class iso_grid_tefflogg:
	'''A class which allows isochrones to be queried for many objects at the same time
		- set up to work in {Teff, logg, feh} space
		- Asumes a regular grid in '''

	def __init__(self, filename, metal_col=0, teff_col=1, logg_col=2, verbose=False):
		self.metal_col=metal_col
		self.teff_col=teff_col
		self.logg_col=logg_col

		self.verbose=verbose

		iso_array=np.loadtxt(filename)
		self.metal_dict={}

		self.metal_interp=None

		self.teff_step=0.
		self.teff_min=0.
		self.teff_gridlen=0.

		self.logg_step=0.
		self.logg_min=0.
		self.logg_gridlen=0.

		self.register(iso_array)

		self.iso_array2=io.iso_objs(iso_array[:,1], iso_array[:,2], iso_array[:,0], iso_array[:,3], iso_array[:,4],
						 iso_array[:,9], iso_array[:,10], iso_array[:,11], iso_array[:,5])

	def register(self, array):

		if self.verbose:
			print "Registering"

		for i in range(array.shape[0]):

			if array[i,self.metal_col] not in self.metal_dict:
				self.metal_dict[ array[i,self.metal_col] ]=i
#				if self.metal_step==None and i!=0:
#					self.metal_step=i
		if self.verbose:
			print "metal dict:", self.metal_dict

		self.metal_interp=si.interp1d(sorted(self.metal_dict.keys()), sorted(self.metal_dict.values()), kind='nearest', bounds_error=False)

		self.teff_min=array[0,self.teff_col]
		for i in range(sorted(self.metal_dict.values())[1]):
			if array[i,self.teff_col]!=self.teff_min:
				self.teff_step=array[i,self.teff_col]-self.teff_min
				self.teff_gridlen=i
				break
		if self.verbose:
			print "Teff grid:", self.teff_min, self.teff_step, self.teff_gridlen

		self.logg_min=array[0,self.logg_col]
		for i in range(self.teff_gridlen):
			if array[i,self.logg_col]!=self.logg_min:
				self.logg_step=array[i,self.logg_col]-self.logg_min
				self.logg_gridlen=i
				break
		if self.verbose:
			print "logg grid:", self.logg_min, self.logg_step, self.logg_gridlen

	def query(self, feh, teff, logg):

		rows=(self.metal_interp(feh)
			+ ( np.rint((teff-self.teff_min)/self.teff_step)*self.teff_gridlen )
			+ ( np.rint((logg-self.logg_min)/self.logg_step)*self.logg_gridlen )).astype(int)

#		r=self.iso_array[rows, 9]
#		i=self.iso_array[rows, 10]
#		ha=self.iso_array[rows, 11]

#		return r, i, ha
		return self.iso_array2.subset(rows)

<|endoftext|>