<commit_before>#Numpy exploration with Python 2.7
from math import sqrt

#1. Numbers
title="Number title"
print title
x=3
b=3.4
#print type of number
print type(x)
print type(b)
#exponential
print x**b
#print multi arguments
print x,b,x+1,b+1,x**b

#2. Strings literral
title="String litteral"
hello='Hello'
world="World"
print hello+" "+world

#string format styling
formated='%s %s %d' %(hello,world,x)
print formated

#3. Lists
title="lists"
print title
nums=range(10)

print "Last element"
print nums[:-1]
print "Remove the last element"
nums.pop()
print nums

print "slice without including the first and last element"
print nums[1:-1]

#4. Loops
title="looping through containers"
print title
for num in nums:
    print num

print "Access list element using indexes in for loop"

for idx,val in enumerate(nums):
    print "%d %d" %(idx+1,val)

print "Creating list by comprehensions using the squares "

squares=[]
for x in nums:
    squares.append(x**2)
print squares

print "even square Same list created using comprehensions"
even_squares=[x**2 for x in nums]

#5. Dictionaries

title="Using dictionaries"
print title
d={"cat":"miaou","dog":"Barks","Lion":"Roars"}

print d["cat"]
print "dog" in d
print "Add new element in the dictionary using key :'fish':swims"
d["fish"]="swims"
print d
print d.get("Monkey","N/A")
print "Looping in dictionaries"

for animal in d:
    print d[animal]

print "Access dictionary with key values using iteritems()"

for animal,speech in d.iteritems():
    print "a %s %s."%(animal,speech)

print "Dictionary with comprehensions created from nums list"
print  nums
even_num_to_square={x:x**2 for  x in nums if x%2==0}
print even_num_to_square

#5. Sets
title="Working with sets"

print title
print "Square roots from nums list using comprehension"
sq_root={sqrt(x) for x in nums}
print sq_root

#6 tuples

title="Working with tuples"
print title
tup={(x,x*2): x for x in nums}
print tup
t=(12,24)
print type(t)
print tup[(5,10)]

#7. Functions
title="Working with functions"
def sign(x):
    if x>0:
       print "The number is positive"
    elif x<0:
       print "The number is negative"
    else:
       print "Zero was given as argument"

for x in [-1,0,1]:
    print sign(x)

print "Function with default arguments"

def hello(name,loud=False):
    if loud:
       print "Hello %s!" %name.upper()
    else:
       print "Hello %s!" %name

print hello("Bob")
print hello ("Bob",True)

#8. Classes
title="Working with classes"

class Greeter(object):

      #Constructor
      def __init__(self,name):
          self.name=name

      def greet(self,loud=False):
          if loud:
             print "Hello %s "% self.name.upper()
          else:
             print "Hello %s "% self.name

g=Greeter("Fred")
print g.greet(True)
print g.greet()

<commit_msg>Added slicing/indexing numpy arrays<commit_after>#Numpy exploration with Python 2.7
from math import sqrt
import numpy as np

#1. Numbers
title="Number title"
print title
x=3
b=3.4
#print type of number
print type(x)
print type(b)
#exponential
print x**b
#print multi arguments
print x,b,x+1,b+1,x**b

#2. Strings literral
title="String litteral"
hello='Hello'
world="World"
print hello+" "+world

#string format styling
formated='%s %s %d' %(hello,world,x)
print formated

#3. Lists
title="lists"
print title
nums=range(10)

print "Last element"
print nums[:-1]
print "Remove the last element"
nums.pop()
print nums

print "slice without including the first and last element"
print nums[1:-1]

#4. Loops
title="looping through containers"
print title
for num in nums:
    print num

print "Access list element using indexes in for loop"

for idx,val in enumerate(nums):
    print "%d %d" %(idx+1,val)

print "Creating list by comprehensions using the squares "

squares=[]
for x in nums:
    squares.append(x**2)
print squares

print "even square Same list created using comprehensions"
even_squares=[x**2 for x in nums]

#5. Dictionaries

title="Using dictionaries"
print title
d={"cat":"miaou","dog":"Barks","Lion":"Roars"}

print d["cat"]
print "dog" in d
print "Add new element in the dictionary using key :'fish':swims"
d["fish"]="swims"
print d
print d.get("Monkey","N/A")
print "Looping in dictionaries"

for animal in d:
    print d[animal]

print "Access dictionary with key values using iteritems()"

for animal,speech in d.iteritems():
    print "a %s %s."%(animal,speech)

print "Dictionary with comprehensions created from nums list"
print  nums
even_num_to_square={x:x**2 for  x in nums if x%2==0}
print even_num_to_square

#5. Sets
title="Working with sets"

print title
print "Square roots from nums list using comprehension"
sq_root={sqrt(x) for x in nums}
print sq_root

#6 tuples

title="Working with tuples"
print title
tup={(x,x*2): x for x in nums}
print tup
t=(12,24)
print type(t)
print tup[(5,10)]

#7. Functions
title="Working with functions"
def sign(x):
    if x>0:
       print "The number is positive"
    elif x<0:
       print "The number is negative"
    else:
       print "Zero was given as argument"

for x in [-1,0,1]:
    print sign(x)

print "Function with default arguments"

def hello(name,loud=False):
    if loud:
       print "Hello %s!" %name.upper()
    else:
       print "Hello %s!" %name

print hello("Bob")
print hello ("Bob",True)

#8. Classes
title="Working with classes"

class Greeter(object):

      #Constructor
      def __init__(self,name):
          self.name=name

      def greet(self,loud=False):
          if loud:
             print "Hello %s "% self.name.upper()
          else:
             print "Hello %s "% self.name

g=Greeter("Fred")
print g.greet(True)
print g.greet()

#9 Numpy datatypes

title="Working with Numpy datatypes"
print "Rank one array has a structure of a list"
a=np.array([1,2,3])
print a
print "Shape"
print a.shape
print "First element is the number of elements counting from the outmost []"
b=np.array([[2,3,4],[5,6,8]])
print b
print "Shape"
print b.shape
print "array is indexed from zero,b[0,2] is 4,b[1,0] is 5"
print b[0,2]
print b[1,0]

#10 initializing numpy arrays
title="Initializing numpy array"
print "Initializing with zeros(2,2)"
a=np.zeros((2,2))
print a

print "initializing with ones(4,4)"
print np.ones((4,4))

print "initialzing with a default value with full((2,2),3)"
print np.full((2,2),3)

print "Creating identity matrix of dimension 3x3"
print np.eye(3)

print "Initializing with random values of an array of 3 elements with 4 random values each"

print np.random.random((3,4))
#11 index array
title="Indexing array and slicing them"
print title
a=np.array([[1,2,3],[4,5,6],[7,8,9]])
print a
b=a[:2,1:3]
print "sliced b=a[:2,1:3]"
print b

print a[0,1]
print "Change the data of a slice of an array will eventually lead to the change of the original array b[0,0]=77 will change a[0,1]"
b[0,0]=77
print "b[0,0]"
print b[0,0]
print "a[0,1]"
print a[0,1]
print "Changed a"
print a
print "the second second row alone of a print row_1=a[1,:] which will be array of shape(4,) with rank 1"
row_1=a[1,:]
print row_1,row_1.shape
print "Print selection from row 1 until 2 but doesn't include 2 row,row_2=[1:2,:] which keeps the shape of (1 row,3 columns)"
row_2=a[1:2,:]
print row_2,row_2.shape
print "one column of shape (,3) but since is rank one it becomes same as row(3,)"
col_1=a[:,1]
print col_1,col_1.shape
print "columns from 1 to 2 indexes wihout including 2 of all rows with shape(3,1)"
col_2=a[:,1:2]
print col_2,col_2.shape

#12 indexing using integer
title="Indexing using integers"
c=np.array([[1,2],[3,4],[5,6]])
print "Indexing with integer,usually the first index list describe the first row coordinates of an element and the second describe the columns cooridnate of element to be selected c[[0,1,2],[0,1,0]]"
print c[[0,1,2],[0,1,0]]
print np.array([c[0,0],c[1,1],c[2,0]])
print "Indexing with integer one array of column indexes desired to change the rows"
d=np.array([1,0])
c[np.arange(2),d]+=10
print c

#13 indexing using boolean

title="Indexing using boolean values"
print title
bool_idx=(c>2)
print bool_idx

<|endoftext|>


<commit_before>#!/usr/bin/env python3

'''
Triaging tool to help understand where we need more timing coverage
Finds correlated variables to help make better test cases
'''

from timfuz import Benchmark, Ar_di2np, loadc_Ads_b, index_names, A_ds2np, simplify_rows
import numpy as np
import glob
import math
import json
import sympy
from collections import OrderedDict
from fractions import Fraction

def fracr(r):
    DELTA = 0.0001

    for i, x in enumerate(r):
        if type(x) is float:
            xi = int(x)
            assert abs(xi - x) < DELTA
            r[i] = xi
    return [Fraction(x) for x in r]

def fracm(m):
    return [fracr(r) for r in m]

class State(object):
    def __init__(self, Ads, drop_names=[]):
        self.Ads = Ads
        self.names = index_names(self.Ads)

        # known zero delay elements
        self.drop_names = set(drop_names)
        # active names in rows
        # includes sub symbols, excludes symbols that have been substituted out
        self.base_names = set(self.names)
        self.names = set(self.base_names)
        # List of variable substitutions
        # k => dict of v:n entries that it came from
        self.subs = {}
        self.verbose = True

    def print_stats(self):
        print("Stats")
        print("  Substitutions: %u" % len(self.subs))
        if self.subs:
            print("    Largest: %u" % max([len(x) for x in self.subs.values()]))
        print("  Rows: %u" % len(self.Ads))
        print("  Cols (in): %u" % (len(self.base_names) + len(self.drop_names)))
        print("  Cols (preprocessed): %u" % len(self.base_names))
        print("    Drop names: %u" % len(self.drop_names))
        print("  Cols (out): %u" % len(self.names))
        assert len(self.names) >= len(self.subs)

    @staticmethod
    def load(fn_ins):
        Ads, b = loadc_Ads_b(fn_ins, corner=None, ico=True)
        print('Simplifying')
        #Ads, b = simplify_rows(Ads, b)
        return State(Ads)

def write_state(state, fout):
    j = {
        'names': dict([(x, None) for x in state.names]),
        'drop_names': list(state.drop_names),
        'base_names': list(state.base_names),
        'subs': dict([(name, values) for name, values in state.subs.items()]),
        'pivots': state.pivots,
    }
    json.dump(j, fout, sort_keys=True, indent=4, separators=(',', ': '))

def Anp2matrix(Anp):
    '''
    Original idea was to make into a square matrix
    but this loses too much information
    so now this actually isn't doing anything and should probably be eliminated
    '''

    ncols = len(Anp[0])
    A_ub2 = [np.zeros(ncols) for _i in range(ncols)]
    dst_rowi = 0
    for rownp in Anp:
        A_ub2[dst_rowi] = np.add(A_ub2[dst_rowi], rownp)
        dst_rowi = (dst_rowi + 1) % ncols
    return A_ub2

def row_np2ds(rownp, names):
    ret = {}
    assert len(rownp) == len(names), (len(rownp), len(names))
    for namei, name in enumerate(names):
        v = rownp[namei]
        if v:
            ret[name] = v
    return ret

def row_sym2dsf(rowsym, names):
    '''Convert a sympy row into a dictionary of keys to (numerator, denominator) tuples'''
    from sympy import fraction

    ret = {}
    assert len(rowsym) == len(names), (len(rowsym), len(names))
    for namei, name in enumerate(names):
        v = rowsym[namei]
        if v:
            (num, den) = fraction(v)
            ret[name] = (int(num), int(den))
    return ret

def state_rref(state, verbose=False):
    print('Converting rows to integer keys')
    names, Anp = A_ds2np(state.Ads)

    print('np: %u rows x %u cols' % (len(Anp), len(Anp[0])))
    print('Combining rows into matrix')
    #mnp = Anp2matrix(Anp)
    mnp = Anp
    print('Matrix: %u rows x %u cols' % (len(mnp), len(mnp[0])))
    print('Converting np to sympy matrix')
    mfrac = fracm(mnp)
    msym = sympy.Matrix(mfrac)
    if verbose:
        print('names')
        print(names)
        print('Matrix')
        sympy.pprint(msym)
    print('Making rref')
    rref, pivots = msym.rref()

    if verbose:
        print('Pivots')
        sympy.pprint(pivots)
        print('rref')
        sympy.pprint(rref)

    state.pivots = {}

    def row_solved(rowsym, row_pivot):
        for ci, c in enumerate(rowsym):
            if ci == row_pivot:
                continue
            if c != 0:
                return False
        return True

    #rrefnp = np.array(rref).astype(np.float64)
    #print('Computing groups w/ rref %u row x %u col' % (len(rrefnp), len(rrefnp[0])))
    #print(rrefnp)
    # rows that have a single 1 are okay
    # anything else requires substitution (unless all 0)
    # pivots may be fewer than the rows
    # remaining rows should be 0s
    for row_i, row_pivot in enumerate(pivots):
        rowsym = rref.row(row_i)
        # yipee! nothign to report
        if row_solved(rowsym, row_pivot):
            continue

        # a grouping
        group_name = "GRP_%u" % row_i
        rowdsf = row_sym2dsf(rowsym, names)

        state.subs[group_name] = rowdsf
        # Add the new symbol
        state.names.add(group_name)
        # Remove substituted symbols
        # Note: symbols may appear multiple times
        state.names.difference_update(set(rowdsf.keys()))
        pivot_name = names[row_pivot]
        state.pivots[group_name] = pivot_name
        if verbose:
            print("%s (%s): %s" % (group_name, pivot_name, rowdsf))

    return state

def run(fout, fn_ins, verbose=0):
    print('Loading data')

    state = State.load(fn_ins)
    state_rref(state, verbose=verbose)
    state.print_stats()
    if fout:
        write_state(state, fout)

def main():
    import argparse

    parser = argparse.ArgumentParser(
        description=
        'Timing fuzzer'
    )

    parser.add_argument('--verbose', action='store_true', help='')
    parser.add_argument('--speed-json', default='build_speed/speed.json',
        help='Provides speed index to name translation')
    parser.add_argument('--out', help='Output sub.json substitution result')
    parser.add_argument(
        'fns_in',
        nargs='*',
        help='timing3.txt input files')
    args = parser.parse_args()
    bench = Benchmark()

    fout = None
    if args.out:
        fout = open(args.out, 'w')

    fns_in = args.fns_in
    if not fns_in:
        fns_in = glob.glob('specimen_*/timing3.csv')

    try:
        run(fout=fout,
            fn_ins=args.fns_in, verbose=args.verbose)
    finally:
        print('Exiting after %s' % bench)

if __name__ == '__main__':
    main()
<commit_msg>timfuz: normalize_last=False<commit_after>#!/usr/bin/env python3

'''
Triaging tool to help understand where we need more timing coverage
Finds correlated variables to help make better test cases
'''

from timfuz import Benchmark, Ar_di2np, loadc_Ads_b, index_names, A_ds2np, simplify_rows
import numpy as np
import glob
import math
import json
import sympy
from collections import OrderedDict
from fractions import Fraction

def fracr(r):
    DELTA = 0.0001

    for i, x in enumerate(r):
        if type(x) is float:
            xi = int(x)
            assert abs(xi - x) < DELTA
            r[i] = xi
    return [Fraction(x) for x in r]

def fracm(m):
    return [fracr(r) for r in m]

class State(object):
    def __init__(self, Ads, drop_names=[]):
        self.Ads = Ads
        self.names = index_names(self.Ads)

        # known zero delay elements
        self.drop_names = set(drop_names)
        # active names in rows
        # includes sub symbols, excludes symbols that have been substituted out
        self.base_names = set(self.names)
        self.names = set(self.base_names)
        # List of variable substitutions
        # k => dict of v:n entries that it came from
        self.subs = {}
        self.verbose = True

    def print_stats(self):
        print("Stats")
        print("  Substitutions: %u" % len(self.subs))
        if self.subs:
            print("    Largest: %u" % max([len(x) for x in self.subs.values()]))
        print("  Rows: %u" % len(self.Ads))
        print("  Cols (in): %u" % (len(self.base_names) + len(self.drop_names)))
        print("  Cols (preprocessed): %u" % len(self.base_names))
        print("    Drop names: %u" % len(self.drop_names))
        print("  Cols (out): %u" % len(self.names))
        print("  Solvable vars: %u" % len(self.names & self.base_names))
        assert len(self.names) >= len(self.subs)

    @staticmethod
    def load(fn_ins):
        Ads, b = loadc_Ads_b(fn_ins, corner=None, ico=True)
        print('Simplifying')
        #Ads, b = simplify_rows(Ads, b)
        return State(Ads)

def write_state(state, fout):
    j = {
        'names': dict([(x, None) for x in state.names]),
        'drop_names': list(state.drop_names),
        'base_names': list(state.base_names),
        'subs': dict([(name, values) for name, values in state.subs.items()]),
        'pivots': state.pivots,
    }
    json.dump(j, fout, sort_keys=True, indent=4, separators=(',', ': '))

def Anp2matrix(Anp):
    '''
    Original idea was to make into a square matrix
    but this loses too much information
    so now this actually isn't doing anything and should probably be eliminated
    '''

    ncols = len(Anp[0])
    A_ub2 = [np.zeros(ncols) for _i in range(ncols)]
    dst_rowi = 0
    for rownp in Anp:
        A_ub2[dst_rowi] = np.add(A_ub2[dst_rowi], rownp)
        dst_rowi = (dst_rowi + 1) % ncols
    return A_ub2

def row_np2ds(rownp, names):
    ret = {}
    assert len(rownp) == len(names), (len(rownp), len(names))
    for namei, name in enumerate(names):
        v = rownp[namei]
        if v:
            ret[name] = v
    return ret

def row_sym2dsf(rowsym, names):
    '''Convert a sympy row into a dictionary of keys to (numerator, denominator) tuples'''
    from sympy import fraction

    ret = {}
    assert len(rowsym) == len(names), (len(rowsym), len(names))
    for namei, name in enumerate(names):
        v = rowsym[namei]
        if v:
            (num, den) = fraction(v)
            ret[name] = (int(num), int(den))
    return ret

def state_rref(state, verbose=False):
    print('Converting rows to integer keys')
    names, Anp = A_ds2np(state.Ads)

    print('np: %u rows x %u cols' % (len(Anp), len(Anp[0])))
    print('Combining rows into matrix')
    #mnp = Anp2matrix(Anp)
    mnp = Anp
    print('Matrix: %u rows x %u cols' % (len(mnp), len(mnp[0])))
    print('Converting np to sympy matrix')
    mfrac = fracm(mnp)
    msym = sympy.Matrix(mfrac)
    # internal encoding has significnat performance implications
    #print(type(msym[3]))
    #assert type(msym[0]) is sympy.Integer

    if verbose:
        print('names')
        print(names)
        print('Matrix')
        sympy.pprint(msym)
    print('Making rref')
    rref, pivots = msym.rref(normalize_last=False)

    if verbose:
        print('Pivots')
        sympy.pprint(pivots)
        print('rref')
        sympy.pprint(rref)

    state.pivots = {}

    def row_solved(rowsym, row_pivot):
        for ci, c in enumerate(rowsym):
            if ci == row_pivot:
                continue
            if c != 0:
                return False
        return True

    #rrefnp = np.array(rref).astype(np.float64)
    #print('Computing groups w/ rref %u row x %u col' % (len(rrefnp), len(rrefnp[0])))
    #print(rrefnp)
    # rows that have a single 1 are okay
    # anything else requires substitution (unless all 0)
    # pivots may be fewer than the rows
    # remaining rows should be 0s
    for row_i, row_pivot in enumerate(pivots):
        rowsym = rref.row(row_i)
        # yipee! nothign to report
        if row_solved(rowsym, row_pivot):
            continue

        # a grouping
        group_name = "GRP_%u" % row_i
        rowdsf = row_sym2dsf(rowsym, names)

        state.subs[group_name] = rowdsf
        # Add the new symbol
        state.names.add(group_name)
        # Remove substituted symbols
        # Note: symbols may appear multiple times
        state.names.difference_update(set(rowdsf.keys()))
        pivot_name = names[row_pivot]
        state.pivots[group_name] = pivot_name
        if verbose:
            print("%s (%s): %s" % (group_name, pivot_name, rowdsf))

    return state

def run(fout, fn_ins, verbose=0):
    print('Loading data')

    state = State.load(fn_ins)
    state_rref(state, verbose=verbose)
    state.print_stats()
    if fout:
        write_state(state, fout)

def main():
    import argparse

    parser = argparse.ArgumentParser(
        description=
        'Timing fuzzer'
    )

    parser.add_argument('--verbose', action='store_true', help='')
    parser.add_argument('--speed-json', default='build_speed/speed.json',
        help='Provides speed index to name translation')
    parser.add_argument('--out', help='Output sub.json substitution result')
    parser.add_argument(
        'fns_in',
        nargs='*',
        help='timing3.txt input files')
    args = parser.parse_args()
    bench = Benchmark()

    fout = None
    if args.out:
        fout = open(args.out, 'w')

    fns_in = args.fns_in
    if not fns_in:
        fns_in = glob.glob('specimen_*/timing3.csv')

    try:
        run(fout=fout,
            fn_ins=args.fns_in, verbose=args.verbose)
    finally:
        print('Exiting after %s' % bench)

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


<commit_before>from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.utils import simplejson
from django.utils.translation import ugettext_lazy as _

from oauthost.config import *
from oauthost.models import Scope

def filter_input_params(input_params):
    """Filters request parameters and returns filtered dictionary.

    SPEC: Parameters sent without a value MUST be treated as if they were omitted from the request.

    """
    params_filtered = {}
    for key, value in input_params.items():
        if value:
            params_filtered[key] = value
    return params_filtered

def get_remote_ip(request):
    """Resolves and returns client IP."""

    forwarded = request.META.get('HTTP_X_FORWARDED_FOR')
    ip = request.META.get('REMOTE_ADDR')
    if forwarded is not None:
        ip = forwarded.split(',')[-1].strip()
    return ip

def resolve_scopes_to_apply(scopes_requested, client):
    """Gets space delimited list of scopes from client request,
    and returns a list of scope objects, corrected according
    to auth server settings.

    """

    if scopes_requested is not None:
        scopes_requested = scopes_requested.split(' ')
    else:
        scopes_requested = []

    scopes_available = []
    scopes_to_apply = []

    # Scopes available to the client.
    for scope in client.scopes.all():
        scopes_available.append(scope)

    # Scopes selection is unrestricted by the client, and we make all scopes available.
    if not scopes_available:
        scopes = Scope.objects.all()
        for scope in scopes:
            scopes_available.append(scope)

    # SPEC: If the issued access token scope is different from the one
    # requested by the client, the authorization server SHOULD include
    # the "scope" response parameter to inform the client of the actual
    # scope granted.

    # No scopes requested, and we are giving an access to all scopes available.
    # TODO Needs revision.
    if not scopes_requested:
        scopes_to_apply = scopes_available

    # Unavailable scopes are requested.
    scopes_available_set = set(s.identifier for s in scopes_available)
    if set(scopes_requested).difference(scopes_available_set):
        scopes_to_apply_ids = scopes_available_set.intersection(scopes_requested)
        if not scopes_to_apply_ids:
            # Only unavailable scopes are requested.
            # TODO Needs revision.
            scopes_to_apply = []
        else:
            scopes_to_apply = []
            for scope in scopes_available:
                if scope.identifier in scopes_to_apply_ids:
                    scopes_to_apply.append(scope)

    return scopes_to_apply

def ep_auth_response_error_page(request, error_text, http_status=400):
    """For authorization endpoint. Renders a page with error description."""
    data_dict = {'oauthost_title': _('Error'), 'oauthost_error_text': error_text}
    return render(request, OAUTHOST_TEMPLATE_AUTHORIZE_ERROR, data_dict, status=http_status)

def ep_auth_build_redirect_uri(redirect_base, params, use_uri_fragment):
    """For authorization endpoint. Builds up redirection URL."""
    if use_uri_fragment:
        redirect_base = '%s#' % redirect_base
    else:
        # SPEC: query component MUST be retained when adding additional query parameters.
        if '?' not in redirect_base:
            redirect_base = '%s?' % redirect_base
    return '%s%s' % (redirect_base, '&'.join(['%s=%s' % (key, value) for key, value in params.items()]))

def ep_auth_response(redirect_base, params, use_uri_fragment):
    """For authorization endpoint. Issues response."""
    return HttpResponseRedirect(ep_auth_build_redirect_uri(redirect_base, params, use_uri_fragment))

def ep_auth_response_error(redirect_to, uri_fragment, error_type, description):
    """For authorization endpoint. Issues error response."""
    return ep_auth_response(redirect_to, {'error': error_type, 'error_description': description}, uri_fragment)

def ep_auth_clear_session_data(request):
    """For authorization endpoint. Clears oauth data from session."""
    del request.session['oauth_client_id']
    del request.session['oauth_response_type']
    del request.session['oauth_redirect_uri']
    del request.session['oauth_scopes_ids']
    del request.session['oauth_state']

def ep_token_response(params, status=200, additional_headers={}):
    """For token endpoint. Issues JSON response."""
    response = HttpResponse(content_type='application/json;charset=UTF-8',
        content=simplejson.dumps(params), status=status)
    response['Cache-Control'] = 'no-store'
    response['Pragma'] = 'no-cache'
    for key, value in additional_headers.items():
        response[key] = value
    return response

def ep_token_reponse_error(error_type, description, status=400, additional_headers={}):
    """For token endpoint. Issues JSON error response."""
    return ep_token_response({'error': error_type, 'error_description': description}, status, additional_headers)

def forbidden_error_response(request):
    """Renders `forbidden` page."""
    return render(request, OAUTHOST_TEMPLATE_FORBIDDEN, {'oauthost_title': _('Access Denied')}, status=403)

def auth_handler_response(request, scope=None):
    """Checks for token data in request using various
    methods depending on token types defined in REGISTRY_TOKEN_TYPE.

    ``scope`` - scope identifier string to check token has access to the scope.

    """
    token_auth_classes = [item[2] for item in REGISTRY_TOKEN_TYPE]

    for auth_class in token_auth_classes:
        handler = auth_class(request, scope)
        response = handler.response()
        if response is not None:
            return response

    return None

class PistonAuthHelper(object):
    """Authentication class for Piston resources.

    To be used in a usual piston-auth-way::

        from piston.resource import Resource
        from oauthost.utils import PistonAuthHelper

        my_resource_view = Resource(MyResourceHandler, authentication=PistonAuthHelper('my_resource:my_scope'))

    """

    def __init__(self, target_scope):
        self.target_scope = target_scope

    def is_authenticated(self, request):
        self.auth_response = auth_handler_response(request, scope=self.target_scope)
        return not self.auth_response

    def challenge(self):
        return self.auth_response
<commit_msg>Fixed wrong response check in PistonAuthHelper.is_authenticated().<commit_after>from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.utils import simplejson
from django.utils.translation import ugettext_lazy as _

from oauthost.config import *
from oauthost.models import Scope

def filter_input_params(input_params):
    """Filters request parameters and returns filtered dictionary.

    SPEC: Parameters sent without a value MUST be treated as if they were omitted from the request.

    """
    params_filtered = {}
    for key, value in input_params.items():
        if value:
            params_filtered[key] = value
    return params_filtered

def get_remote_ip(request):
    """Resolves and returns client IP."""

    forwarded = request.META.get('HTTP_X_FORWARDED_FOR')
    ip = request.META.get('REMOTE_ADDR')
    if forwarded is not None:
        ip = forwarded.split(',')[-1].strip()
    return ip

def resolve_scopes_to_apply(scopes_requested, client):
    """Gets space delimited list of scopes from client request,
    and returns a list of scope objects, corrected according
    to auth server settings.

    """

    if scopes_requested is not None:
        scopes_requested = scopes_requested.split(' ')
    else:
        scopes_requested = []

    scopes_available = []
    scopes_to_apply = []

    # Scopes available to the client.
    for scope in client.scopes.all():
        scopes_available.append(scope)

    # Scopes selection is unrestricted by the client, and we make all scopes available.
    if not scopes_available:
        scopes = Scope.objects.all()
        for scope in scopes:
            scopes_available.append(scope)

    # SPEC: If the issued access token scope is different from the one
    # requested by the client, the authorization server SHOULD include
    # the "scope" response parameter to inform the client of the actual
    # scope granted.

    # No scopes requested, and we are giving an access to all scopes available.
    # TODO Needs revision.
    if not scopes_requested:
        scopes_to_apply = scopes_available

    # Unavailable scopes are requested.
    scopes_available_set = set(s.identifier for s in scopes_available)
    if set(scopes_requested).difference(scopes_available_set):
        scopes_to_apply_ids = scopes_available_set.intersection(scopes_requested)
        if not scopes_to_apply_ids:
            # Only unavailable scopes are requested.
            # TODO Needs revision.
            scopes_to_apply = []
        else:
            scopes_to_apply = []
            for scope in scopes_available:
                if scope.identifier in scopes_to_apply_ids:
                    scopes_to_apply.append(scope)

    return scopes_to_apply

def ep_auth_response_error_page(request, error_text, http_status=400):
    """For authorization endpoint. Renders a page with error description."""
    data_dict = {'oauthost_title': _('Error'), 'oauthost_error_text': error_text}
    return render(request, OAUTHOST_TEMPLATE_AUTHORIZE_ERROR, data_dict, status=http_status)

def ep_auth_build_redirect_uri(redirect_base, params, use_uri_fragment):
    """For authorization endpoint. Builds up redirection URL."""
    if use_uri_fragment:
        redirect_base = '%s#' % redirect_base
    else:
        # SPEC: query component MUST be retained when adding additional query parameters.
        if '?' not in redirect_base:
            redirect_base = '%s?' % redirect_base
    return '%s%s' % (redirect_base, '&'.join(['%s=%s' % (key, value) for key, value in params.items()]))

def ep_auth_response(redirect_base, params, use_uri_fragment):
    """For authorization endpoint. Issues response."""
    return HttpResponseRedirect(ep_auth_build_redirect_uri(redirect_base, params, use_uri_fragment))

def ep_auth_response_error(redirect_to, uri_fragment, error_type, description):
    """For authorization endpoint. Issues error response."""
    return ep_auth_response(redirect_to, {'error': error_type, 'error_description': description}, uri_fragment)

def ep_auth_clear_session_data(request):
    """For authorization endpoint. Clears oauth data from session."""
    del request.session['oauth_client_id']
    del request.session['oauth_response_type']
    del request.session['oauth_redirect_uri']
    del request.session['oauth_scopes_ids']
    del request.session['oauth_state']

def ep_token_response(params, status=200, additional_headers={}):
    """For token endpoint. Issues JSON response."""
    response = HttpResponse(content_type='application/json;charset=UTF-8',
        content=simplejson.dumps(params), status=status)
    response['Cache-Control'] = 'no-store'
    response['Pragma'] = 'no-cache'
    for key, value in additional_headers.items():
        response[key] = value
    return response

def ep_token_reponse_error(error_type, description, status=400, additional_headers={}):
    """For token endpoint. Issues JSON error response."""
    return ep_token_response({'error': error_type, 'error_description': description}, status, additional_headers)

def forbidden_error_response(request):
    """Renders `forbidden` page."""
    return render(request, OAUTHOST_TEMPLATE_FORBIDDEN, {'oauthost_title': _('Access Denied')}, status=403)

def auth_handler_response(request, scope=None):
    """Checks for token data in request using various
    methods depending on token types defined in REGISTRY_TOKEN_TYPE.

    ``scope`` - scope identifier string to check token has access to the scope.

    """
    token_auth_classes = [item[2] for item in REGISTRY_TOKEN_TYPE]

    for auth_class in token_auth_classes:
        handler = auth_class(request, scope)
        response = handler.response()
        if response is not None:
            return response

    return None

class PistonAuthHelper(object):
    """Authentication class for Piston resources.

    To be used in a usual piston-auth-way::

        from piston.resource import Resource
        from oauthost.utils import PistonAuthHelper

        my_resource_view = Resource(MyResourceHandler, authentication=PistonAuthHelper('my_resource:my_scope'))

    """

    def __init__(self, target_scope):
        self.target_scope = target_scope

    def is_authenticated(self, request):
        self.auth_response = auth_handler_response(request, scope=self.target_scope)
        return self.auth_response is None

    def challenge(self):
        return self.auth_response
<|endoftext|>


<commit_before>#!/usr/bin/python

import json

from sys import argv
from io import StringIO

def tokenize(template):
    """Tokenize a mustache template

    Tokenizes a mustache template in a generator fashion,
    using file-like objects. It also accepts a string containing
    the template.

    Arguments:
    template -- a file-like object, or a string of a mustache template

    Returns:
    A generator of mustache tags in the form of a tuple
    -- (tag_type, tag_key)

    Where tag_type is one of:
     * literal
     * section
     * inverted section
     * end
     * partial
     * no escape
    And tag_key is either the key or in the case of a literal tag,
    the literal itself.
    """

    class UnclosedSection(Exception):
        """Raised when you have unbalanced section tags"""
        pass

    def get(amount=1):
        """Reads amount of data from the template"""

        data = template.read(amount)

        # set the finish flag if there is not enough data left
        if len(data) != amount:
            template.is_finished = True

        return data

    def grab_literal(until=None):
        """Grabs data from template until it hits the until"""

        until = until or l_del
        literal = get()
        while not template.is_finished:
            if literal.endswith(until):
                return literal[:-len(until)]

            literal += get()

        return literal

    tag_types = {
        '!': 'comment',
        '#': 'section',
        '^': 'inverted section',
        '/': 'end',
        '>': 'partial',
        '=': 'set delimiter?',
        '{': 'no escape?',
        '&': 'no escape'
    }

    try:
        template = StringIO(template)
    except TypeError:
        pass

    template.is_finished = False
    is_standalone = True
    open_sections = []
    l_del = '{{'
    r_del = '}}'
    while not template.is_finished:
        literal = grab_literal()

        # If the template is completed
        if template.is_finished:
            # Then yield the literal and leave
            yield ('literal', literal)
            break

        # Checking if the next tag could be a standalone
        # If there is a newline, or the previous tag was a standalone
        if literal.find('\n') != -1 or is_standalone:
            padding = literal.split('\n')[-1]

            # If all the characters since the last newline are spaces
            if padding.isspace() or padding == '':
                # Then the next tag could be a standalone
                is_standalone = True
            else:
                # Otherwise it can't be
                is_standalone = False

        # Start work on the tag

        # Get the type character of the tag
        tag_key = get(1)

        # Find the type meaning of the first character
        tag_type = tag_types.get(tag_key, 'variable')

        # If the type is not a variable
        if tag_type != 'variable':
            # Then that first character is not needed
            tag_key = ''

        # Grab and strip the whitespace off the key
        tag_key += grab_literal(r_del)
        tag_key = tag_key.strip()

        # If we might be a no html escape tag
        if tag_type == 'no escape?':
            # TODO: this is buggy

            # If we have a third curly brace
            if get(1) == '}':
                # Then we are a no html escape tag
                tag_type = 'no escape'
            else:
                # Otherwise we need to give that character back
                template.seek(template.tell() - 1)

        # If we might be a set delimiter tag
        elif tag_type == 'set delimiter?':
            # If our key ends with an equal sign
            if tag_key.endswith('='):
                # Then get and set the delimiters
                dels = tag_key[:-1].strip().split(' ')
                l_del, r_del = dels[0], dels[-1]

        # If we are a section tag
        elif tag_type in ['section', 'inverted section']:
            # Then open a new section
            open_sections.append(tag_key)

        # If we are an end tag
        elif tag_type == 'end':
            # Then check to see if the last opened section
            # is the same as us
            last_section = open_sections.pop()
            if tag_key != last_section:
                # Otherwise we need to complain
                raise UnclosedSection()

        # If we might be a standalone and we aren't a tag that can't
        # be a standalone
        if is_standalone and tag_type not in ['variable', 'no escape']:
            until = grab_literal('\n')

            # If the stuff to the right of us are spaces
            if until.isspace() or until == '':
                # Then we're a standalone
                is_standalone = True

                # And if we aren't a partial
                if tag_type != 'partial':
                    # Then we need to remove the spaces from the left
                    literal = literal.rstrip(' ')

            else:
                # TODO: this is messy

                # Otherwise we aren't a standalone
                is_standalone = False

                # Now we need to backtrack

                # If the template is finished
                if template.is_finished:
                    # Tell it that it has more work
                    template.is_finished = False

                # If we're a set delimiter tag
                if tag_type == 'set delimiter?':
                    # Then step back the length of the stuff we grabbed
                    template.seek(template.tell() - len(until))
                else:
                    # Otherwise step back the length plus one
                    template.seek(template.tell() - (len(until) + 1))

                # I don't know why there's a difference...

        # If we're a tag can't be a standalone
        elif tag_type in ['variable', 'no escape']:
            # Then we aren't a standalone
            is_standalone = False

        # Start yielding

        # Ignore literals that are empty
        if literal != '':
            yield ('literal', literal)

        # Ignore comments and set delimiters
        if tag_type not in ['comment', 'set delimiter?']:
            yield (tag_type, tag_key)

    # If there are any open sections when we're done
    if open_sections:
        # Then we need to complain
        raise UnclosedSection()

def render(template='', data={}, partials_path='.', partials_ext='mustache',
           partials_dict={}, padding=0):
    """Render a mustache template.

    Renders a mustache template with a data scope and partial capability.
    Given the file structure...
    .
    |- main.py
    |- main.ms
    |- partials
     |- part.ms

    then main.py would make the following call:

    render(open('main.ms', 'r'), {...}, 'partials', 'ms')

    Arguments:
    template      -- A file-like object or a string containing the template
    data          -- A python dictionary with your data scope
    partials_path -- The path to where your partials are stored
                     (defaults to '.')
    partials_ext  -- The extension that you want the parser to look for
                     (defaults to 'mustache')
    partials_dict -- A python dictionary which will be search for partials
                     before the filesystem is. {'include': 'foo'} is the same
                     as a file called include.mustache
                     (defaults to {})
    padding       -- This is for padding partials, and shouldn't be used
                     (but can be if you really want to)

    Returns:
    A string containing the rendered template.
    """

    def html_escape(string):
        """HTML escape all of these " & < >"""

        html_codes = {
            '"': '"',
            '&': '&',
            '<': '<',
            '>': '>',
        }

        def escape_char(char):
            return html_codes.get(char, char)

        try:
            return ''.join(map(escape_char, string))
        except TypeError:
            return ''

    def get_key(key):
        """Get a key from the current scope"""

        # If the key is a dot
        if key == '.':
            # Then just return the current scope
            return scopes[0]

        # Loop through the scopes
        for scope in scopes:
            try:
                # For every dot seperated key
                for key in key.split('.'):
                    # Move into the scope
                    scope = scope[key]
                # Return the last scope we got
                return scope
            except (TypeError, KeyError):
                # We couldn't find the key in the current scope
                # We'll try again on the next pass
                pass

        # We couldn't find the key in any of the scopes
        return ''

    def get_partial(name):
        """Load a partial"""
        try:
            # Maybe the partial is in the dictionary
            return partials_dict[name]
        except KeyError:
            # Nope...
            try:
                # Maybe it's in the file system
                path = partials_path + '/' + name + '.' + partials_ext
                return open(path, 'r')
            except IOError:
                # Alright I give up on you
                return StringIO(None)

    # If the template is a list
    if type(template) is list:
        # Then we don't need to tokenize it
        tokens = template
    else:
        # Otherwise make a generator
        tokens = tokenize(template)

    output = ''

    # If the data is a list
    if type(data) is list:
        # Then it's probably a list of scopes
        scopes = data
    else:
        # Otherwise it's a single scope
        scopes = [data]

    # Run through the tokens
    for tag, key in tokens:
        # Set the current scope
        try:
            current_scope = scopes[0]
        except IndexError:
            current_scope = None

        # If we're an end tag
        if tag == 'end':
            # Pop out of the latest scope
            scopes = scopes[1:]

        # If the current scope is falsy and not the only scope
        elif not current_scope and len(scopes) != 1:
            # If we're a section tag
            if tag == 'section':
                # Set it as the most recent scope
                scopes.insert(0, scope)

            # If we're an inverted section tag
            elif tag == 'inverted section':
                # Set the flipped scope as the most recent scope
                scopes.insert(0, not scope)

        # If we're a literal tag
        elif tag == 'literal':
            # Add padding to the key and add it to the output
            output += key.replace('\n', '\n' + (' ' * padding))

        # If we're a variable tag
        elif tag == 'variable':
            # Add the html escaped key to the output
            output += html_escape(str(get_key(key)))

        # If we're a no html escape tag
        elif tag == 'no escape':
            # Just lookup the key and add it
            output += str(get_key(key))

        # If we're a section tag
        elif tag == 'section':
            # Get the sections scope
            scope = get_key(key)

            # If the scope is a list
            if type(scope) is list:
                # Then we need to do some looping

                # Gather up all the tags inside the section
                tags = []
                for tag in tokens:
                    if tag == ('end', key):
                        break
                    tags.append(tag)

                # For every item in the scope
                for thing in scope:
                    # Append it as the most recent scope and render
                    new_scope = [thing] + scopes
                    output += render(tags, new_scope, partials_path,
                                     partials_ext, partials_dict)

            else:
                # Otherwise we're just a scope section
                scopes.insert(0, scope)

        # If we're an inverted section
        elif tag == 'inverted section':
            # Add the flipped scope to the scopes
            scope = get_key(key)
            scopes.insert(0, not scope)

        # If we're a partial
        elif tag == 'partial':
            # Load the partial
            partial = get_partial(key)

            # Find how much to pad the partial
            left = output.split('\n')[-1]
            part_padding = padding
            if left.isspace():
                part_padding += left.count(' ')

            # Render the partial
            part_out = render(partial, scopes, partials_path,
                              partials_ext, partials_dict, part_padding)

            # If the partial was indented
            if left.isspace():
                # then remove the spaces from the end
                part_out = part_out.rstrip(' ')

            # Add the partials output to the ouput
            output += part_out

        else:
            # This should never get hit
            print('UNKNOWN TAG:', tag)

    return output

if __name__ == '__main__':
    args = {
        'template': open(argv[2], 'r'),
        'data': json.load(open(argv[1], 'r')),
    }

    output = render(**args)
    print(output)
<commit_msg>Change file-like objects to strings.<commit_after>#!/usr/bin/python

import json

import mmap
from sys import argv

def tokenize(template):
    """Tokenize a mustache template

    Tokenizes a mustache template in a generator fashion,
    using file-like objects. It also accepts a string containing
    the template.

    Arguments:
    template -- a file-like object, or a string of a mustache template

    Returns:
    A generator of mustache tags in the form of a tuple
    -- (tag_type, tag_key)

    Where tag_type is one of:
     * literal
     * section
     * inverted section
     * end
     * partial
     * no escape
    And tag_key is either the key or in the case of a literal tag,
    the literal itself.
    """

    class UnclosedSection(Exception):
        """Raised when you have unbalanced section tags"""
        pass

    def get(amount=1):
        """Reads amount of data from the template"""

        data = template.read(amount)

        # set the finish flag if there is not enough data left
        if len(data) != amount:
            template.is_finished = True

        return data

    def grab_literal(until=None):
        """Grabs data from template until it hits the until"""

        until = until or l_del
        literal = get()
        while not template.is_finished:
            if literal.endswith(until):
                return literal[:-len(until)]

            literal += get()

        return literal

    tag_types = {
        '!': 'comment',
        '#': 'section',
        '^': 'inverted section',
        '/': 'end',
        '>': 'partial',
        '=': 'set delimiter?',
        '{': 'no escape?',
        '&': 'no escape'
    }

    try:
        mmap.mmap(template.fileno())
    except AttributeError:
        pass

    template.is_finished = False
    is_standalone = True
    open_sections = []
    l_del = '{{'
    r_del = '}}'
    while not template.is_finished:
        literal = grab_literal()

        # If the template is completed
        if template.is_finished:
            # Then yield the literal and leave
            yield ('literal', literal)
            break

        # Checking if the next tag could be a standalone
        # If there is a newline, or the previous tag was a standalone
        if literal.find('\n') != -1 or is_standalone:
            padding = literal.split('\n')[-1]

            # If all the characters since the last newline are spaces
            if padding.isspace() or padding == '':
                # Then the next tag could be a standalone
                is_standalone = True
            else:
                # Otherwise it can't be
                is_standalone = False

        # Start work on the tag

        # Get the type character of the tag
        tag_key = get(1)

        # Find the type meaning of the first character
        tag_type = tag_types.get(tag_key, 'variable')

        # If the type is not a variable
        if tag_type != 'variable':
            # Then that first character is not needed
            tag_key = ''

        # Grab and strip the whitespace off the key
        tag_key += grab_literal(r_del)
        tag_key = tag_key.strip()

        # If we might be a no html escape tag
        if tag_type == 'no escape?':
            # TODO: this is buggy

            # If we have a third curly brace
            if get(1) == '}':
                # Then we are a no html escape tag
                tag_type = 'no escape'
            else:
                # Otherwise we need to give that character back
                template.seek(template.tell() - 1)

        # If we might be a set delimiter tag
        elif tag_type == 'set delimiter?':
            # If our key ends with an equal sign
            if tag_key.endswith('='):
                # Then get and set the delimiters
                dels = tag_key[:-1].strip().split(' ')
                l_del, r_del = dels[0], dels[-1]

        # If we are a section tag
        elif tag_type in ['section', 'inverted section']:
            # Then open a new section
            open_sections.append(tag_key)

        # If we are an end tag
        elif tag_type == 'end':
            # Then check to see if the last opened section
            # is the same as us
            last_section = open_sections.pop()
            if tag_key != last_section:
                # Otherwise we need to complain
                raise UnclosedSection()

        # If we might be a standalone and we aren't a tag that can't
        # be a standalone
        if is_standalone and tag_type not in ['variable', 'no escape']:
            until = grab_literal('\n')

            # If the stuff to the right of us are spaces
            if until.isspace() or until == '':
                # Then we're a standalone
                is_standalone = True

                # And if we aren't a partial
                if tag_type != 'partial':
                    # Then we need to remove the spaces from the left
                    literal = literal.rstrip(' ')

            else:
                # TODO: this is messy

                # Otherwise we aren't a standalone
                is_standalone = False

                # Now we need to backtrack

                # If the template is finished
                if template.is_finished:
                    # Tell it that it has more work
                    template.is_finished = False

                # If we're a set delimiter tag
                if tag_type == 'set delimiter?':
                    # Then step back the length of the stuff we grabbed
                    template.seek(template.tell() - len(until))
                else:
                    # Otherwise step back the length plus one
                    template.seek(template.tell() - (len(until) + 1))

                # I don't know why there's a difference...

        # If we're a tag can't be a standalone
        elif tag_type in ['variable', 'no escape']:
            # Then we aren't a standalone
            is_standalone = False

        # Start yielding

        # Ignore literals that are empty
        if literal != '':
            yield ('literal', literal)

        # Ignore comments and set delimiters
        if tag_type not in ['comment', 'set delimiter?']:
            yield (tag_type, tag_key)

    # If there are any open sections when we're done
    if open_sections:
        # Then we need to complain
        raise UnclosedSection()

def render(template='', data={}, partials_path='.', partials_ext='mustache',
           partials_dict={}, padding=0):
    """Render a mustache template.

    Renders a mustache template with a data scope and partial capability.
    Given the file structure...
    .
    |- main.py
    |- main.ms
    |- partials
     |- part.ms

    then main.py would make the following call:

    render(open('main.ms', 'r'), {...}, 'partials', 'ms')

    Arguments:
    template      -- A file-like object or a string containing the template
    data          -- A python dictionary with your data scope
    partials_path -- The path to where your partials are stored
                     (defaults to '.')
    partials_ext  -- The extension that you want the parser to look for
                     (defaults to 'mustache')
    partials_dict -- A python dictionary which will be search for partials
                     before the filesystem is. {'include': 'foo'} is the same
                     as a file called include.mustache
                     (defaults to {})
    padding       -- This is for padding partials, and shouldn't be used
                     (but can be if you really want to)

    Returns:
    A string containing the rendered template.
    """

    def html_escape(string):
        """HTML escape all of these " & < >"""

        html_codes = {
            '"': '"',
            '&': '&',
            '<': '<',
            '>': '>',
        }

        def escape_char(char):
            return html_codes.get(char, char)

        try:
            return ''.join(map(escape_char, string))
        except TypeError:
            return ''

    def get_key(key):
        """Get a key from the current scope"""

        # If the key is a dot
        if key == '.':
            # Then just return the current scope
            return scopes[0]

        # Loop through the scopes
        for scope in scopes:
            try:
                # For every dot seperated key
                for key in key.split('.'):
                    # Move into the scope
                    scope = scope[key]
                # Return the last scope we got
                return scope
            except (TypeError, KeyError):
                # We couldn't find the key in the current scope
                # We'll try again on the next pass
                pass

        # We couldn't find the key in any of the scopes
        return ''

    def get_partial(name):
        """Load a partial"""
        try:
            # Maybe the partial is in the dictionary
            return partials_dict[name]
        except KeyError:
            # Nope...
            try:
                # Maybe it's in the file system
                path = partials_path + '/' + name + '.' + partials_ext
                return open(path, 'r')
            except IOError:
                # Alright I give up on you
                return StringIO(None)

    # If the template is a list
    if type(template) is list:
        # Then we don't need to tokenize it
        tokens = template
    else:
        # Otherwise make a generator
        tokens = tokenize(template)

    output = ''

    # If the data is a list
    if type(data) is list:
        # Then it's probably a list of scopes
        scopes = data
    else:
        # Otherwise it's a single scope
        scopes = [data]

    # Run through the tokens
    for tag, key in tokens:
        # Set the current scope
        try:
            current_scope = scopes[0]
        except IndexError:
            current_scope = None

        # If we're an end tag
        if tag == 'end':
            # Pop out of the latest scope
            scopes = scopes[1:]

        # If the current scope is falsy and not the only scope
        elif not current_scope and len(scopes) != 1:
            # If we're a section tag
            if tag == 'section':
                # Set it as the most recent scope
                scopes.insert(0, scope)

            # If we're an inverted section tag
            elif tag == 'inverted section':
                # Set the flipped scope as the most recent scope
                scopes.insert(0, not scope)

        # If we're a literal tag
        elif tag == 'literal':
            # Add padding to the key and add it to the output
            output += key.replace('\n', '\n' + (' ' * padding))

        # If we're a variable tag
        elif tag == 'variable':
            # Add the html escaped key to the output
            output += html_escape(str(get_key(key)))

        # If we're a no html escape tag
        elif tag == 'no escape':
            # Just lookup the key and add it
            output += str(get_key(key))

        # If we're a section tag
        elif tag == 'section':
            # Get the sections scope
            scope = get_key(key)

            # If the scope is a list
            if type(scope) is list:
                # Then we need to do some looping

                # Gather up all the tags inside the section
                tags = []
                for tag in tokens:
                    if tag == ('end', key):
                        break
                    tags.append(tag)

                # For every item in the scope
                for thing in scope:
                    # Append it as the most recent scope and render
                    new_scope = [thing] + scopes
                    output += render(tags, new_scope, partials_path,
                                     partials_ext, partials_dict)

            else:
                # Otherwise we're just a scope section
                scopes.insert(0, scope)

        # If we're an inverted section
        elif tag == 'inverted section':
            # Add the flipped scope to the scopes
            scope = get_key(key)
            scopes.insert(0, not scope)

        # If we're a partial
        elif tag == 'partial':
            # Load the partial
            partial = get_partial(key)

            # Find how much to pad the partial
            left = output.split('\n')[-1]
            part_padding = padding
            if left.isspace():
                part_padding += left.count(' ')

            # Render the partial
            part_out = render(partial, scopes, partials_path,
                              partials_ext, partials_dict, part_padding)

            # If the partial was indented
            if left.isspace():
                # then remove the spaces from the end
                part_out = part_out.rstrip(' ')

            # Add the partials output to the ouput
            output += part_out

        else:
            # This should never get hit
            print('UNKNOWN TAG:', tag)

    return output

if __name__ == '__main__':
    args = {
        'template': open(argv[2], 'r'),
        'data': json.load(open(argv[1], 'r')),
    }

    output = render(**args)
    print(output)
<|endoftext|>


<commit_before>"""
Model domains
=============

Regular latitude/longitude
--------------------------

For regular latitude/longitude grids a simple bounding box test is all
that is required to determine if a point lies inside the domain.

Irregular boundaries
--------------------

Regional ocean models with irregular boundaries can perform an additional
point in polygon check to determine if a point is inside the domain.

Global models
-------------

Ocean models of global extent typically have a southern boundary, since
Antarctica is a land mass covering the South Pole. A North/South extent
check may be sufficient to determine whether a point belongs to the domain or
not.
"""
import numpy as np
from . import box

class Domain(object):
    """Grid domain definition"""
    def __init__(self, longitudes, latitudes):
        self.bounding_box = box.Box(np.min(longitudes),
                                    np.max(longitudes),
                                    np.min(latitudes),
                                    np.max(latitudes))

    def contains(self, longitudes, latitudes):
        """check observations are contained within domain"""
        return self.bounding_box.inside(longitudes, latitudes)

def boundary(values):
    """Extract boundary from grid

    A boundary of a grid shaped N x M consists of 2N + 2M - 4 points.
    2 rows, 2 columns minus 4 corners that have been double counted.

    :param values: 2D array shaped (N, M)
    :returns: array shaped (B, 2) where B is the number of points on the
              boundary (2N + 2M - 4).
    """
    return np.asarray(list(values[:, 0]) +
                      list(values[-1, 1:-1]) +
                      list(values[::-1, -1]) +
                      list(values[0, -2:0:-1]),
                      dtype="d")

def point_in_polygon(polygon, point):
    """Determine if points lie inside polygon"""
    return algorithm(polygon[:, 0], polygon[:, 1], point[0], point[1])

def algorithm(x, y, xp, yp):
    """Point in polygon algorithm"""
    search = PolygonSearch(x, y)
    return search.inside(xp, yp)

class PolygonSearch(object):
    """Point in polygon search algorithm"""
    def __init__(self, x, y):
        self.x, self.y = np.asarray(x), np.asarray(y)

        # Define valid line segments
        self.x1, self.y1, self.x2, self.y2 = valid_segments(self.x, self.y)

        # Detect intervals containing f(x) = yp
        self.y_min, self.y_max = order_intervals(self.y1, self.y2)

        # Determine y-axis grid limit
        self.y_limit = np.max([self.y1, self.y2])

    def inside(self, xp, yp):
        """Check point(s) lie inside polygon"""
        xp, yp = np.asarray(xp), np.asarray(yp)
        if xp.ndim == 0:
            return self._scalar_inside(xp, yp)
        return self._vector_inside(xp, yp)

    def _vector_inside(self, xp, yp):
        return np.array([self._scalar_inside(x, y) for x, y in zip(xp, yp)],
                        dtype=np.bool)

    def _scalar_inside(self, xp, yp):
        # Apply algorithm to points at top of domain
        if yp == self.y_limit:
            nodes = self.x[self.y == self.y_limit]
            return self.between_nodes(nodes, xp)

        # Detect intervals containing f(x) = yp
        points = interval_contains(self.y_min, self.y_max, yp)

        # Check that nodes exist
        if len(self.x1[points]) == 0:
            return False

        # Find x-values corresponding to yp for each segment
        nodes = solve(self.x1[points],
                      self.y1[points],
                      self.x2[points],
                      self.y2[points],
                      yp)
        return self.between_nodes(nodes, xp)

    @staticmethod
    def between_nodes(nodes, position):
        """Check position in relation to node positions

        A point is inside the domain for one of two reasons, either:
           - there are an odd number of nodes on either side of the point
           - the point is on the boundary (is a node position)

        :returns: True if position is in domain
        """
        # Include solutions on boundary
        if position in nodes:
            return True
        # Count nodes left/right of xp
        return (odd(count_below(nodes, position)) and
                odd(count_above(nodes, position)))

def valid_segments(x, y):
    """Convert coordinates representing polygon to segments used by algorithm

    .. note:: segments parallel to x-axis are removed since algorithm
              can't search line segments with dy equal to zero.
    """
    # pylint: disable=invalid-name
    x1, y1 = x, y
    x2, y2 = cycle(x), cycle(y)
    return remove_horizontal(x1, y1, x2, y2)

def remove_horizontal(x1, y1, x2, y2):
    """Remove segments with zero slope"""
    keep = y1 != y2
    return x1[keep], y1[keep], x2[keep], y2[keep]

def cycle(values):
    """Shift array view in a cyclic manner"""
    return np.append(values[1:], values[0])

def order_intervals(left, right):
    """Rearrange intervals into ascending order

    :param left: left interval values
    :param right: right interval values
    :returns: (minimum, maximum) arrays sorted into lower/upper values
    """
    return np.min([left, right], axis=0), np.max([left, right], axis=0)

def interval_contains(minimum, maximum, value):
    """Determine if interval contains point

    .. note:: zero sized intervals do not contain points

    .. note:: interval is closed to the left and open on the right
    """
    minimum, maximum = np.asarray(minimum), np.asarray(maximum)
    return (minimum <= value) & (value < maximum)

def solve(x1, y1, x2, y2, y):
    """Solve equation of line for x given y

    This is the inverse of the usual approach to solving a linear equation.
    Linear equations can be solved forward for y or backward for x using the
    same form of equation, y0 + (dy / dx) * (x - x0). In this case with
    y and x switched, the equation reads x0 + (dx / dy) * (y - y0).

    :returns: value that satisfies line defined by (x1, y1), (x2, y2)
    """
    dxdy = (x2 - x1) / (y2 - y1)
    return x1 + (dxdy * (y - y1))

def count_below(values, threshold):
    """Count number of values lying below some threshold"""
    return (values < threshold).sum()

def count_above(values, threshold):
    """Count number of values lying above some threshold"""
    return (values > threshold).sum()

def odd(number):
    """Determine if number is odd"""
    return (number % 2) == 1
<commit_msg>simplified valid_segment selection by separating concerns, one method makes segments and one method removes horizontal segments<commit_after># pylint: disable=invalid-name
"""
Model domains
=============

Regular latitude/longitude
--------------------------

For regular latitude/longitude grids a simple bounding box test is all
that is required to determine if a point lies inside the domain.

Irregular boundaries
--------------------

Regional ocean models with irregular boundaries can perform an additional
point in polygon check to determine if a point is inside the domain.

Global models
-------------

Ocean models of global extent typically have a southern boundary, since
Antarctica is a land mass covering the South Pole. A North/South extent
check may be sufficient to determine whether a point belongs to the domain or
not.
"""
import numpy as np
from . import box

class Domain(object):
    """Grid domain definition"""
    def __init__(self, longitudes, latitudes):
        self.bounding_box = box.Box(np.min(longitudes),
                                    np.max(longitudes),
                                    np.min(latitudes),
                                    np.max(latitudes))

    def contains(self, longitudes, latitudes):
        """check observations are contained within domain"""
        return self.bounding_box.inside(longitudes, latitudes)

def boundary(values):
    """Extract boundary from grid

    A boundary of a grid shaped N x M consists of 2N + 2M - 4 points.
    2 rows, 2 columns minus 4 corners that have been double counted.

    :param values: 2D array shaped (N, M)
    :returns: array shaped (B, 2) where B is the number of points on the
              boundary (2N + 2M - 4).
    """
    return np.asarray(list(values[:, 0]) +
                      list(values[-1, 1:-1]) +
                      list(values[::-1, -1]) +
                      list(values[0, -2:0:-1]),
                      dtype="d")

def point_in_polygon(polygon, point):
    """Determine if points lie inside polygon"""
    return algorithm(polygon[:, 0], polygon[:, 1], point[0], point[1])

def algorithm(x, y, xp, yp):
    """Point in polygon algorithm"""
    search = PolygonSearch(x, y)
    return search.inside(xp, yp)

class PolygonSearch(object):
    """Point in polygon search algorithm"""
    def __init__(self, x, y):
        self.x, self.y = np.asarray(x), np.asarray(y)

        # Define valid line segments
        x1, y1, x2, y2 = as_segments(self.x, self.y)
        self.x1, self.y1, self.x2, self.y2 = remove_horizontal(x1, y1, x2, y2)

        # Detect intervals containing f(x) = yp
        self.y_min, self.y_max = order_intervals(self.y1, self.y2)

        # Determine y-axis grid limit
        self.y_limit = np.max([self.y1, self.y2])

    def inside(self, xp, yp):
        """Check point(s) lie inside polygon"""
        xp, yp = np.asarray(xp), np.asarray(yp)
        if xp.ndim == 0:
            return self._scalar_inside(xp, yp)
        return self._vector_inside(xp, yp)

    def _vector_inside(self, xp, yp):
        return np.array([self._scalar_inside(x, y) for x, y in zip(xp, yp)],
                        dtype=np.bool)

    def _scalar_inside(self, xp, yp):
        # Apply algorithm to points at top of domain
        if yp == self.y_limit:
            nodes = self.x[self.y == self.y_limit]
            return self.between_nodes(nodes, xp)

        # Detect intervals containing f(x) = yp
        points = interval_contains(self.y_min, self.y_max, yp)

        # Check that nodes exist
        if len(self.x1[points]) == 0:
            return False

        # Find x-values corresponding to yp for each segment
        nodes = solve(self.x1[points],
                      self.y1[points],
                      self.x2[points],
                      self.y2[points],
                      yp)
        return self.between_nodes(nodes, xp)

    @staticmethod
    def between_nodes(nodes, position):
        """Check position in relation to node positions

        A point is inside the domain for one of two reasons, either:
           - there are an odd number of nodes on either side of the point
           - the point is on the boundary (is a node position)

        :returns: True if position is in domain
        """
        # Include solutions on boundary
        if position in nodes:
            return True
        # Count nodes left/right of xp
        return (odd(count_below(nodes, position)) and
                odd(count_above(nodes, position)))

def as_segments(x, y):
    """Convert coordinates representing polygon to segments"""
    return x, y, cycle(x), cycle(y)

def remove_horizontal(x1, y1, x2, y2):
    """Remove segments with zero slope"""
    keep = y1 != y2
    return x1[keep], y1[keep], x2[keep], y2[keep]

def cycle(values):
    """Shift array view in a cyclic manner"""
    return np.append(values[1:], values[0])

def order_intervals(left, right):
    """Rearrange intervals into ascending order

    :param left: left interval values
    :param right: right interval values
    :returns: (minimum, maximum) arrays sorted into lower/upper values
    """
    return np.min([left, right], axis=0), np.max([left, right], axis=0)

def interval_contains(minimum, maximum, value):
    """Determine if interval contains point

    .. note:: zero sized intervals do not contain points

    .. note:: interval is closed to the left and open on the right
    """
    minimum, maximum = np.asarray(minimum), np.asarray(maximum)
    return (minimum <= value) & (value < maximum)

def solve(x1, y1, x2, y2, y):
    """Solve equation of line for x given y

    This is the inverse of the usual approach to solving a linear equation.
    Linear equations can be solved forward for y or backward for x using the
    same form of equation, y0 + (dy / dx) * (x - x0). In this case with
    y and x switched, the equation reads x0 + (dx / dy) * (y - y0).

    :returns: value that satisfies line defined by (x1, y1), (x2, y2)
    """
    dxdy = (x2 - x1) / (y2 - y1)
    return x1 + (dxdy * (y - y1))

def count_below(values, threshold):
    """Count number of values lying below some threshold"""
    return (values < threshold).sum()

def count_above(values, threshold):
    """Count number of values lying above some threshold"""
    return (values > threshold).sum()

def odd(number):
    """Determine if number is odd"""
    return (number % 2) == 1
<|endoftext|>


<commit_before>#!/usr/bin/python

import json

from sys import argv
from io import StringIO

def tokenize(template):
    """Tokenize a mustache template

    Tokenizes a mustache template in a generator fashion,
    using file-like objects. It also accepts a string containing
    the template.

    Arguments:
    template -- a file-like object, or a string of a mustache template

    Returns:
    A generator of mustache tags in the form of a tuple
    -- (tag_type, tag_key)

    Where tag_type is one of:
     * literal
     * section
     * inverted section
     * end
     * partial
     * no escape
    And tag_key is either the key or in the case of a literal tag,
    the literal itself.
    """

    class UnclosedSection(Exception):
        pass

    def get(amount=1):
        data = template.read(amount)
        if len(data) != amount:
            template.is_finished = True

        return data

    def grab_literal(until=None):
        until = until or l_del
        literal = get()
        while not template.is_finished:
            if literal[-len(until):] == until:
                return literal[:-len(until)]

            literal += get()

        return literal

    tag_types = {
        '!': 'comment',
        '#': 'section',
        '^': 'inverted section',
        '/': 'end',
        '>': 'partial',
        '=': 'set delimiter?',
        '{': 'no escape?',
        '&': 'no escape'
    }

    try:
        template = StringIO(template)
    except TypeError:
        pass

    template.is_finished = False
    is_standalone = True
    open_sections = []
    l_del = '{{'
    r_del = '}}'
    while not template.is_finished:
        literal = grab_literal()

        if literal != '':
            if not literal.isspace():
                padding = literal.split('\n')[-1]
                if padding.isspace() or padding == '':
                    is_standalone = True
                else:
                    is_standalone = False

        if template.is_finished:
            yield ('literal', literal)
            break

        tag_key = get(1)
        tag_type = tag_types.get(tag_key, 'variable')
        if tag_type != 'variable':
            tag_key = ''

        tag_key += grab_literal(r_del)
        tag_key = tag_key.strip()

        if tag_type == 'no escape?':
            if get(1) == '}':
                tag_type = 'no escape'
            else:
                template.seek(template.tell() - 1)

        elif tag_type == 'set delimiter?':
            if tag_key[-1] == '=':
                dels = tag_key[:-1].strip().split(' ')
                l_del, r_del = dels[0], dels[-1]

        elif tag_type in ['section', 'inverted section']:
            open_sections.append(tag_key)

        elif tag_type == 'end':
            last_section = open_sections.pop()
            if tag_key != last_section:
                raise UnclosedSection()

        if is_standalone and tag_type not in ['variable', 'no escape']:
            until = grab_literal('\n')
            if until.isspace() or until == '':
                is_standalone = True
                literal = literal.rstrip(' ')

            else:
                is_standalone = False
                if template.is_finished:
                    template.is_finished = False

                template.seek(template.tell() - len(until))

        if literal != '':
            yield ('literal', literal)

        if tag_type not in ['comment', 'set delimiter?']:
            yield (tag_type, tag_key)

    if open_sections:
        raise UnclosedSection()

def render(template, data, partials_path='.', partials_ext='mustache',
           partials_dict={}):
    """Render a mustache template.

    Renders a mustache template with a data scope and partial capability.
    Given the file structure...
    .
    |- main.py
    |- main.ms
    |- partials
     |- part.ms

    then main.py would make the following call:

    render(open('main.ms', 'r'), {...}, 'partials', 'ms')

    Arguments:
    template      -- A file-like object or a string containing the template
    data          -- A python dictionary with your data scope
    partials_path -- The path to where your partials are stored
                     (defaults to '.')
    partials_ext  -- The extension that you want the parser to look for
                     (defaults to 'mustache')
    partials_dict -- A python dictionary which will be search for partials
                     before the filesystem is. {'include': 'foo'} is the same
                     as a file called include.mustache
                     (defaults to {})

    Returns:
    A string containing the rendered template.
    """

    def html_escape(string):
        html_codes = {
            '"': '"',
            '&': '&',
            '<': '<',
            '>': '>',
        }

        def escape_char(char):
            return html_codes.get(char, char)

        try:
            return ''.join(map(escape_char, string))
        except TypeError:
            return ''

    def get_key(key):
        for scope in scopes:
            try:
                for key in key.split('.'):
                    scope = scope[key]
                return scope
            except (TypeError, KeyError):
                pass
        return ''

    def get_partial(name):
        try:
            return partials_dict[name]
        except KeyError:
            try:
                path = partials_path + '/' + name + '.' + partials_ext
                return open(path, 'r')
            except IOError:
                return StringIO(None)

    if type(template) is list:
        tokens = template
    else:
        tokens = tokenize(template)

    output = ''
    if type(data) is list:
        scopes = data
    else:
        scopes = [data]

    for tag, key in tokens:
        try:
            current_scope = scopes[0]
        except IndexError:
            current_scope = None

        if tag == 'end':
            scopes = scopes[1:]

        elif not current_scope and len(scopes) != 1:
            pass

        elif tag == 'literal':
            output += key

        elif tag == 'variable':
            output += html_escape(str(get_key(key)))

        elif tag == 'no escape':
            output += str(get_key(key))

        elif tag == 'section':
            scope = get_key(key)

            if type(scope) is list:
                tags = []
                for tag in tokens:
                    if tag == ('end', key):
                        break
                    tags.append(tag)

                for thing in scope:
                    new_scope = [thing] + scopes
                    output += render(tags, new_scope, partials_path,
                                     partials_ext, partials_dict)

            else:
                scopes.insert(0, scope)

        elif tag == 'inverted section':
            scope = get_key(key)
            scopes.insert(0, not scope)

        elif tag == 'partial':
            partial = get_partial(key)
            output += render(partial, scopes)

        else:
            print('>>', tag)

    return output

if __name__ == '__main__':
    data = argv[1]
    template = argv[2]

    output = render(open(template, 'r'), json.load(open(data, 'r')))
    print(output)
<commit_msg>Fixed partial scoping<commit_after>#!/usr/bin/python

import json

from sys import argv
from io import StringIO

def tokenize(template):
    """Tokenize a mustache template

    Tokenizes a mustache template in a generator fashion,
    using file-like objects. It also accepts a string containing
    the template.

    Arguments:
    template -- a file-like object, or a string of a mustache template

    Returns:
    A generator of mustache tags in the form of a tuple
    -- (tag_type, tag_key)

    Where tag_type is one of:
     * literal
     * section
     * inverted section
     * end
     * partial
     * no escape
    And tag_key is either the key or in the case of a literal tag,
    the literal itself.
    """

    class UnclosedSection(Exception):
        pass

    def get(amount=1):
        data = template.read(amount)
        if len(data) != amount:
            template.is_finished = True

        return data

    def grab_literal(until=None):
        until = until or l_del
        literal = get()
        while not template.is_finished:
            if literal[-len(until):] == until:
                return literal[:-len(until)]

            literal += get()

        return literal

    tag_types = {
        '!': 'comment',
        '#': 'section',
        '^': 'inverted section',
        '/': 'end',
        '>': 'partial',
        '=': 'set delimiter?',
        '{': 'no escape?',
        '&': 'no escape'
    }

    try:
        template = StringIO(template)
    except TypeError:
        pass

    template.is_finished = False
    is_standalone = True
    open_sections = []
    l_del = '{{'
    r_del = '}}'
    while not template.is_finished:
        literal = grab_literal()

        if literal != '':
            if not literal.isspace():
                padding = literal.split('\n')[-1]
                if padding.isspace() or padding == '':
                    is_standalone = True
                else:
                    is_standalone = False

        if template.is_finished:
            yield ('literal', literal)
            break

        tag_key = get(1)
        tag_type = tag_types.get(tag_key, 'variable')
        if tag_type != 'variable':
            tag_key = ''

        tag_key += grab_literal(r_del)
        tag_key = tag_key.strip()

        if tag_type == 'no escape?':
            if get(1) == '}':
                tag_type = 'no escape'
            else:
                template.seek(template.tell() - 1)

        elif tag_type == 'set delimiter?':
            if tag_key[-1] == '=':
                dels = tag_key[:-1].strip().split(' ')
                l_del, r_del = dels[0], dels[-1]

        elif tag_type in ['section', 'inverted section']:
            open_sections.append(tag_key)

        elif tag_type == 'end':
            last_section = open_sections.pop()
            if tag_key != last_section:
                raise UnclosedSection()

        if is_standalone and tag_type not in ['variable', 'no escape']:
            until = grab_literal('\n')
            if until.isspace() or until == '':
                is_standalone = True
                literal = literal.rstrip(' ')

            else:
                is_standalone = False
                if template.is_finished:
                    template.is_finished = False

                template.seek(template.tell() - len(until))

        if literal != '':
            yield ('literal', literal)

        if tag_type not in ['comment', 'set delimiter?']:
            yield (tag_type, tag_key)

    if open_sections:
        raise UnclosedSection()

def render(template, data, partials_path='.', partials_ext='mustache',
           partials_dict={}):
    """Render a mustache template.

    Renders a mustache template with a data scope and partial capability.
    Given the file structure...
    .
    |- main.py
    |- main.ms
    |- partials
     |- part.ms

    then main.py would make the following call:

    render(open('main.ms', 'r'), {...}, 'partials', 'ms')

    Arguments:
    template      -- A file-like object or a string containing the template
    data          -- A python dictionary with your data scope
    partials_path -- The path to where your partials are stored
                     (defaults to '.')
    partials_ext  -- The extension that you want the parser to look for
                     (defaults to 'mustache')
    partials_dict -- A python dictionary which will be search for partials
                     before the filesystem is. {'include': 'foo'} is the same
                     as a file called include.mustache
                     (defaults to {})

    Returns:
    A string containing the rendered template.
    """

    def html_escape(string):
        html_codes = {
            '"': '"',
            '&': '&',
            '<': '<',
            '>': '>',
        }

        def escape_char(char):
            return html_codes.get(char, char)

        try:
            return ''.join(map(escape_char, string))
        except TypeError:
            return ''

    def get_key(key):
        for scope in scopes:
            try:
                for key in key.split('.'):
                    scope = scope[key]
                return scope
            except (TypeError, KeyError):
                pass
        return ''

    def get_partial(name):
        try:
            return partials_dict[name]
        except KeyError:
            try:
                path = partials_path + '/' + name + '.' + partials_ext
                return open(path, 'r')
            except IOError:
                return StringIO(None)

    if type(template) is list:
        tokens = template
    else:
        tokens = tokenize(template)

    output = ''

    if type(data) is list:
        scopes = data
    else:
        scopes = [data]

    for tag, key in tokens:
        try:
            current_scope = scopes[0]
        except IndexError:
            current_scope = None

        if tag == 'end':
            scopes = scopes[1:]

        elif not current_scope and len(scopes) != 1:
            pass

        elif tag == 'literal':
            output += key

        elif tag == 'variable':
            output += html_escape(str(get_key(key)))

        elif tag == 'no escape':
            output += str(get_key(key))

        elif tag == 'section':
            scope = get_key(key)

            if type(scope) is list:
                tags = []
                for tag in tokens:
                    if tag == ('end', key):
                        break
                    tags.append(tag)

                for thing in scope:
                    new_scope = [thing] + scopes
                    output += render(tags, new_scope, partials_path,
                                     partials_ext, partials_dict)

            else:
                scopes.insert(0, scope)

        elif tag == 'inverted section':
            scope = get_key(key)
            scopes.insert(0, not scope)

        elif tag == 'partial':
            partial = get_partial(key)
            output += render(partial, scopes, partials_path,
                             partials_ext, partials_dict)

        else:
            print('>>', tag)

    return output

if __name__ == '__main__':
    data = argv[1]
    template = argv[2]

    output = render(open(template, 'r'), json.load(open(data, 'r')))
    print(output)
<|endoftext|>