<commit_before># fourier <master> <inputFile> <outputFile> <freq>
#
# computes the amplitude and phase of time series data
#

import sys
import os
from pyspark import SparkContext
from thunder.util.dataio import *
from thunder.util.signal import *

if len(sys.argv) < 5:
  print >> sys.stderr, \
  "(fourier) usage: fourier <master> <inputFile> <outputFile> <freq>"
  exit(-1)

# parse inputs
sc = SparkContext(sys.argv[1], "fourier")
inputFile = str(sys.argv[2])
freq = int(sys.argv[4])
outputFile = str(sys.argv[3])+"-fourier"
if not os.path.exists(outputFile) : os.makedirs(outputFile)

# load data
data = sc.textFile(inputFile).map(lambda y : parse(y,"dff")).cache()

# do fourier on each time series
out = data.map(lambda x : getFourier(x,freq))

# save results
co = out.map(lambda x : x[0])
ph = out.map(lambda x : x[1])
saveout(co,outputFile,"co","matlab")
saveout(ph,outputFile,"ph","matlab")
<commit_msg>Testing<commit_after># fourier <master> <inputFile> <outputFile> <freq>
#
# computes the amplitude and phase of time series data
#

import sys
import os
from pyspark import SparkContext
from thunder.util.dataio import *
from thunder.util.signal import *

if len(sys.argv) < 5:
  print >> sys.stderr, \
  "(fourier) usage: fourier <master> <inputFile> <outputFile> <freq>"
  exit(-1)

def parse(line, filter="raw", inds=None):

	vec = [float(x) for x in line.split(' ')]
	ts = (vec[3:]) # get tseries
	if filter == "dff" : # convert to dff
		meanVal = mean(ts)
		ts = (ts - meanVal) / (meanVal + 0.1)
	if inds is not None :
		if inds == "xyz" :
			return ((int(vec[0]),int(vec[1]),int(vec[2])),ts)
		if inds == "linear" :
			k = int(vec[0]) + int((vec[1] - 1)*1650)
			return (k,ts)
	else :
		return ts

# parse inputs
sc = SparkContext(sys.argv[1], "fourier")
inputFile = str(sys.argv[2])
freq = int(sys.argv[4])
outputFile = str(sys.argv[3])+"-fourier"
if not os.path.exists(outputFile) : os.makedirs(outputFile)

# load data
data = sc.textFile(inputFile).map(lambda y : parse(y,"dff")).cache()

# do fourier on each time series
out = data.map(lambda x : getFourier(x,freq))

# save results
co = out.map(lambda x : x[0])
ph = out.map(lambda x : x[1])
saveout(co,outputFile,"co","matlab")
saveout(ph,outputFile,"ph","matlab")
<|endoftext|>


<commit_before>"""
Vector Addition
=================
In this tutorial, you will write a simple vector addition using Triton and learn about:

- The basic programming model of Triton
- The `triton.jit` decorator, which is used to define Triton kernels.
- The best practices for validating and benchmarking your custom ops against native reference implementations
"""

# %%
# Compute Kernel
# --------------------------

import torch

import triton
import triton.language as tl

@triton.jit
def add_kernel(
    x_ptr,  # *Pointer* to first input vector
    y_ptr,  # *Pointer* to second input vector
    output_ptr,  # *Pointer* to output vector
    n_elements,  # Size of the vector
    time_start_ptr, time_end_ptr,
    BLOCK_SIZE: tl.constexpr,  # Number of elements each program should process
                 # NOTE: `constexpr` so it can be used as a shape value
):
    tl.atomic_min(time_start_ptr, tl.clock())
    # There are multiple 'program's processing different data. We identify which program
    # we are here
    pid = tl.program_id(axis=0)  # We use a 1D launch grid so axis is 0
    # This program will process inputs that are offset from the initial data.
    # for instance, if you had a vector of length 256 and block_size of 64, the programs
    # would each access the elements [0:64, 64:128, 128:192, 192:256].
    # Note that offsets is a list of pointers
    block_start = pid * BLOCK_SIZE
    offsets = block_start + tl.arange(0, BLOCK_SIZE)
    # Create a mask to guard memory operations against out-of-bounds accesses
    mask = offsets < n_elements
    # Load x and y from DRAM, masking out any extra elements in case the input is not a
    # multiple of the block size
    x = tl.load(x_ptr + offsets, mask=mask)
    y = tl.load(y_ptr + offsets, mask=mask)
    output = x + y
    # Write x + y back to DRAM
    tl.store(output_ptr + offsets, output, mask=mask)
    tl.atomic_max(time_end_ptr, tl.clock())

# %%
# Let's also declare a helper function to (1) allocate the `z` tensor
# and (2) enqueue the above kernel with appropriate grid/block sizes.

def add(x: torch.Tensor, y: torch.Tensor):
    time_start = torch.zeros(1, dtype=torch.int64, device='cuda')
    time_end = torch.zeros(1, dtype=torch.int64, device='cuda')
    # We need to preallocate the output
    output = torch.empty_like(x)
    assert x.is_cuda and y.is_cuda and output.is_cuda
    n_elements = output.numel()
    # The SPMD launch grid denotes the number of kernel instances that run in parallel.
    # It is analogous to CUDA launch grids. It can be either Tuple[int], or Callable(metaparameters) -> Tuple[int]
    # In this case, we use a 1D grid where the size is the number of blocks
    grid = lambda meta: (triton.cdiv(n_elements, meta['BLOCK_SIZE']),)
    # NOTE:
    #  - each torch.tensor object is implicitly converted into a pointer to its first element.
    #  - `triton.jit`'ed functions can be index with a launch grid to obtain a callable GPU kernel
    #  - don't forget to pass meta-parameters as keywords arguments
    add_kernel[grid](x, y, output, n_elements, time_start, time_end, BLOCK_SIZE=1024)
    # We return a handle to z but, since `torch.cuda.synchronize()` hasn't been called, the kernel is still
    # running asynchronously at this point.
    print((time_end, time_start))
    return output

# %%
# We can now use the above function to compute the element-wise sum of two `torch.tensor` objects and test its correctness:

torch.manual_seed(0)
size = 98432
x = torch.rand(size, device='cuda')
y = torch.rand(size, device='cuda')
output_torch = x + y
output_triton = add(x, y)
print(output_torch)
print(output_triton)
print(
    f'The maximum difference between torch and triton is '
    f'{torch.max(torch.abs(output_torch - output_triton))}'
)

# %%
# Seems like we're good to go!

# %%
# Benchmark
# -----------
# We can now benchmark our custom op on vectors of increasing sizes to get a sense of how it does relative to PyTorch.
# To make things easier, Triton has a set of built-in utilities that allow us to concisely plot the performance of your custom ops
# for different problem sizes.

@triton.testing.perf_report(
    triton.testing.Benchmark(
        x_names=['size'],  # argument names to use as an x-axis for the plot
        x_vals=[
            2 ** i for i in range(12, 28, 1)
        ],  # different possible values for `x_name`
        x_log=True,  # x axis is logarithmic
        line_arg='provider',  # argument name whose value corresponds to a different line in the plot
        line_vals=['triton', 'torch'],  # possible values for `line_arg`
        line_names=['Triton', 'Torch'],  # label name for the lines
        styles=[('blue', '-'), ('green', '-')],  # line styles
        ylabel='GB/s',  # label name for the y-axis
        plot_name='vector-add-performance',  # name for the plot. Used also as a file name for saving the plot.
        args={},  # values for function arguments not in `x_names` and `y_name`
    )
)
def benchmark(size, provider):
    x = torch.rand(size, device='cuda', dtype=torch.float32)
    y = torch.rand(size, device='cuda', dtype=torch.float32)
    if provider == 'torch':
        ms, min_ms, max_ms = triton.testing.do_bench(lambda: x + y)
    if provider == 'triton':
        ms, min_ms, max_ms = triton.testing.do_bench(lambda: add(x, y))
    gbps = lambda ms: 12 * size / ms * 1e-6
    return gbps(ms), gbps(max_ms), gbps(min_ms)

# %%
# We can now run the decorated function above. Pass `print_data=True` to see the performance number, `show_plots=True` to plot them, and/or
# `save_path='/path/to/results/' to save them to disk along with raw CSV data
benchmark.run(print_data=True, show_plots=True)
<commit_msg>[TUTORIALS] Removed leftover print<commit_after>"""
Vector Addition
=================
In this tutorial, you will write a simple vector addition using Triton and learn about:

- The basic programming model of Triton
- The `triton.jit` decorator, which is used to define Triton kernels.
- The best practices for validating and benchmarking your custom ops against native reference implementations
"""

# %%
# Compute Kernel
# --------------------------

import torch

import triton
import triton.language as tl

@triton.jit
def add_kernel(
    x_ptr,  # *Pointer* to first input vector
    y_ptr,  # *Pointer* to second input vector
    output_ptr,  # *Pointer* to output vector
    n_elements,  # Size of the vector
    time_start_ptr, time_end_ptr,
    BLOCK_SIZE: tl.constexpr,  # Number of elements each program should process
                 # NOTE: `constexpr` so it can be used as a shape value
):
    tl.atomic_min(time_start_ptr, tl.clock())
    # There are multiple 'program's processing different data. We identify which program
    # we are here
    pid = tl.program_id(axis=0)  # We use a 1D launch grid so axis is 0
    # This program will process inputs that are offset from the initial data.
    # for instance, if you had a vector of length 256 and block_size of 64, the programs
    # would each access the elements [0:64, 64:128, 128:192, 192:256].
    # Note that offsets is a list of pointers
    block_start = pid * BLOCK_SIZE
    offsets = block_start + tl.arange(0, BLOCK_SIZE)
    # Create a mask to guard memory operations against out-of-bounds accesses
    mask = offsets < n_elements
    # Load x and y from DRAM, masking out any extra elements in case the input is not a
    # multiple of the block size
    x = tl.load(x_ptr + offsets, mask=mask)
    y = tl.load(y_ptr + offsets, mask=mask)
    output = x + y
    # Write x + y back to DRAM
    tl.store(output_ptr + offsets, output, mask=mask)
    tl.atomic_max(time_end_ptr, tl.clock())

# %%
# Let's also declare a helper function to (1) allocate the `z` tensor
# and (2) enqueue the above kernel with appropriate grid/block sizes.

def add(x: torch.Tensor, y: torch.Tensor):
    time_start = torch.zeros(1, dtype=torch.int64, device='cuda')
    time_end = torch.zeros(1, dtype=torch.int64, device='cuda')
    # We need to preallocate the output
    output = torch.empty_like(x)
    assert x.is_cuda and y.is_cuda and output.is_cuda
    n_elements = output.numel()
    # The SPMD launch grid denotes the number of kernel instances that run in parallel.
    # It is analogous to CUDA launch grids. It can be either Tuple[int], or Callable(metaparameters) -> Tuple[int]
    # In this case, we use a 1D grid where the size is the number of blocks
    grid = lambda meta: (triton.cdiv(n_elements, meta['BLOCK_SIZE']),)
    # NOTE:
    #  - each torch.tensor object is implicitly converted into a pointer to its first element.
    #  - `triton.jit`'ed functions can be index with a launch grid to obtain a callable GPU kernel
    #  - don't forget to pass meta-parameters as keywords arguments
    add_kernel[grid](x, y, output, n_elements, time_start, time_end, BLOCK_SIZE=1024)
    # We return a handle to z but, since `torch.cuda.synchronize()` hasn't been called, the kernel is still
    # running asynchronously at this point.
    return output

# %%
# We can now use the above function to compute the element-wise sum of two `torch.tensor` objects and test its correctness:

torch.manual_seed(0)
size = 98432
x = torch.rand(size, device='cuda')
y = torch.rand(size, device='cuda')
output_torch = x + y
output_triton = add(x, y)
print(output_torch)
print(output_triton)
print(
    f'The maximum difference between torch and triton is '
    f'{torch.max(torch.abs(output_torch - output_triton))}'
)

# %%
# Seems like we're good to go!

# %%
# Benchmark
# -----------
# We can now benchmark our custom op on vectors of increasing sizes to get a sense of how it does relative to PyTorch.
# To make things easier, Triton has a set of built-in utilities that allow us to concisely plot the performance of your custom ops
# for different problem sizes.

@triton.testing.perf_report(
    triton.testing.Benchmark(
        x_names=['size'],  # argument names to use as an x-axis for the plot
        x_vals=[
            2 ** i for i in range(12, 28, 1)
        ],  # different possible values for `x_name`
        x_log=True,  # x axis is logarithmic
        line_arg='provider',  # argument name whose value corresponds to a different line in the plot
        line_vals=['triton', 'torch'],  # possible values for `line_arg`
        line_names=['Triton', 'Torch'],  # label name for the lines
        styles=[('blue', '-'), ('green', '-')],  # line styles
        ylabel='GB/s',  # label name for the y-axis
        plot_name='vector-add-performance',  # name for the plot. Used also as a file name for saving the plot.
        args={},  # values for function arguments not in `x_names` and `y_name`
    )
)
def benchmark(size, provider):
    x = torch.rand(size, device='cuda', dtype=torch.float32)
    y = torch.rand(size, device='cuda', dtype=torch.float32)
    if provider == 'torch':
        ms, min_ms, max_ms = triton.testing.do_bench(lambda: x + y)
    if provider == 'triton':
        ms, min_ms, max_ms = triton.testing.do_bench(lambda: add(x, y))
    gbps = lambda ms: 12 * size / ms * 1e-6
    return gbps(ms), gbps(max_ms), gbps(min_ms)

# %%
# We can now run the decorated function above. Pass `print_data=True` to see the performance number, `show_plots=True` to plot them, and/or
# `save_path='/path/to/results/' to save them to disk along with raw CSV data
benchmark.run(print_data=True, show_plots=True)
<|endoftext|>


<commit_before>import mock
import os
import sys
import unittest
import pythonwarrior

from pythonwarrior.floor import Floor
from pythonwarrior.level import Level
from pythonwarrior.profile import Profile
from pythonwarrior.units.warrior import Warrior

class TestLevel(unittest.TestCase):
    def setUp(self):
        self.profile = Profile()
        self.floor = Floor()
        self.level = Level(self.profile, 1)
        self.level.floor = self.floor

    def test_should_consider_passed_When_warrior_is_on_stairs(self):
        self.level.warrior = Warrior()
        self.floor.add(self.level.warrior, 0, 0, 'north')
        self.floor.place_stairs(0, 0)
        self.assertTrue(self.level.is_passed())

    def test_should_default_time_bonus_to_zero(self):
        self.assertEqual(self.level.time_bonus, 0)

    def test_should_have_a_grade_relative_to_ace_score(self):
        self.level.ace_score = 100
        self.assertEqual(self.level.grade_for(110), "S")
        self.assertEqual(self.level.grade_for(100), "S")
        self.assertEqual(self.level.grade_for(99), "A")
        self.assertEqual(self.level.grade_for(89), "B")
        self.assertEqual(self.level.grade_for(79), "C")
        self.assertEqual(self.level.grade_for(69), "D")
        self.assertEqual(self.level.grade_for(59), "F")

    def test_should_have_no_grade_if_there_is_no_ace_score(self):
        self.assertIsNone(self.level.ace_score)
        self.assertIsNone(self.level.grade_for(100))

    def test_should_load_file_contents_into_level(self):
        with mock.patch.object(self.level, 'load_path',
                               return_value='path/to/level.py'):
            mock_file = mock.Mock(
                read=mock.Mock(return_value="level.description('foo')"))
            with mock.patch('__builtin__.open',
                            return_value=mock_file):
                self.level.load_level()
                self.assertEqual(self.level.description, 'foo')

    def test_should_have_a_player_path_from_profile(self):
        with mock.patch.object(self.profile, '_player_path', 'path/to/player'):
            self.assertEqual(self.level.player_path(), 'path/to/player')

    def test_should_have_load_path_from_profile_tower_with_level_number(self):
        with mock.patch.object(self.profile, 'tower_path', 'path/to/tower'):
            self.assertEqual(self.level.load_path(),
                             os.path.abspath(
                                 'pythonwarrior/towers/tower/level_001.py'))

    @mock.patch('pythonwarrior.level.os.path.exists')
    def test_should_exist_if_file_exists(self, mock_exists):
        self.level.load_path = mock.Mock(return_value='/foo/bar')
        mock_exists.return_value = True
        self.assertTrue(self.level.exists())
        mock_exists.assert_called_once_with('/foo/bar')

    @mock.patch('pythonwarrior.level.PlayerGenerator')
    def test_should_generate_player_files(self, mock_pg):
        generator = mock.Mock()
        mock_pg.return_value = generator
        self.level.load_level = mock.Mock()
        self.level.generate_player_files()
        generator.generate.assert_called_once_with()
        self.level.load_level.assert_called_once_with()

    def test_should_setup_warrior_with_profile_abilities(self):
        self.profile.abilities = ['foo', 'bar']
        warrior = mock.Mock()
        self.level.setup_warrior(warrior)
        warrior.add_abilities.assert_called_once_with('foo', 'bar')

    def test_should_setup_warrior_with_profile_name(self):
        self.profile.warrior_name = "Joe"
        warrior = mock.Mock()
        self.level.setup_warrior(warrior)
        self.assertEqual(warrior.name_attr, "Joe")

class TestPlaying(unittest.TestCase):
    def setUp(self):
        self.profile = Profile()
        self.floor = Floor()
        self.level = Level(self.profile, 1)
        self.level.floor = self.floor
        self.level.load_level = mock.Mock()
        self.level.is_failed = mock.Mock(return_value=False)

    def test_load_level_once_when_playing_multiple_turns(self):
        self.level.play(2)
        self.level.load_level.assert_called_once_with()

    def test_should_call_prepare_turn_and_play_turn_on_each_object_specified_number_of_times(self):
        unit = Warrior()
        unit.prepare_turn = mock.Mock()
        unit.perform_turn = mock.Mock()
        self.floor.add(unit, 0, 0, 'north')
        self.level.play(2)
        unit.prepare_turn.assert_called_with()
        unit.perform_turn.assert_called_with()
        self.assertEqual(2, unit.prepare_turn.call_count)
        self.assertEqual(2, unit.perform_turn.call_count)

    def test_should_return_immediately_when_passed(self):
        unit = Warrior()
        unit.turn = mock.Mock()
        self.floor.add(unit, 0, 0, 'north')
        self.level.is_passed = mock.Mock(return_value=True)
        self.level.play(2)

    def test_call_fxn_in_play_for_each_turn(self):
        self.i = 0

        def foo():
            self.i += 1

        self.level.play(2, foo)
        self.assertEqual(self.i, 2)

    def test_should_count_down_time_bonus_once_each_turn(self):
        self.level.time_bonus = 10
        self.level.play(3)
        self.assertEqual(self.level.time_bonus, 7)

    def test_should_count_down_time_bonus_to_zero(self):
        self.level.time_bonus = 2
        self.level.play(5)
        self.assertEqual(self.level.time_bonus, 0)

    def test_should_have_a_pretty_score_calculation(self):
        self.assertEqual(self.level.score_calculation(123, 45),
                         "123 + 45 = 168")

    def test_should_not_have_score_calc_when_starting_score_is_zero(self):
        self.assertEqual(self.level.score_calculation(0, 45), "45")

class TestTallying(unittest.TestCase):
    def setUp(self):
        self.profile = Profile()
        self.floor = Floor()
        self.level = Level(self.profile, 1)
        self.level.floor = self.floor
        self.level.load_level = mock.Mock()
        self.level.is_failed = mock.Mock(return_value=False)
        self.level.floor.other_units = mock.Mock(return_value=[mock.Mock()])
        self.warrior = mock.Mock(score=0, abilities={})
        self.level.warrior = self.warrior

    def test_should_add_warrior_score_to_profile(self):
        self.warrior.score = 30
        self.profile.score = 0
        self.level.tally_points()
        self.assertEqual(self.profile.score, 30)

    def test_should_apply_warrior_abilities_to_profile(self):
        self.warrior.abilities = {'foo': None, 'bar': None}
        self.level.tally_points()
        self.assertEqual(['foo', 'bar'], self.profile.abilities)

    def test_should_apply_time_bonus_to_profile_score(self):
        self.level.time_bonus = 20
        self.level.tally_points()
        self.assertEqual(20, self.profile.score)

    def test_should_give_20_percent_bonus_when_no_other_units_left(self):
        self.level.floor.other_units = mock.Mock(return_value=[])
        self.warrior.score = 10
        self.level.time_bonus = 10
        self.level.tally_points()
        self.assertEqual(24, self.profile.score)
<commit_msg>Remove unused imports<commit_after>import mock
import os
import unittest

from pythonwarrior.floor import Floor
from pythonwarrior.level import Level
from pythonwarrior.profile import Profile
from pythonwarrior.units.warrior import Warrior

class TestLevel(unittest.TestCase):
    def setUp(self):
        self.profile = Profile()
        self.floor = Floor()
        self.level = Level(self.profile, 1)
        self.level.floor = self.floor

    def test_should_consider_passed_When_warrior_is_on_stairs(self):
        self.level.warrior = Warrior()
        self.floor.add(self.level.warrior, 0, 0, 'north')
        self.floor.place_stairs(0, 0)
        self.assertTrue(self.level.is_passed())

    def test_should_default_time_bonus_to_zero(self):
        self.assertEqual(self.level.time_bonus, 0)

    def test_should_have_a_grade_relative_to_ace_score(self):
        self.level.ace_score = 100
        self.assertEqual(self.level.grade_for(110), "S")
        self.assertEqual(self.level.grade_for(100), "S")
        self.assertEqual(self.level.grade_for(99), "A")
        self.assertEqual(self.level.grade_for(89), "B")
        self.assertEqual(self.level.grade_for(79), "C")
        self.assertEqual(self.level.grade_for(69), "D")
        self.assertEqual(self.level.grade_for(59), "F")

    def test_should_have_no_grade_if_there_is_no_ace_score(self):
        self.assertIsNone(self.level.ace_score)
        self.assertIsNone(self.level.grade_for(100))

    def test_should_load_file_contents_into_level(self):
        with mock.patch.object(self.level, 'load_path',
                               return_value='path/to/level.py'):
            mock_file = mock.Mock(
                read=mock.Mock(return_value="level.description('foo')"))
            with mock.patch('__builtin__.open',
                            return_value=mock_file):
                self.level.load_level()
                self.assertEqual(self.level.description, 'foo')

    def test_should_have_a_player_path_from_profile(self):
        with mock.patch.object(self.profile, '_player_path', 'path/to/player'):
            self.assertEqual(self.level.player_path(), 'path/to/player')

    def test_should_have_load_path_from_profile_tower_with_level_number(self):
        with mock.patch.object(self.profile, 'tower_path', 'path/to/tower'):
            self.assertEqual(self.level.load_path(),
                             os.path.abspath(
                                 'pythonwarrior/towers/tower/level_001.py'))

    @mock.patch('pythonwarrior.level.os.path.exists')
    def test_should_exist_if_file_exists(self, mock_exists):
        self.level.load_path = mock.Mock(return_value='/foo/bar')
        mock_exists.return_value = True
        self.assertTrue(self.level.exists())
        mock_exists.assert_called_once_with('/foo/bar')

    @mock.patch('pythonwarrior.level.PlayerGenerator')
    def test_should_generate_player_files(self, mock_pg):
        generator = mock.Mock()
        mock_pg.return_value = generator
        self.level.load_level = mock.Mock()
        self.level.generate_player_files()
        generator.generate.assert_called_once_with()
        self.level.load_level.assert_called_once_with()

    def test_should_setup_warrior_with_profile_abilities(self):
        self.profile.abilities = ['foo', 'bar']
        warrior = mock.Mock()
        self.level.setup_warrior(warrior)
        warrior.add_abilities.assert_called_once_with('foo', 'bar')

    def test_should_setup_warrior_with_profile_name(self):
        self.profile.warrior_name = "Joe"
        warrior = mock.Mock()
        self.level.setup_warrior(warrior)
        self.assertEqual(warrior.name_attr, "Joe")

class TestPlaying(unittest.TestCase):
    def setUp(self):
        self.profile = Profile()
        self.floor = Floor()
        self.level = Level(self.profile, 1)
        self.level.floor = self.floor
        self.level.load_level = mock.Mock()
        self.level.is_failed = mock.Mock(return_value=False)

    def test_load_level_once_when_playing_multiple_turns(self):
        self.level.play(2)
        self.level.load_level.assert_called_once_with()

    def test_should_call_prepare_turn_and_play_turn_on_each_object_specified_number_of_times(self):
        unit = Warrior()
        unit.prepare_turn = mock.Mock()
        unit.perform_turn = mock.Mock()
        self.floor.add(unit, 0, 0, 'north')
        self.level.play(2)
        unit.prepare_turn.assert_called_with()
        unit.perform_turn.assert_called_with()
        self.assertEqual(2, unit.prepare_turn.call_count)
        self.assertEqual(2, unit.perform_turn.call_count)

    def test_should_return_immediately_when_passed(self):
        unit = Warrior()
        unit.turn = mock.Mock()
        self.floor.add(unit, 0, 0, 'north')
        self.level.is_passed = mock.Mock(return_value=True)
        self.level.play(2)

    def test_call_fxn_in_play_for_each_turn(self):
        self.i = 0

        def foo():
            self.i += 1

        self.level.play(2, foo)
        self.assertEqual(self.i, 2)

    def test_should_count_down_time_bonus_once_each_turn(self):
        self.level.time_bonus = 10
        self.level.play(3)
        self.assertEqual(self.level.time_bonus, 7)

    def test_should_count_down_time_bonus_to_zero(self):
        self.level.time_bonus = 2
        self.level.play(5)
        self.assertEqual(self.level.time_bonus, 0)

    def test_should_have_a_pretty_score_calculation(self):
        self.assertEqual(self.level.score_calculation(123, 45),
                         "123 + 45 = 168")

    def test_should_not_have_score_calc_when_starting_score_is_zero(self):
        self.assertEqual(self.level.score_calculation(0, 45), "45")

class TestTallying(unittest.TestCase):
    def setUp(self):
        self.profile = Profile()
        self.floor = Floor()
        self.level = Level(self.profile, 1)
        self.level.floor = self.floor
        self.level.load_level = mock.Mock()
        self.level.is_failed = mock.Mock(return_value=False)
        self.level.floor.other_units = mock.Mock(return_value=[mock.Mock()])
        self.warrior = mock.Mock(score=0, abilities={})
        self.level.warrior = self.warrior

    def test_should_add_warrior_score_to_profile(self):
        self.warrior.score = 30
        self.profile.score = 0
        self.level.tally_points()
        self.assertEqual(self.profile.score, 30)

    def test_should_apply_warrior_abilities_to_profile(self):
        self.warrior.abilities = {'foo': None, 'bar': None}
        self.level.tally_points()
        self.assertEqual(['foo', 'bar'], self.profile.abilities)

    def test_should_apply_time_bonus_to_profile_score(self):
        self.level.time_bonus = 20
        self.level.tally_points()
        self.assertEqual(20, self.profile.score)

    def test_should_give_20_percent_bonus_when_no_other_units_left(self):
        self.level.floor.other_units = mock.Mock(return_value=[])
        self.warrior.score = 10
        self.level.time_bonus = 10
        self.level.tally_points()
        self.assertEqual(24, self.profile.score)
<|endoftext|>


<commit_before>from django.views.generic import View, ListView, CreateView, UpdateView,\
    DetailView
from django.core.urlresolvers import reverse_lazy, reverse
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.core.cache import cache

import re
import datetime
from braces.views import LoginRequiredMixin

from .models import Category, Thread, Post, Preview, PollQuestion, \
    ThreadCession
from .forms import ThreadForm, PostForm, PollThreadForm, QuestionForm, \
    ChoicesFormSet, FormSetHelper
from .util import get_query

### Helpers ###
def get_preview(content):
    "Redirect to post preview"
    p = Preview.objects.create(content_plain=content)
    return HttpResponseRedirect(reverse('forum:preview', kwargs={'pk': p.pk}))

class ThreadStatusMixin(object):
    "Populate thread status and readCaret where needed"

    def get_context_data(self, **kwargs):

        def get_post_page(post):
            return  post.position // PostView.paginate_by + 1

        context = super().get_context_data(**kwargs)
        user = self.request.user
        readCaret = cache.get("user/{}/readCaret".format(user.pk))
        if not readCaret:
            readCaret = user.postsReadCaret.all()
            cache.set("user/{}/readCaret".format(user.pk),
                  readCaret, None)
        for t in context['object_list']:
            contributors = cache.get("thread/{}/contributors".format(t.pk))
            if not contributors:  # caches thread's contributors
                contributors = t.contributors.all()
                cache.set("thread/{}/contributors".format(t.pk),
                  contributors, None)
            # Get latest_post from cache or create it
            latest_post = cache.get("thread/{}/latest_post".format(t.pk))
            if not latest_post:
                latest_post = t.latest_post
                cache.set("thread/{}/latest_post".format(t.pk),
                          latest_post, None)
            uptodate_caret = latest_post in readCaret
            if user in contributors and uptodate_caret:
                status = "added"
            elif user in contributors:
                status = "added+on"
                try:
                    t.readCaret = readCaret.get(thread=t)
                    t.readCaret.page = get_post_page(t.readCaret)
                except ObjectDoesNotExist:
                    t.readCaret = "not_visited"
            elif uptodate_caret:
                status = "off"
            else:
                status = "on"
                try:
                    t.readCaret = readCaret.get(thread=t)
                    t.readCaret.page = get_post_page(t.readCaret)
                except ObjectDoesNotExist:
                    t.readCaret = "not_visited"
            t.status = 'img/{}.png'.format(status)
        return context

class PreviewPostMixin(object):
    def post(self, request, *args, **kwargs):
        if "preview" in request.POST:
            return get_preview(request.POST['content_plain'])
        else:
            return super().post(request, *args, **kwargs)

### Main Forum Views ###
class TopView(LoginRequiredMixin, ListView):
    model = Category

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['readCaret'] = self.request.user.postsReadCaret.all()
        return context

class ThreadView(LoginRequiredMixin, ThreadStatusMixin, ListView):
    paginate_by = 30

    def get_queryset(self):
        "Return threads of the current category ordered by latest post"
        self.c = Category.objects.get(slug=self.kwargs['category_slug'])
        return self.c.threads.select_related('author', 'question')\
                             .filter(visible=True)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['category'] = self.c
        return context

class PostView(LoginRequiredMixin, ListView):
    paginate_by = 30

    def dispatch(self, request, *args, **kwargs):
        c_slug = self.kwargs['category_slug']
        t_slug = self.kwargs['thread_slug']
        self.t = Thread.objects.get(slug=t_slug,
                                    category__slug=c_slug)
        # 403 if the thread has been removed
        if not self.t.visible:
            return HttpResponseForbidden()
        self.t.viewCount += 1  # Increment views
        self.t.save()
        # Handle user read caret
        p = self.t.latest_post
        try:
            caret = self.request.user.postsReadCaret.get(thread=self.t)
        except:
            caret = False
        if caret != p:
            self.request.user.postsReadCaret.remove(caret)
            self.request.user.postsReadCaret.add(p)
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        "Return list of posts given thread and category slugs"
        return self.t.posts.all()

    def get_context_data(self, **kwargs):
        "Pass thread from url to context"
        context = super().get_context_data(**kwargs)
        context['thread'] = self.t
        return context

### Thread and Post creation and edit ###
class NewThread(LoginRequiredMixin, PreviewPostMixin, CreateView):
    form_class = ThreadForm
    template_name = 'forum/new_thread.html'

    def dispatch(self, request, *args, **kwargs):
        self.c = Category.objects.get(slug=self.kwargs['category_slug'])
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        "Pass Category from url to context"
        context = super().get_context_data(**kwargs)
        context['category'] = self.c
        return context

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update({'category_slug': self.kwargs['category_slug']})
        return kwargs

    def form_valid(self, form):
        "Handle thread and 1st post creation in the db"
        # Create the thread
        t = Thread.objects.create(
            title=form.cleaned_data['title'],
            icon=form.cleaned_data['icon'],
            author=self.request.user,
            category=self.c,
            personal=form.cleaned_data['personal'])
        # Complete the post and save it
        form.instance.thread = t
        form.instance.thread.category.postCount += 1  # Increment category
        form.instance.thread.category.save()          # post counter
        form.instance.author = self.request.user
        p = form.save()
        self.request.user.postsReadCaret.add(p)
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse_lazy('forum:category', kwargs=self.kwargs)

class NewPost(LoginRequiredMixin, PreviewPostMixin, CreateView):
    form_class = PostForm
    template_name = 'forum/new_post.html'

    def dispatch(self, request, *args, **kwargs):
        self.t = Thread.objects.get(
            slug=self.kwargs['thread_slug'],
            category__slug=self.kwargs['category_slug'])
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        "Pass category and thread from url to context"
        context = super().get_context_data(**kwargs)
        context['category'] = self.t.category
        context['thread'] = self.t
        context['history'] = Post.objects.filter(
            thread=self.t).order_by('-pk')[:10]
        return context

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update({'category_slug': self.kwargs['category_slug'],
                       'thread': self.t})
        return kwargs

    def form_valid(self, form):
        "Handle post creation in the db"
        # Update category and thread
        self.t.category.postCount += 1
        self.t.category.save()
        # Update remaining form fields
        form.instance.thread = self.t
        form.instance.author = self.request.user
        return super().form_valid(form)

    def get_success_url(self):
        return (reverse_lazy('forum:thread', kwargs=self.kwargs)
                + '?page=last#' + str(self.object.pk))

class QuotePost(NewPost):
    """Quote the content of another post"""

    def dispatch(self, request, *args, **kwargs):
        self.p = Post.objects.get(pk=self.kwargs['pk'])
        self.t = self.p.thread
        return super().dispatch(request, *args, **kwargs)

    def get_initial(self):
        "Pass quoted post content as initial data for form"
        initial = super().get_initial()
        text = "[quote][b]{:s} a dit :[/b]\n{:s}[/quote]".format(
            self.p.author.username, self.p.content_plain)
        initial['content_plain'] = text
        return initial

class EditPost(LoginRequiredMixin, PreviewPostMixin, UpdateView):
    form_class = ThreadForm
    model = Post
    template_name = 'forum/edit.html'

    def dispatch(self, request, *args, **kwargs):
        "Get the right post and thread"
        self.p = Post.objects.get(pk=self.kwargs['pk'])
        if self.p.author != self.request.user:
            return HttpResponseForbidden()
        self.t = self.p.thread
        self.c = self.t.category
        return super().dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        if "cede" in request.POST:
            ThreadCession.objects.get_or_create(thread=self.t)
            return HttpResponseRedirect(
                reverse('forum:cession',
                        kwargs={'category_slug': self.c.slug,
                                'thread_slug': self.t.slug}))
        else:
            return super().post(request, *args, **kwargs)

    def get_initial(self):
        "Pass initial data to form"
        initial = super().get_initial()
        initial['title'] = self.t.title
        initial['icon'] = self.t.icon[4:][:-4]
        return initial

    def get_context_data(self, **kwargs):
        "Pass category and thread from url to context"
        context = super().get_context_data(**kwargs)
        context['category'] = self.c
        context['thread'] = self.t
        context['post'] = self.p
        return context

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update({'category_slug': self.kwargs['category_slug'],
                       'thread': self.t,
                       'post': self.p})
        return kwargs

    def form_valid(self, form):
        "Handle thread and 1st post creation in the db"
        # Edit thread title if indeed the first post
        if self.p == self.t.posts.first():
            self.t.title = form.cleaned_data['title']
            self.t.icon = form.cleaned_data['icon']
            self.t.save()
        form.instance.modified = datetime.datetime.now()
        return super().form_valid(form)

    def get_success_url(self):
        self.kwargs.pop('pk')  # remove useless pk
        self.kwargs['thread_slug'] = self.t.slug
        post_page = self.object.position//PostView.paginate_by + 1
        return (reverse_lazy('forum:thread', kwargs=self.kwargs)
                + '?page=' + str(post_page) + '#' + str(self.object.pk))

class DeleteThread(LoginRequiredMixin, View):

    def post(self, request, *args, **kwargs):
        t = Thread.objects.get(pk=self.kwargs['pk'])
        if t.author != self.request.user:
            return HttpResponseForbidden
        elif not t.personal:
            return HttpResponseForbidden
        else:
            t.visible = False
            t.save()
            return HttpResponseRedirect(reverse('forum:category',
                kwargs={'category_slug': t.category}))

class PreviewView(LoginRequiredMixin, DetailView):
    model = Preview

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        self.object.delete()  # Now the object is loaded, delete it
        return self.render_to_response(context)

class ThreadCessionView(LoginRequiredMixin, DetailView):

    def dispatch(self, request, *args, **kwargs):
        self.t = Thread.objects.get(
                    slug=self.kwargs['thread_slug'],
                    category__slug=self.kwargs['category_slug'])
        if self.t.author != self.request.user:
            return HttpResponseForbidden()
        return super().dispatch(request, *args, **kwargs)

    def get_object(self):
        return ThreadCession.objects.get(thread=self.t)

### Poll Views ###
@login_required
def NewPoll(request, category_slug):
    c = Category.objects.get(slug=category_slug)
    thread_form = PollThreadForm(prefix="thread")
    question_form = QuestionForm(prefix="question")
    choices_formset = ChoicesFormSet(instance=PollQuestion())
    formset_helper = FormSetHelper()

    if request.method == 'POST':
        if "preview" in request.POST:
            return get_preview(request.POST['thread-content_plain'])
        else:
            thread_form = PollThreadForm(request.POST, prefix="thread")
            question_form = QuestionForm(request.POST, prefix="question")
            choices_formset = ChoicesFormSet(request.POST)
            if (thread_form.is_valid() and question_form.is_valid()
                    and choices_formset.is_valid()):
                # Create the thread
                t = Thread.objects.create(
                    title=thread_form.cleaned_data['title'],
                    icon=thread_form.cleaned_data['icon'],
                    author=request.user,
                    category=c)
                # Complete the post and save it
                thread_form.instance.thread = t
                thread_form.instance.author = request.user
                p = thread_form.save()
                request.user.postsReadCaret.add(p)
                # Complete the poll and save it
                question_form.instance.thread = t
                question = question_form.save()
                choices_formset = ChoicesFormSet(request.POST,
                                                 instance=question)
                if choices_formset.is_valid():
                    choices_formset.save()
                    return HttpResponseRedirect(reverse(
                        'forum:category',
                        kwargs={'category_slug': category_slug}))

    return render(request, 'forum/new_poll.html', {
        'question_form': question_form,
        'thread_form': thread_form,
        'choices_formset': choices_formset,
        'formset_helper': formset_helper,
        'category_slug': category_slug,
        'category': c,
    })

@login_required
def VotePoll(request, category_slug, thread_slug):
    thread = Thread.objects.get(slug=thread_slug,
                                category__slug=category_slug)
    question = thread.question

    if request.method == 'POST':
        if request.user not in question.voters.all():
            choice = question.choices.get(
                choice_text=request.POST['choice_text'])
            choice.votes += 1
            question.voters.add(request.user)
            choice.save()
            question.save()
        return HttpResponseRedirect(reverse(
            'forum:thread', kwargs={'category_slug': category_slug,
                                    'thread_slug': thread_slug}))

### Search View ###
class SearchView(LoginRequiredMixin, ThreadStatusMixin, ListView):
    paginate_by = 30
    template_name = 'forum/search_results.html'

    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        self.query = self.request.GET['q']
        cls = Thread
        if not self.query:  # An empty string was submitted
            return
        elif re.findall(r'^user:', self.query):
            entry_query = get_query(self.query[5:], ['author__username'])
        elif re.findall(r'^post:', self.query):
            cls = Post
            entry_query = get_query(self.query[5:], ['content_plain'])
        else:
            entry_query = get_query(self.query, ['title'])
        return cls.objects.filter(entry_query)

    def get_context_data(self, **kwargs):
        model = self.object_list.model._meta.model_name
        if model == 'thread':
            context = super().get_context_data(**kwargs)
        else:
            context = ListView.get_context_data(self, **kwargs)
        context['model'] = model
        context['query'] = self.query
        context['query_url'] = 'q=' + self.query + '&'
        return context
<commit_msg>Now personal flag properly works with polls<commit_after>from django.views.generic import View, ListView, CreateView, UpdateView,\
    DetailView
from django.core.urlresolvers import reverse_lazy, reverse
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.core.cache import cache

import re
import datetime
from braces.views import LoginRequiredMixin

from .models import Category, Thread, Post, Preview, PollQuestion, \
    ThreadCession
from .forms import ThreadForm, PostForm, PollThreadForm, QuestionForm, \
    ChoicesFormSet, FormSetHelper
from .util import get_query

### Helpers ###
def get_preview(content):
    "Redirect to post preview"
    p = Preview.objects.create(content_plain=content)
    return HttpResponseRedirect(reverse('forum:preview', kwargs={'pk': p.pk}))

class ThreadStatusMixin(object):
    "Populate thread status and readCaret where needed"

    def get_context_data(self, **kwargs):

        def get_post_page(post):
            return  post.position // PostView.paginate_by + 1

        context = super().get_context_data(**kwargs)
        user = self.request.user
        readCaret = cache.get("user/{}/readCaret".format(user.pk))
        if not readCaret:
            readCaret = user.postsReadCaret.all()
            cache.set("user/{}/readCaret".format(user.pk),
                  readCaret, None)
        for t in context['object_list']:
            contributors = cache.get("thread/{}/contributors".format(t.pk))
            if not contributors:  # caches thread's contributors
                contributors = t.contributors.all()
                cache.set("thread/{}/contributors".format(t.pk),
                  contributors, None)
            # Get latest_post from cache or create it
            latest_post = cache.get("thread/{}/latest_post".format(t.pk))
            if not latest_post:
                latest_post = t.latest_post
                cache.set("thread/{}/latest_post".format(t.pk),
                          latest_post, None)
            uptodate_caret = latest_post in readCaret
            if user in contributors and uptodate_caret:
                status = "added"
            elif user in contributors:
                status = "added+on"
                try:
                    t.readCaret = readCaret.get(thread=t)
                    t.readCaret.page = get_post_page(t.readCaret)
                except ObjectDoesNotExist:
                    t.readCaret = "not_visited"
            elif uptodate_caret:
                status = "off"
            else:
                status = "on"
                try:
                    t.readCaret = readCaret.get(thread=t)
                    t.readCaret.page = get_post_page(t.readCaret)
                except ObjectDoesNotExist:
                    t.readCaret = "not_visited"
            t.status = 'img/{}.png'.format(status)
        return context

class PreviewPostMixin(object):
    def post(self, request, *args, **kwargs):
        if "preview" in request.POST:
            return get_preview(request.POST['content_plain'])
        else:
            return super().post(request, *args, **kwargs)

### Main Forum Views ###
class TopView(LoginRequiredMixin, ListView):
    model = Category

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['readCaret'] = self.request.user.postsReadCaret.all()
        return context

class ThreadView(LoginRequiredMixin, ThreadStatusMixin, ListView):
    paginate_by = 30

    def get_queryset(self):
        "Return threads of the current category ordered by latest post"
        self.c = Category.objects.get(slug=self.kwargs['category_slug'])
        return self.c.threads.select_related('author', 'question')\
                             .filter(visible=True)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['category'] = self.c
        return context

class PostView(LoginRequiredMixin, ListView):
    paginate_by = 30

    def dispatch(self, request, *args, **kwargs):
        c_slug = self.kwargs['category_slug']
        t_slug = self.kwargs['thread_slug']
        self.t = Thread.objects.get(slug=t_slug,
                                    category__slug=c_slug)
        # 403 if the thread has been removed
        if not self.t.visible:
            return HttpResponseForbidden()
        self.t.viewCount += 1  # Increment views
        self.t.save()
        # Handle user read caret
        p = self.t.latest_post
        try:
            caret = self.request.user.postsReadCaret.get(thread=self.t)
        except:
            caret = False
        if caret != p:
            self.request.user.postsReadCaret.remove(caret)
            self.request.user.postsReadCaret.add(p)
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        "Return list of posts given thread and category slugs"
        return self.t.posts.all()

    def get_context_data(self, **kwargs):
        "Pass thread from url to context"
        context = super().get_context_data(**kwargs)
        context['thread'] = self.t
        return context

### Thread and Post creation and edit ###
class NewThread(LoginRequiredMixin, PreviewPostMixin, CreateView):
    form_class = ThreadForm
    template_name = 'forum/new_thread.html'

    def dispatch(self, request, *args, **kwargs):
        self.c = Category.objects.get(slug=self.kwargs['category_slug'])
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        "Pass Category from url to context"
        context = super().get_context_data(**kwargs)
        context['category'] = self.c
        return context

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update({'category_slug': self.kwargs['category_slug']})
        return kwargs

    def form_valid(self, form):
        "Handle thread and 1st post creation in the db"
        # Create the thread
        t = Thread.objects.create(
            title=form.cleaned_data['title'],
            icon=form.cleaned_data['icon'],
            author=self.request.user,
            category=self.c,
            personal=form.cleaned_data['personal'])
        # Complete the post and save it
        form.instance.thread = t
        form.instance.thread.category.postCount += 1  # Increment category
        form.instance.thread.category.save()          # post counter
        form.instance.author = self.request.user
        p = form.save()
        self.request.user.postsReadCaret.add(p)
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse_lazy('forum:category', kwargs=self.kwargs)

class NewPost(LoginRequiredMixin, PreviewPostMixin, CreateView):
    form_class = PostForm
    template_name = 'forum/new_post.html'

    def dispatch(self, request, *args, **kwargs):
        self.t = Thread.objects.get(
            slug=self.kwargs['thread_slug'],
            category__slug=self.kwargs['category_slug'])
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        "Pass category and thread from url to context"
        context = super().get_context_data(**kwargs)
        context['category'] = self.t.category
        context['thread'] = self.t
        context['history'] = Post.objects.filter(
            thread=self.t).order_by('-pk')[:10]
        return context

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update({'category_slug': self.kwargs['category_slug'],
                       'thread': self.t})
        return kwargs

    def form_valid(self, form):
        "Handle post creation in the db"
        # Update category and thread
        self.t.category.postCount += 1
        self.t.category.save()
        # Update remaining form fields
        form.instance.thread = self.t
        form.instance.author = self.request.user
        return super().form_valid(form)

    def get_success_url(self):
        return (reverse_lazy('forum:thread', kwargs=self.kwargs)
                + '?page=last#' + str(self.object.pk))

class QuotePost(NewPost):
    """Quote the content of another post"""

    def dispatch(self, request, *args, **kwargs):
        self.p = Post.objects.get(pk=self.kwargs['pk'])
        self.t = self.p.thread
        return super().dispatch(request, *args, **kwargs)

    def get_initial(self):
        "Pass quoted post content as initial data for form"
        initial = super().get_initial()
        text = "[quote][b]{:s} a dit :[/b]\n{:s}[/quote]".format(
            self.p.author.username, self.p.content_plain)
        initial['content_plain'] = text
        return initial

class EditPost(LoginRequiredMixin, PreviewPostMixin, UpdateView):
    form_class = ThreadForm
    model = Post
    template_name = 'forum/edit.html'

    def dispatch(self, request, *args, **kwargs):
        "Get the right post and thread"
        self.p = Post.objects.get(pk=self.kwargs['pk'])
        if self.p.author != self.request.user:
            return HttpResponseForbidden()
        self.t = self.p.thread
        self.c = self.t.category
        return super().dispatch(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        if "cede" in request.POST:
            ThreadCession.objects.get_or_create(thread=self.t)
            return HttpResponseRedirect(
                reverse('forum:cession',
                        kwargs={'category_slug': self.c.slug,
                                'thread_slug': self.t.slug}))
        else:
            return super().post(request, *args, **kwargs)

    def get_initial(self):
        "Pass initial data to form"
        initial = super().get_initial()
        initial['title'] = self.t.title
        initial['icon'] = self.t.icon[4:][:-4]
        return initial

    def get_context_data(self, **kwargs):
        "Pass category and thread from url to context"
        context = super().get_context_data(**kwargs)
        context['category'] = self.c
        context['thread'] = self.t
        context['post'] = self.p
        return context

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs.update({'category_slug': self.kwargs['category_slug'],
                       'thread': self.t,
                       'post': self.p})
        return kwargs

    def form_valid(self, form):
        "Handle thread and 1st post creation in the db"
        # Edit thread title if indeed the first post
        if self.p == self.t.posts.first():
            self.t.title = form.cleaned_data['title']
            self.t.icon = form.cleaned_data['icon']
            self.t.save()
        form.instance.modified = datetime.datetime.now()
        return super().form_valid(form)

    def get_success_url(self):
        self.kwargs.pop('pk')  # remove useless pk
        self.kwargs['thread_slug'] = self.t.slug
        post_page = self.object.position//PostView.paginate_by + 1
        return (reverse_lazy('forum:thread', kwargs=self.kwargs)
                + '?page=' + str(post_page) + '#' + str(self.object.pk))

class DeleteThread(LoginRequiredMixin, View):

    def post(self, request, *args, **kwargs):
        t = Thread.objects.get(pk=self.kwargs['pk'])
        if t.author != self.request.user:
            return HttpResponseForbidden
        elif not t.personal:
            return HttpResponseForbidden
        else:
            t.visible = False
            t.save()
            return HttpResponseRedirect(reverse('forum:category',
                kwargs={'category_slug': t.category}))

class PreviewView(LoginRequiredMixin, DetailView):
    model = Preview

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        self.object.delete()  # Now the object is loaded, delete it
        return self.render_to_response(context)

class ThreadCessionView(LoginRequiredMixin, DetailView):

    def dispatch(self, request, *args, **kwargs):
        self.t = Thread.objects.get(
                    slug=self.kwargs['thread_slug'],
                    category__slug=self.kwargs['category_slug'])
        if self.t.author != self.request.user:
            return HttpResponseForbidden()
        return super().dispatch(request, *args, **kwargs)

    def get_object(self):
        return ThreadCession.objects.get(thread=self.t)

### Poll Views ###
@login_required
def NewPoll(request, category_slug):
    c = Category.objects.get(slug=category_slug)
    thread_form = PollThreadForm(prefix="thread")
    question_form = QuestionForm(prefix="question")
    choices_formset = ChoicesFormSet(instance=PollQuestion())
    formset_helper = FormSetHelper()

    if request.method == 'POST':
        if "preview" in request.POST:
            return get_preview(request.POST['thread-content_plain'])
        else:
            thread_form = PollThreadForm(request.POST, prefix="thread")
            question_form = QuestionForm(request.POST, prefix="question")
            choices_formset = ChoicesFormSet(request.POST)
            if (thread_form.is_valid() and question_form.is_valid()
                    and choices_formset.is_valid()):
                # Create the thread
                t = Thread.objects.create(
                    title=thread_form.cleaned_data['title'],
                    icon=thread_form.cleaned_data['icon'],
                    author=request.user,
                    category=c,
                    personal=thread_form.cleaned_data['personal'])
                # Complete the post and save it
                thread_form.instance.thread = t
                thread_form.instance.author = request.user
                p = thread_form.save()
                request.user.postsReadCaret.add(p)
                # Complete the poll and save it
                question_form.instance.thread = t
                question = question_form.save()
                choices_formset = ChoicesFormSet(request.POST,
                                                 instance=question)
                if choices_formset.is_valid():
                    choices_formset.save()
                    return HttpResponseRedirect(reverse(
                        'forum:category',
                        kwargs={'category_slug': category_slug}))

    return render(request, 'forum/new_poll.html', {
        'question_form': question_form,
        'thread_form': thread_form,
        'choices_formset': choices_formset,
        'formset_helper': formset_helper,
        'category_slug': category_slug,
        'category': c,
    })

@login_required
def VotePoll(request, category_slug, thread_slug):
    thread = Thread.objects.get(slug=thread_slug,
                                category__slug=category_slug)
    question = thread.question

    if request.method == 'POST':
        if request.user not in question.voters.all():
            choice = question.choices.get(
                choice_text=request.POST['choice_text'])
            choice.votes += 1
            question.voters.add(request.user)
            choice.save()
            question.save()
        return HttpResponseRedirect(reverse(
            'forum:thread', kwargs={'category_slug': category_slug,
                                    'thread_slug': thread_slug}))

### Search View ###
class SearchView(LoginRequiredMixin, ThreadStatusMixin, ListView):
    paginate_by = 30
    template_name = 'forum/search_results.html'

    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def get_queryset(self):
        self.query = self.request.GET['q']
        cls = Thread
        if not self.query:  # An empty string was submitted
            return
        elif re.findall(r'^user:', self.query):
            entry_query = get_query(self.query[5:], ['author__username'])
        elif re.findall(r'^post:', self.query):
            cls = Post
            entry_query = get_query(self.query[5:], ['content_plain'])
        else:
            entry_query = get_query(self.query, ['title'])
        return cls.objects.filter(entry_query)

    def get_context_data(self, **kwargs):
        model = self.object_list.model._meta.model_name
        if model == 'thread':
            context = super().get_context_data(**kwargs)
        else:
            context = ListView.get_context_data(self, **kwargs)
        context['model'] = model
        context['query'] = self.query
        context['query_url'] = 'q=' + self.query + '&'
        return context
<|endoftext|>


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

import re
import sys
import argparse

def add_gene_name(result_tmp_file, anno_file, output_file):
    result_tmp_data = read_TSV(result_tmp_file)

    gene_name_dict = get_gene_name_dict(anno_file)

    result_tmp_data_with_gene_name = []
    for line_list in result_tmp_data:
        gene_name_1 = sorted(gene_name_dict.get('_'.join(line_list[1:3]), [None]))
        gene_name_2 = sorted(gene_name_dict.get('_'.join(line_list[4:6]), [None]))

        if (gene_name_1 == [None]) or (gene_name_2 == [None]):
            isIntragenic = 'NA'
        else:
            if len(gene_name_1) + len(gene_name_2) > len(set(gene_name_1 + gene_name_2)):
                isIntragenic = '1'
                gene_name_1 = gene_name_2 = list(set(gene_name_1) & set(gene_name_2))
            else:
                isIntragenic = '0'

        result_tmp_data_with_gene_name.append(line_list + [','.join(gene_name_1), ','.join(gene_name_2), isIntragenic])

    write_TSV(result_tmp_data_with_gene_name, output_file)

def get_gene_name_dict(anno_file):
    # read annotation data
    with open(anno_file) as data_reader:
        anno_raw_data = data_reader.read()

    # parse gene name
    chrm_exon_gene_data = list(set(re.findall('(chr[^\t]+)\t.*exon\t([0-9]+)\t([0-9]+).*gene_name "([^;]+)";', anno_raw_data)))

    # release memory
    del anno_raw_data

    chrm_exon_gene_data_sep = map(lambda line: (line[0], line[1], line[3]), chrm_exon_gene_data) + map(lambda line: (line[0], line[2], line[3]), chrm_exon_gene_data)
    chrm_exon_gene_data_sep = list(set(chrm_exon_gene_data_sep))

    # generating gene_name_dict
    gene_name_dict = {}
    for line in chrm_exon_gene_data_sep:
        gene_key = '_'.join(line[:2])
        gene_name = line[2]
        if gene_name_dict.has_key(gene_key):
            gene_name_dict[gene_key].append(gene_name)
        else:
            gene_name_dict[gene_key] = [gene_name]

    return gene_name_dict

def read_TSV(tsv_file, read_from_string=False):
    if read_from_string:
        tsv_data_lines = tsv_file.rstrip('\n').split('\n')
        tsv_data_list = [line.split('\t') for line in tsv_data_lines]
        return tsv_data_list
    else:
        with open(tsv_file) as data_reader:
            tsv_data_list = [line.rstrip('\n').split('\t') for line in data_reader]
        return tsv_data_list

def write_TSV(result, out_file="result.txt", write_to_string=False):
    if write_to_string:
        result_tsv = '\n'.join(['\t'.join(line) for line in result])
        return result_tsv
    else:
        with open(out_file, 'w') as data_writer:
            for line in result:
                print >> data_writer, '\t'.join(map(str, line))

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-tmp", "--result_tmp_file", dest="result_tmp_file", help="[Project].result.tmp")
    parser.add_argument('-g', '--gene_annotation', dest="gene_anno", help="Assign custom gene annotation GTF file.")
    parser.add_argument("-o", "--output", dest="output", help="The output filename.")
    args = parser.parse_args()

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit()

    add_gene_name(args.result_tmp_file, args.gene_anno, args.output)

<commit_msg>bugfix: get_gene_name.py: fix default value for non-annotated junc-sites<commit_after>#! /usr/bin/env python2

import re
import sys
import argparse

def add_gene_name(result_tmp_file, anno_file, output_file):
    result_tmp_data = read_TSV(result_tmp_file)

    gene_name_dict = get_gene_name_dict(anno_file)

    result_tmp_data_with_gene_name = []
    for line_list in result_tmp_data:
        gene_name_1 = sorted(gene_name_dict.get('_'.join(line_list[1:3]), []))
        gene_name_2 = sorted(gene_name_dict.get('_'.join(line_list[4:6]), []))

        if (gene_name_1 == []) or (gene_name_2 == []):
            isIntragenic = 'NA'
        else:
            if len(gene_name_1) + len(gene_name_2) > len(set(gene_name_1 + gene_name_2)):
                isIntragenic = '1'
                gene_name_1 = gene_name_2 = list(set(gene_name_1) & set(gene_name_2))
            else:
                isIntragenic = '0'

        result_tmp_data_with_gene_name.append(line_list + [','.join(gene_name_1), ','.join(gene_name_2), isIntragenic])

    write_TSV(result_tmp_data_with_gene_name, output_file)

def get_gene_name_dict(anno_file):
    # read annotation data
    with open(anno_file) as data_reader:
        anno_raw_data = data_reader.read()

    # parse gene name
    chrm_exon_gene_data = list(set(re.findall('(chr[^\t]+)\t.*exon\t([0-9]+)\t([0-9]+).*gene_name "([^;]+)";', anno_raw_data)))

    # release memory
    del anno_raw_data

    chrm_exon_gene_data_sep = map(lambda line: (line[0], line[1], line[3]), chrm_exon_gene_data) + map(lambda line: (line[0], line[2], line[3]), chrm_exon_gene_data)
    chrm_exon_gene_data_sep = list(set(chrm_exon_gene_data_sep))

    # generating gene_name_dict
    gene_name_dict = {}
    for line in chrm_exon_gene_data_sep:
        gene_key = '_'.join(line[:2])
        gene_name = line[2]
        if gene_name_dict.has_key(gene_key):
            gene_name_dict[gene_key].append(gene_name)
        else:
            gene_name_dict[gene_key] = [gene_name]

    return gene_name_dict

def read_TSV(tsv_file, read_from_string=False):
    if read_from_string:
        tsv_data_lines = tsv_file.rstrip('\n').split('\n')
        tsv_data_list = [line.split('\t') for line in tsv_data_lines]
        return tsv_data_list
    else:
        with open(tsv_file) as data_reader:
            tsv_data_list = [line.rstrip('\n').split('\t') for line in data_reader]
        return tsv_data_list

def write_TSV(result, out_file="result.txt", write_to_string=False):
    if write_to_string:
        result_tsv = '\n'.join(['\t'.join(line) for line in result])
        return result_tsv
    else:
        with open(out_file, 'w') as data_writer:
            for line in result:
                print >> data_writer, '\t'.join(map(str, line))

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-tmp", "--result_tmp_file", dest="result_tmp_file", help="[Project].result.tmp")
    parser.add_argument('-g', '--gene_annotation', dest="gene_anno", help="Assign custom gene annotation GTF file.")
    parser.add_argument("-o", "--output", dest="output", help="The output filename.")
    args = parser.parse_args()

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit()

    add_gene_name(args.result_tmp_file, args.gene_anno, args.output)

<|endoftext|>


<commit_before><commit_msg>added option to include failure reason<commit_after><|endoftext|>


<commit_before>from django.conf.urls import patterns, url

from project import views

urlpatterns = patterns('',
    url(r'^$', views.ProjectListView.as_view(), name='project-list'),
    url(r'categories/$', views.CategoryList.as_view(), name='category-list'),
    url(r'(?P<slug>[-_\w]+)/$', views.CategoryDetail.as_view(), name='category-detail'),
    url(r'^create/$', views.ProjectCreateView.as_view(), name='project-create'),
    url(r'(?P<user_id>\w+)/(?P<slug>[-_\w]+)/add/user/$', views.ProjectAddUserUpdateView.as_view(), name='project-add-user'),
    url(r'(?P<user_id>\w+)/(?P<slug>[-_\w]+)/$', views.ProjectView.as_view(), name='project-detail'),
    url(r'(?P<user_id>\w+)/$', views.UserProjectListView.as_view(), name='user-project-list'),
)
<commit_msg>Urls fix for project<commit_after>from django.conf.urls import patterns, url

from project import views

urlpatterns = patterns('',
    url(r'^$', views.ProjectListView.as_view(), name='project-list'),
    url(r'categories/$', views.CategoryList.as_view(), name='category-list'),
    url(r'^create/$', views.ProjectCreateView.as_view(), name='project-create'),
    url(r'(?P<slug>[-_\w]+)/$', views.CategoryDetail.as_view(), name='category-detail'),
    url(r'(?P<user_id>\w+)/(?P<slug>[-_\w]+)/add/user/$', views.ProjectAddUserUpdateView.as_view(), name='project-add-user'),
    url(r'(?P<user_id>\w+)/(?P<slug>[-_\w]+)/$', views.ProjectView.as_view(), name='project-detail'),
    url(r'(?P<user_id>\w+)/$', views.UserProjectListView.as_view(), name='user-project-list'),
)
<|endoftext|>


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

# Copyright 2014 Tomo Krajina
#
# 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 inspect as mod_inspect
import datetime as mod_datetime

from . import utils as mod_utils

class GPXFieldTypeConverter:
    def __init__(self, from_string, to_string):
        self.from_string = from_string
        self.to_string = to_string

def parse_time(string):
    from . import gpx as mod_gpx
    if not string:
        return None
    if 'T' in string:
        string = string.replace('T', ' ')
    if 'Z' in string:
        string = string.replace('Z', '')
    for date_format in mod_gpx.DATE_FORMATS:
        try:
            return mod_datetime.datetime.strptime(string, date_format)
        except ValueError as e:
            pass
    raise GPXException('Invalid time: %s' % string)

# ----------------------------------------------------------------------------------------------------
# Type converters used to convert from/to the string in the XML:
# ----------------------------------------------------------------------------------------------------

class FloatConverter:
    def __init__(self):
        self.from_string = lambda string : None if string is None else float(string.strip())
        self.to_string =   lambda flt    : str(flt)

class IntConverter:
    def __init__(self):
        self.from_string = lambda string : None if string is None else int(string.strip())
        self.to_string =   lambda flt    : str(flt)

class TimeConverter:
    def from_string(self, string):
        from . import gpx as mod_gpx
        if not string:
            return None
        if 'T' in string:
            string = string.replace('T', ' ')
        if 'Z' in string:
            string = string.replace('Z', '')
        for date_format in mod_gpx.DATE_FORMATS:
            try:
                return mod_datetime.datetime.strptime(string, date_format)
            except ValueError as e:
                pass
        return None
    def to_string(self, time):
        from . import gpx as mod_gpx
        return time.strftime(mod_gpx.DATE_FORMAT) if time else None

INT_TYPE = IntConverter()
FLOAT_TYPE = FloatConverter()
TIME_TYPE = TimeConverter()

# ----------------------------------------------------------------------------------------------------
# Field converters:
# ----------------------------------------------------------------------------------------------------

class AbstractGPXField:
    def __init__(self, attribute_field=None, is_list=None):
        self.attribute_field = attribute_field
        self.is_list = is_list
        self.attribute = False

    def from_xml(self, parser, node, version):
        raise Exception('Not implemented')

    def to_xml(self, value, version):
        raise Exception('Not implemented')

class GPXField(AbstractGPXField):
    """
    Used for to (de)serialize fields with simple field<->xml_tag mapping.
    """
    def __init__(self, name, tag=None, attribute=None, type=None, possible=None, mandatory=None):
        AbstractGPXField.__init__(self)
        self.name = name
        if tag and attribute:
            raise GPXException('Only tag *or* attribute may be given!')
        if attribute:
            self.tag = None
            self.attribute = name if attribute is True else attribute
        elif tag:
            self.tag = name if tag is True else tag
            self.attribute = None
        else:
            self.tag = name
            self.attribute = None
        self.type_converter = type
        self.possible = possible
        self.mandatory = mandatory

    def from_xml(self, parser, node, version):
        if self.attribute:
            result = parser.get_node_attribute(node, self.attribute)
        else:
            __node = parser.get_first_child(node, self.tag)
            result = parser.get_node_data(__node)

        if result is None:
            if self.mandatory:
                from . import gpx as mod_gpx
                raise mod_gpx.GPXException('%s is mandatory in %s' % (self.name, self.tag))
            return None

        if self.type_converter:
            try:
                result = self.type_converter.from_string(result)
            except Exception as e:
                from . import gpx as mod_gpx
                raise mod_gpx.GPXException('Invalid value for <%s>... %s (%s)' % (self.tag, result, e))

        if self.possible:
            if not (result in self.possible):
                from . import gpx as mod_gpx
                raise mod_gpx.GPXException('Invalid value "%s", possible: %s' % (result, self.possible))

        return result

    def to_xml(self, value, version):
        if self.attribute:
            return '%s="%s"' % (self.attribute, value)
        else:
            if self.type_converter:
                value = self.type_converter.to_string(value)
            if isinstance(self.tag, list) or isinstance(self.tag, tuple):
                raise Exception('Not yet implemented')
            return mod_utils.to_xml(self.tag, content=value)

class GPXComplexField(AbstractGPXField):
    def __init__(self, name, classs, tag=None, is_list=None):
        AbstractGPXField.__init__(self, is_list=is_list)
        self.name = name
        self.tag = tag or name
        self.classs = classs

    def from_xml(self, parser, node, version):
        if self.is_list:
            result = []
            for child_node in parser.get_children(node):
                if parser.get_node_name(child_node) == self.tag:
                    result.append(gpx_fields_from_xml(self.classs, parser, child_node, version))
            return result
        else:
            __node = parser.get_first_child(node, self.tag)
            if __node is None:
                return None
            return gpx_fields_from_xml(self.classs, parser, __node, version)

    def to_xml(self, value, version):
        if self.is_list:
            result = ''
            for obj in value:
                result += gpx_fields_to_xml(obj, self.tag, version)
            return result
        else:
            return gpx_fields_to_xml(value, self.tag, version)

class GPXEmailField(AbstractGPXField):
    """
    Converts GPX1.1 email tag group from/to string.
    """
    def __init__(self, name, tag=None):
        self.attribute = False
        self.is_list = False
        self.name = name
        self.tag = tag or name

    def from_xml(self, parser, node, version):
        email_node = parser.get_first_child(node, self.tag)
        email_id = parser.get_node_attribute(email_node, 'id')
        email_domain = parser.get_node_attribute(email_node, 'domain')
        return '%s@%s' % (email_id, email_domain)

    def to_xml(self, value, version):
        if '@' in value:
            pos = value.find('@')
            email_id = value[:pos]
            email_domain = value[pos+1:]
        else:
            email_id = value
            email_domain = 'unknown'
        return '\n<%s id="%s" domain="%s" />' % (self.tag, email_id, email_domain)

# ----------------------------------------------------------------------------------------------------
# Utility methods:
# ----------------------------------------------------------------------------------------------------

def gpx_fields_to_xml(instance, tag, version, custom_attributes=None):
    fields = instance.gpx_10_fields
    if version == '1.1':
        fields = instance.gpx_11_fields

    tag_open = bool(tag)
    body = ''
    if tag:
        body = '\n<' + tag
        if custom_attributes:
            for key, value in custom_attributes.items():
                body += ' %s="%s"' % (key, mod_utils.make_str(value))

    for gpx_field in fields:
        if isinstance(gpx_field, str):
            if gpx_field[0] == '/':
                if tag_open:
                    body += '>'
                    tag_open = False
                body += '<%s>' % gpx_field
            else:
                body += '\n<%s' % gpx_field
                tag_open = True
        else:
            value = getattr(instance, gpx_field.name)
            if gpx_field.attribute:
                body += ' %s="%s"' % (gpx_field.attribute, mod_utils.make_str(value))
            elif value:
                if tag_open:
                    body += '>'
                    tag_open = False
                body += gpx_field.to_xml(value, version)

    if tag:
        body += '</' + tag + '>'

    return body

def gpx_fields_from_xml(class_or_instance, parser, node, version):
    if mod_inspect.isclass(class_or_instance):
        result = class_or_instance()
    else:
        result = class_or_instance

    fields = result.gpx_10_fields
    if version == '1.1':
        fields = result.gpx_11_fields

    node_path = [ node ]

    for gpx_field in fields:
        current_node = node_path[-1]
        if isinstance (gpx_field, str):
            if gpx_field.startswith('/'):
                node_path.pop()
            else:
                if not current_node:
                    node_path.append(None)
                else:
                    node_path.append(parser.get_first_child(current_node, gpx_field))
        else:
            if current_node:
                value = gpx_field.from_xml(parser, current_node, version)
                setattr(result, gpx_field.name, value)
            elif gpx_field.attribute:
                value = gpx_field.from_xml(parser, node, version)
                setattr(result, gpx_field.name, value)

    return result

def gpx_fields_fill_default_values(classs):
    """
    Will fill the default values for this class. Instances will inherit those
    values so we don't need to fill default values for every instance.

    This method will also fill the attribute gpx_field_names with a list of
    gpx field names. This can be used
    """
    fields = classs.gpx_10_fields + classs.gpx_11_fields

    gpx_field_names = []

    for field in fields:
        if not isinstance(field, str):
            if field.is_list:
                value = []
            else:
                value = None
            setattr(classs, field.name, value)
            gpx_field_names.append(field.name)
    print('%s -> %s' % (classs, gpx_field_names))
    setattr(classs, 'gpx_field_names', gpx_field_names)
    setattr(classs, '__slots__', gpx_field_names)
<commit_msg>Bounds fix<commit_after># -*- coding: utf-8 -*-

# Copyright 2014 Tomo Krajina
#
# 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 inspect as mod_inspect
import datetime as mod_datetime

from . import utils as mod_utils

class GPXFieldTypeConverter:
    def __init__(self, from_string, to_string):
        self.from_string = from_string
        self.to_string = to_string

def parse_time(string):
    from . import gpx as mod_gpx
    if not string:
        return None
    if 'T' in string:
        string = string.replace('T', ' ')
    if 'Z' in string:
        string = string.replace('Z', '')
    for date_format in mod_gpx.DATE_FORMATS:
        try:
            return mod_datetime.datetime.strptime(string, date_format)
        except ValueError as e:
            pass
    raise GPXException('Invalid time: %s' % string)

# ----------------------------------------------------------------------------------------------------
# Type converters used to convert from/to the string in the XML:
# ----------------------------------------------------------------------------------------------------

class FloatConverter:
    def __init__(self):
        self.from_string = lambda string : None if string is None else float(string.strip())
        self.to_string =   lambda flt    : str(flt)

class IntConverter:
    def __init__(self):
        self.from_string = lambda string : None if string is None else int(string.strip())
        self.to_string =   lambda flt    : str(flt)

class TimeConverter:
    def from_string(self, string):
        from . import gpx as mod_gpx
        if not string:
            return None
        if 'T' in string:
            string = string.replace('T', ' ')
        if 'Z' in string:
            string = string.replace('Z', '')
        for date_format in mod_gpx.DATE_FORMATS:
            try:
                return mod_datetime.datetime.strptime(string, date_format)
            except ValueError as e:
                pass
        return None
    def to_string(self, time):
        from . import gpx as mod_gpx
        return time.strftime(mod_gpx.DATE_FORMAT) if time else None

INT_TYPE = IntConverter()
FLOAT_TYPE = FloatConverter()
TIME_TYPE = TimeConverter()

# ----------------------------------------------------------------------------------------------------
# Field converters:
# ----------------------------------------------------------------------------------------------------

class AbstractGPXField:
    def __init__(self, attribute_field=None, is_list=None):
        self.attribute_field = attribute_field
        self.is_list = is_list
        self.attribute = False

    def from_xml(self, parser, node, version):
        raise Exception('Not implemented')

    def to_xml(self, value, version):
        raise Exception('Not implemented')

class GPXField(AbstractGPXField):
    """
    Used for to (de)serialize fields with simple field<->xml_tag mapping.
    """
    def __init__(self, name, tag=None, attribute=None, type=None, possible=None, mandatory=None):
        AbstractGPXField.__init__(self)
        self.name = name
        if tag and attribute:
            raise GPXException('Only tag *or* attribute may be given!')
        if attribute:
            self.tag = None
            self.attribute = name if attribute is True else attribute
        elif tag:
            self.tag = name if tag is True else tag
            self.attribute = None
        else:
            self.tag = name
            self.attribute = None
        self.type_converter = type
        self.possible = possible
        self.mandatory = mandatory

    def from_xml(self, parser, node, version):
        if self.attribute:
            result = parser.get_node_attribute(node, self.attribute)
        else:
            __node = parser.get_first_child(node, self.tag)
            result = parser.get_node_data(__node)

        if result is None:
            if self.mandatory:
                from . import gpx as mod_gpx
                raise mod_gpx.GPXException('%s is mandatory in %s' % (self.name, self.tag))
            return None

        if self.type_converter:
            try:
                result = self.type_converter.from_string(result)
            except Exception as e:
                from . import gpx as mod_gpx
                raise mod_gpx.GPXException('Invalid value for <%s>... %s (%s)' % (self.tag, result, e))

        if self.possible:
            if not (result in self.possible):
                from . import gpx as mod_gpx
                raise mod_gpx.GPXException('Invalid value "%s", possible: %s' % (result, self.possible))

        return result

    def to_xml(self, value, version):
        if self.attribute:
            return '%s="%s"' % (self.attribute, value)
        else:
            if self.type_converter:
                value = self.type_converter.to_string(value)
            if isinstance(self.tag, list) or isinstance(self.tag, tuple):
                raise Exception('Not yet implemented')
            return mod_utils.to_xml(self.tag, content=value)

class GPXComplexField(AbstractGPXField):
    def __init__(self, name, classs, tag=None, is_list=None):
        AbstractGPXField.__init__(self, is_list=is_list)
        self.name = name
        self.tag = tag or name
        self.classs = classs

    def from_xml(self, parser, node, version):
        if self.is_list:
            result = []
            for child_node in parser.get_children(node):
                if parser.get_node_name(child_node) == self.tag:
                    result.append(gpx_fields_from_xml(self.classs, parser, child_node, version))
            return result
        else:
            __node = parser.get_first_child(node, self.tag)
            if __node is None:
                return None
            return gpx_fields_from_xml(self.classs, parser, __node, version)

    def to_xml(self, value, version):
        if self.is_list:
            result = ''
            for obj in value:
                result += gpx_fields_to_xml(obj, self.tag, version)
            return result
        else:
            return gpx_fields_to_xml(value, self.tag, version)

class GPXEmailField(AbstractGPXField):
    """
    Converts GPX1.1 email tag group from/to string.
    """
    def __init__(self, name, tag=None):
        self.attribute = False
        self.is_list = False
        self.name = name
        self.tag = tag or name

    def from_xml(self, parser, node, version):
        email_node = parser.get_first_child(node, self.tag)
        email_id = parser.get_node_attribute(email_node, 'id')
        email_domain = parser.get_node_attribute(email_node, 'domain')
        return '%s@%s' % (email_id, email_domain)

    def to_xml(self, value, version):
        if '@' in value:
            pos = value.find('@')
            email_id = value[:pos]
            email_domain = value[pos+1:]
        else:
            email_id = value
            email_domain = 'unknown'
        return '\n<%s id="%s" domain="%s" />' % (self.tag, email_id, email_domain)

# ----------------------------------------------------------------------------------------------------
# Utility methods:
# ----------------------------------------------------------------------------------------------------

def gpx_fields_to_xml(instance, tag, version, custom_attributes=None):
    fields = instance.gpx_10_fields
    if version == '1.1':
        fields = instance.gpx_11_fields

    tag_open = bool(tag)
    body = ''
    if tag:
        body = '\n<' + tag
        if custom_attributes:
            for key, value in custom_attributes.items():
                body += ' %s="%s"' % (key, mod_utils.make_str(value))

    for gpx_field in fields:
        if isinstance(gpx_field, str):
            if gpx_field[0] == '/':
                if tag_open:
                    body += '>'
                    tag_open = False
                body += '<%s>' % gpx_field
            else:
                body += '\n<%s' % gpx_field
                tag_open = True
        else:
            value = getattr(instance, gpx_field.name)
            if gpx_field.attribute:
                body += ' %s="%s"' % (gpx_field.attribute, mod_utils.make_str(value))
            elif value:
                if tag_open:
                    body += '>'
                    tag_open = False
                body += gpx_field.to_xml(value, version)

    if tag:
        if tag_open:
            body += '>'
        body += '</' + tag + '>'

    return body

def gpx_fields_from_xml(class_or_instance, parser, node, version):
    if mod_inspect.isclass(class_or_instance):
        result = class_or_instance()
    else:
        result = class_or_instance

    fields = result.gpx_10_fields
    if version == '1.1':
        fields = result.gpx_11_fields

    node_path = [ node ]

    for gpx_field in fields:
        current_node = node_path[-1]
        if isinstance (gpx_field, str):
            if gpx_field.startswith('/'):
                node_path.pop()
            else:
                if not current_node:
                    node_path.append(None)
                else:
                    node_path.append(parser.get_first_child(current_node, gpx_field))
        else:
            if current_node:
                value = gpx_field.from_xml(parser, current_node, version)
                setattr(result, gpx_field.name, value)
            elif gpx_field.attribute:
                value = gpx_field.from_xml(parser, node, version)
                setattr(result, gpx_field.name, value)

    return result

def gpx_fields_fill_default_values(classs):
    """
    Will fill the default values for this class. Instances will inherit those
    values so we don't need to fill default values for every instance.

    This method will also fill the attribute gpx_field_names with a list of
    gpx field names. This can be used
    """
    fields = classs.gpx_10_fields + classs.gpx_11_fields

    gpx_field_names = []

    for field in fields:
        if not isinstance(field, str):
            if field.is_list:
                value = []
            else:
                value = None
            setattr(classs, field.name, value)
            gpx_field_names.append(field.name)
    print('%s -> %s' % (classs, gpx_field_names))
    setattr(classs, 'gpx_field_names', gpx_field_names)
    setattr(classs, '__slots__', gpx_field_names)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from classytags.core import Tag, Options
from cms.utils.compat import DJANGO_1_4
from django import template
from django.core.serializers.json import DjangoJSONEncoder
from django.utils.text import javascript_quote
if DJANGO_1_4:
    from django.utils import simplejson as json
else:
    import json
register = template.Library()

@register.filter
def js(value):
    return json.dumps(value, cls=DjangoJSONEncoder)

@register.filter
def bool(value):
    if value:
        return 'true'
    else:
        return 'false'

class JavascriptString(Tag):
    name = 'javascript_string'

    options = Options(
        blocks=[
            ('end_javascript_string', 'nodelist'),
        ]
    )

    def render_tag(self, context, **kwargs):
        rendered = self.nodelist.render(context)
        return u"'%s'" % javascript_quote(rendered.strip())
register.tag(JavascriptString)<commit_msg>Added template filter "json" which is not vulnerable to XSS attacks<commit_after># -*- coding: utf-8 -*-
import warnings
from classytags.core import Tag, Options
from cms.utils.compat import DJANGO_1_4
from django import template
from django.core.serializers.json import DjangoJSONEncoder
from django.utils.html import conditional_escape
from django.utils.text import javascript_quote
from django.utils.safestring import mark_safe
if DJANGO_1_4:
    from django.utils import simplejson as json
else:
    import json
register = template.Library()

@register.filter
def js(value):
    warnings.warn("The template filter '...|js' is vulnerable to XSS attacks, please use '...|json' instead.",
                  DeprecationWarning, stacklevel=2)
    return json.dumps(value, cls=DjangoJSONEncoder)

class SafeJSONEncoder(DjangoJSONEncoder):
    def _recursive_escape(self, o, esc=conditional_escape):
        if isinstance(o, dict):
            return type(o)((esc(k), self._recursive_escape(v)) for (k, v) in o.iteritems())
        if isinstance(o, (list, tuple)):
            return type(o)(self._recursive_escape(v) for v in o)
        try:
            return type(o)(esc(o))
        except ValueError:
            return esc(o)

    def encode(self, o):
        value = self._recursive_escape(o)
        return super(SafeJSONEncoder, self).encode(value)

@register.filter('json')
def json_filter(value):
    """
    Returns the JSON representation of ``value`` in a safe manner.
    """
    return mark_safe(json.dumps(value, cls=SafeJSONEncoder))

@register.filter
def bool(value):
    if value:
        return 'true'
    else:
        return 'false'

class JavascriptString(Tag):
    name = 'javascript_string'

    options = Options(
        blocks=[
            ('end_javascript_string', 'nodelist'),
        ]
    )

    def render_tag(self, context, **kwargs):
        rendered = self.nodelist.render(context)
        return u"'%s'" % javascript_quote(rendered.strip())
register.tag(JavascriptString)<|endoftext|>


<commit_before>import datetime
from django.db.models import Q
from models.events import Event
from models.events import EventTheme
from models.events import EventAudience

def get_all_events():
	return Event.objects.all()

def get_event_by_id(event_id):
	event = Event.objects.get(id=event_id)
	return event

def get_approved_events(limit=None, order=None, country_code=None, theme=None, past=False):
	"""
	Select all events which are approved and optionally limit and/or order them
	"""

	events = Event.objects.filter(status='APPROVED')
	if not past:
		events = events.filter(end_date__gte=datetime.datetime.now())
	if country_code:
		events = events.filter(country=country_code)
	if order:
		events = events.order_by(order)
	if limit:
		events = events[:limit]

	return events

def get_pending_events(limit=None, order=None, country_code=None, past=False):

	"""
	Select all future or past events which are pending and optionally limit and/or order them
	"""

	events = Event.objects.filter(status='PENDING')
	if not past:
		events = events.filter(end_date__gte=datetime.datetime.now())
	if country_code:
		events = events.filter(country=country_code)
	if order:
		events = events.order_by(order)
	if limit:
		events = events = events[:limit]

	return events

def get_filtered_events(search_filter=None, country_filter=None, theme_filter=None, audience_filter=None):

	"""
	Filter events by given filter
	"""
	filter_args = ()

	# default
	filter_kwargs = {'status': 'APPROVED', 'end_date__gte': datetime.datetime.now(),'start_date__lte': datetime.datetime.now()}

	if search_filter:
		filter_args = (Q(title__icontains=search_filter) | Q(description__icontains=search_filter) | Q(tags__name__icontains=search_filter)
			| Q(organizer__icontains=search_filter) | Q(location__icontains=search_filter),)

	if country_filter:
		filter_kwargs['country'] = country_filter

	if theme_filter:
		filter_kwargs['theme__in'] = theme_filter

	if audience_filter:
		audience = EventAudience.objects.filter()
		filter_kwargs['audience__in'] = audience_filter

	if len(filter_args) > 0:
		events = Event.objects.filter(*filter_args, **filter_kwargs)
	else:
		events = Event.objects.filter(**filter_kwargs)

	return events

def list_themes():
	themes = EventTheme.objects.all()

	return themes<commit_msg>Fix for multiple identical results<commit_after>import datetime
from django.db.models import Q
from models.events import Event
from models.events import EventTheme
from models.events import EventAudience

def get_all_events():
	return Event.objects.all()

def get_event_by_id(event_id):
	event = Event.objects.get(id=event_id)
	return event

def get_approved_events(limit=None, order=None, country_code=None, theme=None, past=False):
	"""
	Select all events which are approved and optionally limit and/or order them
	"""

	events = Event.objects.filter(status='APPROVED')
	if not past:
		events = events.filter(end_date__gte=datetime.datetime.now())
	if country_code:
		events = events.filter(country=country_code)
	if order:
		events = events.order_by(order)
	if limit:
		events = events[:limit]

	return events

def get_pending_events(limit=None, order=None, country_code=None, past=False):

	"""
	Select all future or past events which are pending and optionally limit and/or order them
	"""

	events = Event.objects.filter(status='PENDING')
	if not past:
		events = events.filter(end_date__gte=datetime.datetime.now())
	if country_code:
		events = events.filter(country=country_code)
	if order:
		events = events.order_by(order)
	if limit:
		events = events = events[:limit]

	return events

def get_filtered_events(search_filter=None, country_filter=None, theme_filter=None, audience_filter=None):

	"""
	Filter events by given filter
	"""
	filter_args = ()

	# default
	filter_kwargs = {'status': 'APPROVED', 'end_date__gte': datetime.datetime.now(),'start_date__lte': datetime.datetime.now()}

	if search_filter:
		filter_args = (Q(title__icontains=search_filter) | Q(description__icontains=search_filter) | Q(tags__name__icontains=search_filter)
			| Q(organizer__icontains=search_filter) | Q(location__icontains=search_filter),)

	if country_filter:
		filter_kwargs['country'] = country_filter

	if theme_filter:
		filter_kwargs['theme__in'] = theme_filter

	if audience_filter:
		audience = EventAudience.objects.filter()
		filter_kwargs['audience__in'] = audience_filter

	if len(filter_args) > 0:
		events = Event.objects.filter(*filter_args, **filter_kwargs).distinct()
	else:
		events = Event.objects.filter(**filter_kwargs).distinct()

	return events

def list_themes():
	themes = EventTheme.objects.all()

	return themes<|endoftext|>