<commit_before># Copyright (c) 2015-2017 by the parties listed in the AUTHORS file.
# All rights reserved.  Use of this source code is governed by
# a BSD-style license that can be found in the LICENSE file.

from ..mpi import MPI
from .mpi import MPITestCase

import sys
import os

import numpy as np
import numpy.testing as nt

import scipy.interpolate as si

from ..tod import OpPolyFilter, Interval
from ..tod.tod import *
from ..tod.pointing import *
from ..tod.noise import *
from ..tod.sim_noise import *
from ..tod.sim_det_noise import *
from ..tod.sim_tod import *

from .. import rng as rng

class OpPolyFilterTest(MPITestCase):

    def setUp(self):
        self.outdir = 'toast_test_output'
        if self.comm.rank == 0:
            if not os.path.isdir(self.outdir):
                os.mkdir(self.outdir)

        # Note: self.comm is set by the test infrastructure
        self.worldsize = self.comm.size
        if (self.worldsize >= 2):
            self.groupsize = int( self.worldsize / 2 )
            self.ngroup = 2
        else:
            self.groupsize = 1
            self.ngroup = 1
        self.toastcomm = Comm(world=self.comm, groupsize=self.groupsize)
        self.data = Data(self.toastcomm)

        self.order = 5

        self.dets = ['f1a_apply', 'f1b_apply', 'f2a', 'f2b', 'white', 'high']
        self.fp = {}
        for d in self.dets:
            self.fp[d] = np.array([0.0, 0.0, 1.0, 0.0])

        self.rate = 20.0

        self.rates = {}
        self.fmin = {}
        self.fknee = {}
        self.alpha = {}
        self.NET = {}

        self.rates['f1a_apply'] = self.rate
        self.fmin['f1a_apply'] = 1.0e-5
        self.fknee['f1a_apply'] = 0.15
        self.alpha['f1a_apply'] = 1.0
        self.NET['f1a_apply'] = 10.0

        self.rates['f1b_apply'] = self.rate
        self.fmin['f1b_apply'] = 1.0e-5
        self.fknee['f1b_apply'] = 0.1
        self.alpha['f1b_apply'] = 1.0
        self.NET['f1b_apply'] = 10.0

        self.rates['f2a'] = self.rate
        self.fmin['f2a'] = 1.0e-5
        self.fknee['f2a'] = 0.05
        self.alpha['f2a'] = 1.0
        self.NET['f2a'] = 10.0

        self.rates['f2b'] = self.rate
        self.fmin['f2b'] = 1.0e-5
        self.fknee['f2b'] = 0.001
        self.alpha['f2b'] = 1.0
        self.NET['f2b'] = 10.0

        self.rates['white'] = self.rate
        self.fmin['white'] = 0.0
        self.fknee['white'] = 0.0
        self.alpha['white'] = 1.0
        self.NET['white'] = 10.0

        self.rates['high'] = self.rate
        self.fmin['high'] = 1.0e-5
        self.fknee['high'] = 40.0
        self.alpha['high'] = 2.0
        self.NET['high'] = 10.0

        self.totsamp = 10000

        self.oversample = 2

        nchunk = 10
        chunksize = int(self.totsamp / nchunk)
        chunks = np.ones(nchunk, dtype=np.int64)
        chunks *= chunksize
        remain = self.totsamp - (nchunk * chunksize)
        for r in range(remain):
            chunks[r] += 1

        self.chunksize = chunksize

        # Construct an empty TOD (no pointing needed)

        self.tod = TODHpixSpiral(
            self.toastcomm.comm_group,
            self.fp,
            self.totsamp,
            firsttime=0.0,
            rate=self.rate,
            nside=512,
            sampsizes=chunks)

        # construct an analytic noise model

        self.nse = AnalyticNoise(
            rate=self.rates,
            fmin=self.fmin,
            detectors=self.dets,
            fknee=self.fknee,
            alpha=self.alpha,
            NET=self.NET
        )

        intervals = []
        interval_len = 1000
        for istart in range(0, self.totsamp, interval_len):
            istop = min(istart + interval_len, self.totsamp)
            intervals.append(Interval(
                start=istart/self.rate, stop=istop/self.rate,
                first=istart, last=istop))

        ob = {}
        ob['name'] = 'noisetest-{}'.format(self.toastcomm.group)
        ob['id'] = 0
        ob['tod'] = self.tod
        ob['intervals'] = intervals
        ob['baselines'] = None
        ob['noise'] = self.nse

        self.data.obs.append(ob)

    def test_filter(self):
        start = MPI.Wtime()

        ob = self.data.obs[0]
        tod = ob['tod']
        nse = ob['noise']

        # generate timestreams

        op = OpSimNoise()
        op.exec(self.data)

        # Replace the noise with a polynomial fit

        old_rms = {}

        for det in tod.local_dets:
            cachename = 'noise_{}'.format(det)
            y = tod.cache.reference(cachename)
            x = np.arange(y.size)
            p = np.polyfit(x, y, self.order)
            y[:] = np.polyval(p, x)
            old_rms[det] = np.std(y)

        # Filter timestreams

        op = OpPolyFilter(name='noise', order=self.order, pattern=r'.*apply.*')
        op.exec(self.data)

        stop = MPI.Wtime()
        elapsed = stop - start

        # Ensure all timestreams are zeroed out by the filter.
        # The polynomial basis used in populating the TOD is different
        # than the one filter uses and the basis functions are not
        # strictly orthogonal on a sparse grid so we expect a low level
        # residual.

        for det in tod.local_dets:
            cachename = 'noise_{}'.format(det)
            y = tod.cache.reference(cachename)
            rms = np.std(y)
            old = old_rms[det]
            if rms / old > 1e-6 and 'apply' in det:
                raise RuntimeError('det {} old rms = {}, new rms = {}'
                                   ''.format(det, old, rms))
            if rms / old < 1e-1 and 'apply' not in det:
                raise RuntimeError('det {} old rms = {}, new rms = {}'
                                   ''.format(det, old, rms))

        self.print_in_turns('polyfilter test took {:.3f} s'.format(elapsed))
<commit_msg>Fix off-by-one<commit_after># Copyright (c) 2015-2017 by the parties listed in the AUTHORS file.
# All rights reserved.  Use of this source code is governed by
# a BSD-style license that can be found in the LICENSE file.

from ..mpi import MPI
from .mpi import MPITestCase

import sys
import os

import numpy as np
import numpy.testing as nt

import scipy.interpolate as si

from ..tod import OpPolyFilter, Interval
from ..tod.tod import *
from ..tod.pointing import *
from ..tod.noise import *
from ..tod.sim_noise import *
from ..tod.sim_det_noise import *
from ..tod.sim_tod import *

from .. import rng as rng

class OpPolyFilterTest(MPITestCase):

    def setUp(self):
        self.outdir = 'toast_test_output'
        if self.comm.rank == 0:
            if not os.path.isdir(self.outdir):
                os.mkdir(self.outdir)

        # Note: self.comm is set by the test infrastructure
        self.worldsize = self.comm.size
        if (self.worldsize >= 2):
            self.groupsize = int( self.worldsize / 2 )
            self.ngroup = 2
        else:
            self.groupsize = 1
            self.ngroup = 1
        self.toastcomm = Comm(world=self.comm, groupsize=self.groupsize)
        self.data = Data(self.toastcomm)

        self.order = 5

        self.dets = ['f1a_apply', 'f1b_apply', 'f2a', 'f2b', 'white', 'high']
        self.fp = {}
        for d in self.dets:
            self.fp[d] = np.array([0.0, 0.0, 1.0, 0.0])

        self.rate = 20.0

        self.rates = {}
        self.fmin = {}
        self.fknee = {}
        self.alpha = {}
        self.NET = {}

        self.rates['f1a_apply'] = self.rate
        self.fmin['f1a_apply'] = 1.0e-5
        self.fknee['f1a_apply'] = 0.15
        self.alpha['f1a_apply'] = 1.0
        self.NET['f1a_apply'] = 10.0

        self.rates['f1b_apply'] = self.rate
        self.fmin['f1b_apply'] = 1.0e-5
        self.fknee['f1b_apply'] = 0.1
        self.alpha['f1b_apply'] = 1.0
        self.NET['f1b_apply'] = 10.0

        self.rates['f2a'] = self.rate
        self.fmin['f2a'] = 1.0e-5
        self.fknee['f2a'] = 0.05
        self.alpha['f2a'] = 1.0
        self.NET['f2a'] = 10.0

        self.rates['f2b'] = self.rate
        self.fmin['f2b'] = 1.0e-5
        self.fknee['f2b'] = 0.001
        self.alpha['f2b'] = 1.0
        self.NET['f2b'] = 10.0

        self.rates['white'] = self.rate
        self.fmin['white'] = 0.0
        self.fknee['white'] = 0.0
        self.alpha['white'] = 1.0
        self.NET['white'] = 10.0

        self.rates['high'] = self.rate
        self.fmin['high'] = 1.0e-5
        self.fknee['high'] = 40.0
        self.alpha['high'] = 2.0
        self.NET['high'] = 10.0

        self.totsamp = 10000

        self.oversample = 2

        nchunk = 10
        chunksize = int(self.totsamp / nchunk)
        chunks = np.ones(nchunk, dtype=np.int64)
        chunks *= chunksize
        remain = self.totsamp - (nchunk * chunksize)
        for r in range(remain):
            chunks[r] += 1

        self.chunksize = chunksize

        # Construct an empty TOD (no pointing needed)

        self.tod = TODHpixSpiral(
            self.toastcomm.comm_group,
            self.fp,
            self.totsamp,
            firsttime=0.0,
            rate=self.rate,
            nside=512,
            sampsizes=chunks)

        # construct an analytic noise model

        self.nse = AnalyticNoise(
            rate=self.rates,
            fmin=self.fmin,
            detectors=self.dets,
            fknee=self.fknee,
            alpha=self.alpha,
            NET=self.NET
        )

        intervals = []
        interval_len = 1000
        for istart in range(0, self.totsamp, interval_len):
            istop = min(istart + interval_len, self.totsamp)
            intervals.append(Interval(
                start=istart/self.rate, stop=istop/self.rate,
                first=istart, last=istop-1))

        ob = {}
        ob['name'] = 'noisetest-{}'.format(self.toastcomm.group)
        ob['id'] = 0
        ob['tod'] = self.tod
        ob['intervals'] = intervals
        ob['baselines'] = None
        ob['noise'] = self.nse

        self.data.obs.append(ob)

    def test_filter(self):
        start = MPI.Wtime()

        ob = self.data.obs[0]
        tod = ob['tod']
        nse = ob['noise']

        # generate timestreams

        op = OpSimNoise()
        op.exec(self.data)

        # Replace the noise with a polynomial fit

        old_rms = {}

        for det in tod.local_dets:
            cachename = 'noise_{}'.format(det)
            y = tod.cache.reference(cachename)
            x = np.arange(y.size)
            p = np.polyfit(x, y, self.order)
            y[:] = np.polyval(p, x)
            old_rms[det] = np.std(y)

        # Filter timestreams

        op = OpPolyFilter(name='noise', order=self.order, pattern=r'.*apply.*')
        op.exec(self.data)

        stop = MPI.Wtime()
        elapsed = stop - start

        # Ensure all timestreams are zeroed out by the filter.
        # The polynomial basis used in populating the TOD is different
        # than the one filter uses and the basis functions are not
        # strictly orthogonal on a sparse grid so we expect a low level
        # residual.

        for det in tod.local_dets:
            cachename = 'noise_{}'.format(det)
            y = tod.cache.reference(cachename)
            rms = np.std(y)
            old = old_rms[det]
            if rms / old > 1e-6 and 'apply' in det:
                raise RuntimeError('det {} old rms = {}, new rms = {}'
                                   ''.format(det, old, rms))
            if rms / old < 1e-1 and 'apply' not in det:
                raise RuntimeError('det {} old rms = {}, new rms = {}'
                                   ''.format(det, old, rms))

        self.print_in_turns('polyfilter test took {:.3f} s'.format(elapsed))
<|endoftext|>


<commit_before>#
# Copyright (c) 2018 Bobby Noelte
#
# SPDX-License-Identifier: Apache-2.0
#

from extract.globals import *
from extract.directive import DTDirective

##
# @brief Manage directives in a default way.
#
class DTDefault(DTDirective):
    def _extract_enum(self, node_path, prop, prop_values, label):
        cell_yaml = get_binding(node_path)['properties'][prop]
        if 'enum' in cell_yaml:
            if prop_values in cell_yaml['enum']:
                if isinstance(cell_yaml['enum'], list):
                   value = cell_yaml['enum'].index(prop_values)
                if isinstance(cell_yaml['enum'], dict):
                   value = cell_yaml['enum'][prop_values]
                label = label + "_ENUM"
                return {label:value}
            else:
                print("ERROR")
        return {}

    ##
    # @brief Extract directives in a default way
    #
    # @param node_path Path to node owning the clockxxx definition.
    # @param prop property name
    # @param prop type (string, boolean, etc)
    # @param def_label Define label string of node owning the directive.
    #
    def extract(self, node_path, prop, prop_type, def_label):
        prop_def = {}
        prop_alias = {}

        if prop_type == 'boolean':
            if prop in reduced[node_path]['props']:
                prop_values = 1
            else:
                prop_values = 0
        else:
            prop_values = reduced[node_path]['props'][prop]

        if isinstance(prop_values, list):
            for i, prop_value in enumerate(prop_values):
                prop_name = str_to_label(prop)
                label = def_label + '_' + prop_name
                if isinstance(prop_value, str):
                    prop_value = "\"" + prop_value + "\""
                prop_def[label + '_' + str(i)] = prop_value
                add_compat_alias(node_path,
                        prop_name + '_' + str(i),
                        label + '_' + str(i),
                        prop_alias)
        else:
            prop_name = str_to_label(prop)
            label = def_label + '_' + prop_name

            if prop_values == 'parent-label':
                prop_values = find_parent_prop(node_path, 'label')

            prop_def = self._extract_enum(node_path, prop, prop_values, label)
            if prop_def:
                add_compat_alias(node_path, prop_name + "_ENUM" , label + "_ENUM", prop_alias)
            if isinstance(prop_values, str):
                prop_values = "\"" + prop_values + "\""
            prop_def[label] = prop_values
            add_compat_alias(node_path, prop_name, label, prop_alias)

            # generate defs for node aliases
            if node_path in aliases:
                add_prop_aliases(
                    node_path,
                    lambda alias: str_to_label(alias) + '_' + prop_name,
                    label,
                    prop_alias)

        insert_defs(node_path, prop_def, prop_alias)

##
# @brief Management information for directives handled by default.
default = DTDefault()
<commit_msg>scripts/dts: Treat string-list always as a list<commit_after>#
# Copyright (c) 2018 Bobby Noelte
#
# SPDX-License-Identifier: Apache-2.0
#

from extract.globals import *
from extract.directive import DTDirective

##
# @brief Manage directives in a default way.
#
class DTDefault(DTDirective):
    def _extract_enum(self, node_path, prop, prop_values, label):
        cell_yaml = get_binding(node_path)['properties'][prop]
        if 'enum' in cell_yaml:
            if prop_values in cell_yaml['enum']:
                if isinstance(cell_yaml['enum'], list):
                   value = cell_yaml['enum'].index(prop_values)
                if isinstance(cell_yaml['enum'], dict):
                   value = cell_yaml['enum'][prop_values]
                label = label + "_ENUM"
                return {label:value}
            else:
                print("ERROR")
        return {}

    ##
    # @brief Extract directives in a default way
    #
    # @param node_path Path to node owning the clockxxx definition.
    # @param prop property name
    # @param prop type (string, boolean, etc)
    # @param def_label Define label string of node owning the directive.
    #
    def extract(self, node_path, prop, prop_type, def_label):
        prop_def = {}
        prop_alias = {}

        if prop_type == 'boolean':
            if prop in reduced[node_path]['props']:
                prop_values = 1
            else:
                prop_values = 0
        else:
            prop_values = reduced[node_path]['props'][prop]

        if prop_type == "string-array":
            if type(prop_values) is not list: prop_values = [ prop_values, ]

        if isinstance(prop_values, list):
            for i, prop_value in enumerate(prop_values):
                prop_name = str_to_label(prop)
                label = def_label + '_' + prop_name
                if isinstance(prop_value, str):
                    prop_value = "\"" + prop_value + "\""
                prop_def[label + '_' + str(i)] = prop_value
                add_compat_alias(node_path,
                        prop_name + '_' + str(i),
                        label + '_' + str(i),
                        prop_alias)
        else:
            prop_name = str_to_label(prop)
            label = def_label + '_' + prop_name

            if prop_values == 'parent-label':
                prop_values = find_parent_prop(node_path, 'label')

            prop_def = self._extract_enum(node_path, prop, prop_values, label)
            if prop_def:
                add_compat_alias(node_path, prop_name + "_ENUM" , label + "_ENUM", prop_alias)
            if isinstance(prop_values, str):
                prop_values = "\"" + prop_values + "\""
            prop_def[label] = prop_values
            add_compat_alias(node_path, prop_name, label, prop_alias)

            # generate defs for node aliases
            if node_path in aliases:
                add_prop_aliases(
                    node_path,
                    lambda alias: str_to_label(alias) + '_' + prop_name,
                    label,
                    prop_alias)

        insert_defs(node_path, prop_def, prop_alias)

##
# @brief Management information for directives handled by default.
default = DTDefault()
<|endoftext|>


<commit_before>"""
  MAC Types

"""

from util import mactobinary

class VppMacAddress():
    def __init__(self, addr):
        self.address = addr

    def encode(self):
        return {
            'bytes': self.bytes
        }

    @property
    def bytes(self):
        return mactobinary(self.address)

    @property
    def address(self):
        return self.addr.address

    def __str__(self):
        return self.address

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.address == other.addres
        elif hasattr(other, "bytes"):
            # vl_api_mac_addres_t
            return self.bytes == other.bytes
        else:
            raise Exception("Comparing VppMacAddress:%s"
                            "with unknown type: %s" %
                            (self, other))
        return False
<commit_msg>Fix L2BD arp termination Test Case<commit_after>"""
  MAC Types

"""

from util import mactobinary

class VppMacAddress():
    def __init__(self, addr):
        self.address = addr

    def encode(self):
        return {
            'bytes': self.bytes
        }

    @property
    def bytes(self):
        return mactobinary(self.address)

    @property
    def address(self):
        return self.address

    @address.setter
    def address(self, value):
        self.address = value

    def __str__(self):
        return self.address

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.address == other.address
        elif hasattr(other, "bytes"):
            # vl_api_mac_addres_t
            return self.bytes == other.bytes
        else:
            raise TypeError("Comparing VppMacAddress:%s"
                            "with unknown type: %s" %
                            (self, other))
        return False
<|endoftext|>


<commit_before>"""
<Program Name>
  update_and_build.py

<Started>
  December 1, 2008

<Author>
  Carter Butaud
  Zachary Boka

<Purpose>
  Builds an installer from the latest code and in the process
  copies the proper files to the directory that the software
  updaters check for updates.
"""

import make_base_installers
import os
import sys
import shutil
import subprocess
import tempfile

DEBUG = False

# For unique temp folders
PROGRAM_NAME = "build_and_update"
UPDATER_SITE = "/home/couvb/public_html/updatesite/test"
if DEBUG:
    UPDATER_SITE = "/home/zackrb/test/updatesite/"
INSTALL_DIR = "seattle_repy"
DIST_DIR = "/var/www/dist"
if DEBUG:
    DIST_DIR = "/home/test/dist/"

def get_digits(s):
    """
    Utility function, returns all the digits from the given string.
    """
    retval = ""
    for c in s:
        if c.isdigit():
            retval += c
    return retval

def sanity_checks(trunk_location, updater_site, pubkey, version):
    """
    <Purpose>
      Checks to make sure that the keys and updater site in the softwareupdater
      script are the same as the ones that this script was given, and that the
      version's release is the same as the version specified in the nodemanager
      script.

    <Arguments>
      trunk_location:
        The path to the repository's trunk, used to find the softwareupdater
        and nodemanager scripts.
      updater_site:
        The local directory where the update is going to be pushed to.
      pubkey:
        Path to the public key that will be used when building the metainfo file
        for the installers and the softwareupdater.
      version:
        Version of the intended release.

    <Exceptions>
      IOError if the softwareupdater script, nodemanager script, or public key
      are not found.

    <Side Effects>
      None.

    <Returns>
      A tuple representing which checks passed and failed (True for pass,
      for for fail). The first element represents the url check, the second
      represents the public key check, and the third represents the version
      check.
    """
    updater_path = os.path.realpath(trunk_location +
                                    "/softwareupdater/softwareupdater.mix")
    nm_path = os.path.realpath(trunk_location + "/nodemanager/nmmain.py")

    if not os.path.exists(updater_path):
        raise IOError("Could not find softwareupdater script at " +
                      updater_path)
    if not os.path.exists(nm_path):
        raise IOError("Could not find nodemanager script at " + nm_path)

    if not os.path.exists(pubkey):
        raise IOError("Could not find public key at " +
                      os.path.realpath(pubkey))

    updater_site = os.path.realpath(updater_site)

    # Find the values in the softwareupdater script
    script_f = open(updater_path)
    script_url = None
    script_key = []
    for line in script_f:
        if "softwareurl = " in line:
            script_url = line.split('"')[1]
        if "softwareupdatepublickey = " in line:
            script_key.append(get_digits(line.split(",")[0]))
            script_key.append(get_digits(line.split(",")[1]))
    script_f.close()

    # Find the version in the nodemanager script
    script_f = open(nm_path)
    script_version = None
    for line in script_f:
        if "version = " in line:
            script_version = line.split('"')[1]
    script_f.close()

    # Get the public key info from the given key.
    key_f = open(pubkey)
    given_key = []
    for line in key_f:
        if line:
            given_key.append(line.split(" ")[0])
            given_key.append(line.split(" ")[1])

    # Get the relevant part of the script url (everything that comes
    # after "couvb")
    script_url_end = script_url[script_url.find("couvb") + len("couvb"):]
    if script_url_end[-1] == "/":
        script_url_end = script_url_end[:-1]

    # Check and see if the updater path ends the same way.
    urls_match = True
    if not updater_site.endswith(script_url_end):
        urls_match = False

    # Check to see if the script key and the given key match,
    keys_match = True
    if not (script_key[0] == given_key[0] and script_key[1] == given_key[1]):
        keys_match = False

    # Check to see if the script version and the given version match.
    versions_match = True
    if not script_version == version:
        versions_match = False

    return (urls_match, keys_match, versions_match)

def build_and_update(trunk_location, pubkey, privkey, version):
    """
    <Purpose>
      Builds the installers, copying the proper files to the software updater
      directory in the process, and deposits the installers in the dist
      directory. Only meant to be run on the actual seattle server.

    <Arguments>
      trunk_location:
        The path to the repository's trunk directory.
      pubkey:
        The public key to be used in the installers.
      privkey:
        The private key to be used in the installers.
      version:
        The version of the distribution, which will be appended to the
        base name of each installer.

    <Exceptions>
      IOError on bad filepaths.

    <Side Effects>
      None.

    <Returns>
      None.
    """
    if not os.path.exists(trunk_location):
        raise IOError("Trunk could not be found at " + trunk_location)
    update_dir = UPDATER_SITE

    # Perform some sanity checks on to make sure the softwareupdater script
    # matches up with the specified info.
    urls_match, keys_match, versions_match = sanity_checks(trunk_location,
                                                           update_dir, pubkey,
                                                           version)
    if not (urls_match and keys_match and versions_match):
        if not urls_match:
            print "Updater location does not match with url in softwareupdater.mix."
        if not keys_match:
            print "Given public key does not match with key in softwareupdater.mix."
        if not versions_match:
            print "Given version does not match with version in nmmain.py"
        return
    print "Sanity checks passed."

    # First, make the temp directories

    # Zack: Create temporary directory for the installation
    temp_install_dir = tempfile.mkdtemp()
    # Zack: Create temporary directory for creating the tarball(s)
    temp_tarball_dir = tempfile.mkdtemp()

    # Next, prepare the installation files
    install_files = make_base_installers.prepare_gen_install_files(trunk_location,
                                                   temp_install_dir, False,
                                                   pubkey, privkey, True)

    # Copy the essential files to the updater site
    p = subprocess.Popen("rm -f " + update_dir + "/*", shell=True)
    p.wait()
    # Zack: Exclude the files that did not belong in the metafile
    for fname in install_files:
      if "nodeman.cfg" != fname and "resources.offcut" != fname
         and "install.py" != fname:
         shutil.copy2(fname, update_dir)

    # Now, package each installer
    make_base_installers.package_win_or_winmob(trunk_location, temp_install_dir, temp_tarball_dir, make_base_installers.get_inst_name("win", version), install_files)
    make_base_installers.package_linux_or_mac(trunk_location, temp_install_dir, temp_tarball_dir, make_base_installers.get_inst_name("linux", version), install_files)
    make_base_installers.package_linux_or_mac(trunk_location, temp_install_dir, temp_tarball_dir, make_base_installers.get_inst_name("mac", version), install_files)

    # Zack: Move the installers to the specified output directory
    os.chdir(temp_tarball_dir)
    for tarball in os.listdir(temp_tarball_dir):
      shutil.copy2(tarball, DIST_DIR)

    # Copy each versioned installer name over the corresponding base
    # base installer
    for dist in ["win", "linux", "mac"]:
        versioned_name = make_base_installers.get_inst_name(dist, version)
        unversioned_name = make_base_installers.get_inst_name(dist, "")
        shutil.copy2(DIST_DIR + "/" + versioned_name, DIST_DIR + "/" + unversioned_name)

    # Zack: Remove the temp directory when done.
    shutil.rmtree(temp_install_dir)
    shutil.rmtree(temp_tarball_dir)
    print "Done!"

def main():
    if len(sys.argv) < 5:
        print "usage: python update_and_build.py trunk/location/ publickey privatekey version"
    else:
        trunk_location = os.path.realpath(sys.argv[1])
        pubkey = os.path.realpath(sys.argv[2])
        privkey = os.path.realpath(sys.argv[3])
        if not DEBUG:
            # Confirm that the user really wants to update all the software
            print "This will update all of the client software!"
            print "Are you sure you want to proceed? (y/n)"
            if raw_input()[0].lower() == "y":
                build_and_update(trunk_location, pubkey, privkey, sys.argv[4])
            else:
                print "Use make_base_installers instead to just create installers."
        else:
            # If we're in DEBUG mode, don't bother to confirm
            print "Operating in debug mode..."
            build_and_update(trunk_location, pubkey, privkey, sys.argv[4])

if __name__ == "__main__":
    main()
<commit_msg>This copy of update_and_build.py should not have errors.  Dificult to test properly without potentially breaking and/or overwriting current installers.<commit_after>"""
<Program Name>
  update_and_build.py

<Started>
  December 1, 2008

<Author>
  Carter Butaud
  Zachary Boka

<Purpose>
  Builds an installer from the latest code and in the process
  copies the proper files to the directory that the software
  updaters check for updates.
"""

import make_base_installers
import os
import sys
import shutil
import subprocess
import tempfile

DEBUG = False

# For unique temp folders
PROGRAM_NAME = "build_and_update"
UPDATER_SITE = "/home/couvb/public_html/updatesite/test"
if DEBUG:
    UPDATER_SITE = "/home/zackrb/test/updatesite/"
INSTALL_DIR = "seattle_repy"
DIST_DIR = "/var/www/dist"
if DEBUG:
    DIST_DIR = "/home/zackrb/test/dist/"

def get_digits(s):
    """
    Utility function, returns all the digits from the given string.
    """
    retval = ""
    for c in s:
        if c.isdigit():
            retval += c
    return retval

def sanity_checks(trunk_location, updater_site, pubkey, version):
    """
    <Purpose>
      Checks to make sure that the keys and updater site in the softwareupdater
      script are the same as the ones that this script was given, and that the
      version's release is the same as the version specified in the nodemanager
      script.

    <Arguments>
      trunk_location:
        The path to the repository's trunk, used to find the softwareupdater
        and nodemanager scripts.
      updater_site:
        The local directory where the update is going to be pushed to.
      pubkey:
        Path to the public key that will be used when building the metainfo file
        for the installers and the softwareupdater.
      version:
        Version of the intended release.

    <Exceptions>
      IOError if the softwareupdater script, nodemanager script, or public key
      are not found.

    <Side Effects>
      None.

    <Returns>
      A tuple representing which checks passed and failed (True for pass,
      for for fail). The first element represents the url check, the second
      represents the public key check, and the third represents the version
      check.
    """
    updater_path = os.path.realpath(trunk_location +
                                    "/softwareupdater/softwareupdater.mix")
    nm_path = os.path.realpath(trunk_location + "/nodemanager/nmmain.py")

    if not os.path.exists(updater_path):
        raise IOError("Could not find softwareupdater script at " +
                      updater_path)
    if not os.path.exists(nm_path):
        raise IOError("Could not find nodemanager script at " + nm_path)

    if not os.path.exists(pubkey):
        raise IOError("Could not find public key at " +
                      os.path.realpath(pubkey))

    updater_site = os.path.realpath(updater_site)

    # Find the values in the softwareupdater script
    script_f = open(updater_path)
    script_url = None
    script_key = []
    for line in script_f:
        if "softwareurl = " in line:
            script_url = line.split('"')[1]
        if "softwareupdatepublickey = " in line:
            script_key.append(get_digits(line.split(",")[0]))
            script_key.append(get_digits(line.split(",")[1]))
    script_f.close()

    # Find the version in the nodemanager script
    script_f = open(nm_path)
    script_version = None
    for line in script_f:
        if "version = " in line:
            script_version = line.split('"')[1]
    script_f.close()

    # Get the public key info from the given key.
    key_f = open(pubkey)
    given_key = []
    for line in key_f:
        if line:
            given_key.append(line.split(" ")[0])
            given_key.append(line.split(" ")[1])

    # Get the relevant part of the script url (everything that comes
    # after "couvb")
    script_url_end = script_url[script_url.find("couvb") + len("couvb"):]
    if script_url_end[-1] == "/":
        script_url_end = script_url_end[:-1]

    # Check and see if the updater path ends the same way.
    urls_match = True
    if not updater_site.endswith(script_url_end):
        urls_match = False

    # Check to see if the script key and the given key match,
    keys_match = True
    if not (script_key[0] == given_key[0] and script_key[1] == given_key[1]):
        keys_match = False

    # Check to see if the script version and the given version match.
    versions_match = True
    if not script_version == version:
        versions_match = False

    return (urls_match, keys_match, versions_match)

def build_and_update(trunk_location, pubkey, privkey, version):
    """
    <Purpose>
      Builds the installers, copying the proper files to the software updater
      directory in the process, and deposits the installers in the dist
      directory. Only meant to be run on the actual seattle server.

    <Arguments>
      trunk_location:
        The path to the repository's trunk directory.
      pubkey:
        The public key to be used in the installers.
      privkey:
        The private key to be used in the installers.
      version:
        The version of the distribution, which will be appended to the
        base name of each installer.

    <Exceptions>
      IOError on bad filepaths.

    <Side Effects>
      None.

    <Returns>
      None.
    """
    if not os.path.exists(trunk_location):
        raise IOError("Trunk could not be found at " + trunk_location)
    update_dir = UPDATER_SITE

    # Perform some sanity checks on to make sure the softwareupdater script
    # matches up with the specified info.
    urls_match, keys_match, versions_match = sanity_checks(trunk_location,
                                                           update_dir, pubkey,
                                                           version)
    if not (urls_match and keys_match and versions_match):
        if not urls_match:
            print "Updater location does not match with url in softwareupdater.mix."
        if not keys_match:
            print "Given public key does not match with key in softwareupdater.mix."
        if not versions_match:
            print "Given version does not match with version in nmmain.py"
        return
    print "Sanity checks passed."

    # First, make the temp directories

    # Zack: Create temporary directory for the installation
    temp_install_dir = tempfile.mkdtemp()
    # Zack: Create temporary directory for creating the tarball(s)
    temp_tarball_dir = tempfile.mkdtemp()

    # Next, prepare the installation files
    install_files = make_base_installers.prepare_gen_install_files(trunk_location,
                                                   temp_install_dir, False,
                                                   pubkey, privkey, True)

    # Copy the essential files to the updater site
    p = subprocess.Popen("rm -f " + update_dir + "/*", shell=True)
    p.wait()
    # Zack: Exclude the files that did not belong in the metafile
    for fname in install_files:
      if "nodeman.cfg" != fname and "resources.offcut" != fname \
         and "install.py" != fname:
         shutil.copy2(fname, update_dir)

    # Now, package each installer
    make_base_installers.package_win_or_winmob(trunk_location, temp_install_dir, temp_tarball_dir, make_base_installers.get_inst_name("win", version), install_files)
    make_base_installers.package_linux_or_mac(trunk_location, temp_install_dir, temp_tarball_dir, make_base_installers.get_inst_name("linux", version), install_files)
    make_base_installers.package_linux_or_mac(trunk_location, temp_install_dir, temp_tarball_dir, make_base_installers.get_inst_name("mac", version), install_files)

    # Zack: Move the installers to the specified output directory
    os.chdir(temp_tarball_dir)
    for tarball in os.listdir(temp_tarball_dir):
      shutil.copy2(tarball, DIST_DIR)

    # Copy each versioned installer name over the corresponding base
    # base installer
    for dist in ["win", "linux", "mac"]:
        versioned_name = make_base_installers.get_inst_name(dist, version)
        unversioned_name = make_base_installers.get_inst_name(dist, "")
        shutil.copy2(DIST_DIR + "/" + versioned_name, DIST_DIR + "/" + unversioned_name)

    # Zack: Remove the temp directory when done.
    shutil.rmtree(temp_install_dir)
    shutil.rmtree(temp_tarball_dir)
    print "Done!"

def main():
    if len(sys.argv) < 5:
        print "usage: python update_and_build.py trunk/location/ publickey privatekey version"
    else:
        trunk_location = os.path.realpath(sys.argv[1])
        pubkey = os.path.realpath(sys.argv[2])
        privkey = os.path.realpath(sys.argv[3])
        if not DEBUG:
            # Confirm that the user really wants to update all the software
            print "This will update all of the client software!"
            print "Are you sure you want to proceed? (y/n)"
            if raw_input()[0].lower() == "y":
                build_and_update(trunk_location, pubkey, privkey, sys.argv[4])
            else:
                print "Use make_base_installers instead to just create installers."
        else:
            # If we're in DEBUG mode, don't bother to confirm
            print "Operating in debug mode..."
            build_and_update(trunk_location, pubkey, privkey, sys.argv[4])

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


<commit_before>"""
Form classes
"""

from django.utils.datastructures import SortedDict
from fields import Field
from widgets import TextInput, Textarea
from util import ErrorDict, ErrorList, ValidationError

NON_FIELD_ERRORS = '__all__'

def pretty_name(name):
    "Converts 'first_name' to 'First name'"
    name = name[0].upper() + name[1:]
    return name.replace('_', ' ')

class SortedDictFromList(SortedDict):
    "A dictionary that keeps its keys in the order in which they're inserted."
    # This is different than django.utils.datastructures.SortedDict, because
    # this takes a list/tuple as the argument to __init__().
    def __init__(self, data=None):
        if data is None: data = []
        self.keyOrder = [d[0] for d in data]
        dict.__init__(self, dict(data))

class DeclarativeFieldsMetaclass(type):
    "Metaclass that converts Field attributes to a dictionary called 'fields'."
    def __new__(cls, name, bases, attrs):
        fields = [(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)]
        fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
        attrs['fields'] = SortedDictFromList(fields)
        return type.__new__(cls, name, bases, attrs)

class Form(object):
    "A collection of Fields, plus their associated data."
    __metaclass__ = DeclarativeFieldsMetaclass

    def __init__(self, data=None, auto_id=False): # TODO: prefix stuff
        self.ignore_errors = data is None
        self.data = data or {}
        self.auto_id = auto_id
        self.clean_data = None # Stores the data after clean() has been called.
        self.__errors = None # Stores the errors after clean() has been called.

    def __str__(self):
        return self.as_table()

    def __iter__(self):
        for name, field in self.fields.items():
            yield BoundField(self, field, name)

    def __getitem__(self, name):
        "Returns a BoundField with the given name."
        try:
            field = self.fields[name]
        except KeyError:
            raise KeyError('Key %r not found in Form' % name)
        return BoundField(self, field, name)

    def _errors(self):
        "Returns an ErrorDict for self.data"
        if self.__errors is None:
            self.full_clean()
        return self.__errors
    errors = property(_errors)

    def is_valid(self):
        """
        Returns True if the form has no errors. Otherwise, False. If errors are
        being ignored, returns False.
        """
        return not self.ignore_errors and not bool(self.errors)

    def as_table(self):
        "Returns this form rendered as HTML
s -- excluding the

."
        output = []
        if self.errors.get(NON_FIELD_ERRORS):
            # Errors not corresponding to a particular field are displayed at the top.
            output.append(u'
%s
' % self.non_field_errors())
        for name, field in self.fields.items():
            bf = BoundField(self, field, name)
            if bf.errors:
                output.append(u'
%s
' % bf.errors)
            output.append(u'
%s:	%s
' % (bf.label, bf))
        return u'\n'.join(output)

    def as_ul(self):
        "Returns this form rendered as HTML
s -- excluding the

."
        output = []
        if self.errors.get(NON_FIELD_ERRORS):
            # Errors not corresponding to a particular field are displayed at the top.
            output.append(u'
%s
' % self.non_field_errors())
        for name, field in self.fields.items():
            bf = BoundField(self, field, name)
            line = u'
'
            if bf.errors:
                line += str(bf.errors)
            line += u'%s: %s
' % (bf.label, bf)
            output.append(line)
        return u'\n'.join(output)

    def non_field_errors(self):
        """
        Returns an ErrorList of errors that aren't associated with a particular
        field -- i.e., from Form.clean(). Returns an empty ErrorList if there
        are none.
        """
        return self.errors.get(NON_FIELD_ERRORS, ErrorList())

    def full_clean(self):
        """
        Cleans all of self.data and populates self.__errors and self.clean_data.
        """
        self.clean_data = {}
        errors = ErrorDict()
        if self.ignore_errors: # Stop further processing.
            self.__errors = errors
            return
        for name, field in self.fields.items():
            value = self.data.get(name, None)
            try:
                value = field.clean(value)
                self.clean_data[name] = value
                if hasattr(self, 'clean_%s' % name):
                    value = getattr(self, 'clean_%s' % name)()
                self.clean_data[name] = value
            except ValidationError, e:
                errors[name] = e.messages
        try:
            self.clean_data = self.clean()
        except ValidationError, e:
            errors[NON_FIELD_ERRORS] = e.messages
        if errors:
            self.clean_data = None
        self.__errors = errors

    def clean(self):
        """
        Hook for doing any extra form-wide cleaning after Field.clean() been
        called on every field. Any ValidationError raised by this method will
        not be associated with a particular field; it will have a special-case
        association with the field named '__all__'.
        """
        return self.clean_data

class BoundField(object):
    "A Field plus data"
    def __init__(self, form, field, name):
        self._form = form
        self._field = field
        self._name = name

    def __str__(self):
        "Renders this field as an HTML widget."
        # Use the 'widget' attribute on the field to determine which type
        # of HTML widget to use.
        value = self.as_widget(self._field.widget)
        if not isinstance(value, basestring):
            # Some Widget render() methods -- notably RadioSelect -- return a
            # "special" object rather than a string. Call the __str__() on that
            # object to get its rendered value.
            value = value.__str__()
        return value

    def _errors(self):
        """
        Returns an ErrorList for this field. Returns an empty ErrorList
        if there are none.
        """
        try:
            return self._form.errors[self._name]
        except KeyError:
            return ErrorList()
    errors = property(_errors)

    def as_widget(self, widget, attrs=None):
        attrs = attrs or {}
        auto_id = self.auto_id
        if not attrs.has_key('id') and not widget.attrs.has_key('id') and auto_id:
            attrs['id'] = auto_id
        return widget.render(self._name, self._form.data.get(self._name, None), attrs=attrs)

    def as_text(self, attrs=None):
        """
        Returns a string of HTML for representing this as an <input type="text">.
        """
        return self.as_widget(TextInput(), attrs)

    def as_textarea(self, attrs=None):
        "Returns a string of HTML for representing this as a <textarea>."
        return self.as_widget(Textarea(), attrs)

    def _label(self):
        return pretty_name(self._name)
    label = property(_label)

    def _auto_id(self):
        """
        Calculates and returns the ID attribute for this BoundField, if the
        associated Form has specified auto_id. Returns an empty string otherwise.
        """
        auto_id = self._form.auto_id
        if auto_id and '%s' in str(auto_id):
            return str(auto_id) % self._name
        elif auto_id:
            return self._name
        return ''
    auto_id = property(_auto_id)
<commit_msg>newforms: Small short-circuit optimization to BoundField.as_widget()<commit_after>"""
Form classes
"""

from django.utils.datastructures import SortedDict
from fields import Field
from widgets import TextInput, Textarea
from util import ErrorDict, ErrorList, ValidationError

NON_FIELD_ERRORS = '__all__'

def pretty_name(name):
    "Converts 'first_name' to 'First name'"
    name = name[0].upper() + name[1:]
    return name.replace('_', ' ')

class SortedDictFromList(SortedDict):
    "A dictionary that keeps its keys in the order in which they're inserted."
    # This is different than django.utils.datastructures.SortedDict, because
    # this takes a list/tuple as the argument to __init__().
    def __init__(self, data=None):
        if data is None: data = []
        self.keyOrder = [d[0] for d in data]
        dict.__init__(self, dict(data))

class DeclarativeFieldsMetaclass(type):
    "Metaclass that converts Field attributes to a dictionary called 'fields'."
    def __new__(cls, name, bases, attrs):
        fields = [(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)]
        fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
        attrs['fields'] = SortedDictFromList(fields)
        return type.__new__(cls, name, bases, attrs)

class Form(object):
    "A collection of Fields, plus their associated data."
    __metaclass__ = DeclarativeFieldsMetaclass

    def __init__(self, data=None, auto_id=False): # TODO: prefix stuff
        self.ignore_errors = data is None
        self.data = data or {}
        self.auto_id = auto_id
        self.clean_data = None # Stores the data after clean() has been called.
        self.__errors = None # Stores the errors after clean() has been called.

    def __str__(self):
        return self.as_table()

    def __iter__(self):
        for name, field in self.fields.items():
            yield BoundField(self, field, name)

    def __getitem__(self, name):
        "Returns a BoundField with the given name."
        try:
            field = self.fields[name]
        except KeyError:
            raise KeyError('Key %r not found in Form' % name)
        return BoundField(self, field, name)

    def _errors(self):
        "Returns an ErrorDict for self.data"
        if self.__errors is None:
            self.full_clean()
        return self.__errors
    errors = property(_errors)

    def is_valid(self):
        """
        Returns True if the form has no errors. Otherwise, False. If errors are
        being ignored, returns False.
        """
        return not self.ignore_errors and not bool(self.errors)

    def as_table(self):
        "Returns this form rendered as HTML
s -- excluding the

."
        output = []
        if self.errors.get(NON_FIELD_ERRORS):
            # Errors not corresponding to a particular field are displayed at the top.
            output.append(u'
%s
' % self.non_field_errors())
        for name, field in self.fields.items():
            bf = BoundField(self, field, name)
            if bf.errors:
                output.append(u'
%s
' % bf.errors)
            output.append(u'
%s:	%s
' % (bf.label, bf))
        return u'\n'.join(output)

    def as_ul(self):
        "Returns this form rendered as HTML
s -- excluding the

."
        output = []
        if self.errors.get(NON_FIELD_ERRORS):
            # Errors not corresponding to a particular field are displayed at the top.
            output.append(u'
%s
' % self.non_field_errors())
        for name, field in self.fields.items():
            bf = BoundField(self, field, name)
            line = u'
'
            if bf.errors:
                line += str(bf.errors)
            line += u'%s: %s
' % (bf.label, bf)
            output.append(line)
        return u'\n'.join(output)

    def non_field_errors(self):
        """
        Returns an ErrorList of errors that aren't associated with a particular
        field -- i.e., from Form.clean(). Returns an empty ErrorList if there
        are none.
        """
        return self.errors.get(NON_FIELD_ERRORS, ErrorList())

    def full_clean(self):
        """
        Cleans all of self.data and populates self.__errors and self.clean_data.
        """
        self.clean_data = {}
        errors = ErrorDict()
        if self.ignore_errors: # Stop further processing.
            self.__errors = errors
            return
        for name, field in self.fields.items():
            value = self.data.get(name, None)
            try:
                value = field.clean(value)
                self.clean_data[name] = value
                if hasattr(self, 'clean_%s' % name):
                    value = getattr(self, 'clean_%s' % name)()
                self.clean_data[name] = value
            except ValidationError, e:
                errors[name] = e.messages
        try:
            self.clean_data = self.clean()
        except ValidationError, e:
            errors[NON_FIELD_ERRORS] = e.messages
        if errors:
            self.clean_data = None
        self.__errors = errors

    def clean(self):
        """
        Hook for doing any extra form-wide cleaning after Field.clean() been
        called on every field. Any ValidationError raised by this method will
        not be associated with a particular field; it will have a special-case
        association with the field named '__all__'.
        """
        return self.clean_data

class BoundField(object):
    "A Field plus data"
    def __init__(self, form, field, name):
        self._form = form
        self._field = field
        self._name = name

    def __str__(self):
        "Renders this field as an HTML widget."
        # Use the 'widget' attribute on the field to determine which type
        # of HTML widget to use.
        value = self.as_widget(self._field.widget)
        if not isinstance(value, basestring):
            # Some Widget render() methods -- notably RadioSelect -- return a
            # "special" object rather than a string. Call the __str__() on that
            # object to get its rendered value.
            value = value.__str__()
        return value

    def _errors(self):
        """
        Returns an ErrorList for this field. Returns an empty ErrorList
        if there are none.
        """
        try:
            return self._form.errors[self._name]
        except KeyError:
            return ErrorList()
    errors = property(_errors)

    def as_widget(self, widget, attrs=None):
        attrs = attrs or {}
        auto_id = self.auto_id
        if auto_id and not attrs.has_key('id') and not widget.attrs.has_key('id'):
            attrs['id'] = auto_id
        return widget.render(self._name, self._form.data.get(self._name, None), attrs=attrs)

    def as_text(self, attrs=None):
        """
        Returns a string of HTML for representing this as an <input type="text">.
        """
        return self.as_widget(TextInput(), attrs)

    def as_textarea(self, attrs=None):
        "Returns a string of HTML for representing this as a <textarea>."
        return self.as_widget(Textarea(), attrs)

    def _label(self):
        return pretty_name(self._name)
    label = property(_label)

    def _auto_id(self):
        """
        Calculates and returns the ID attribute for this BoundField, if the
        associated Form has specified auto_id. Returns an empty string otherwise.
        """
        auto_id = self._form.auto_id
        if auto_id and '%s' in str(auto_id):
            return str(auto_id) % self._name
        elif auto_id:
            return self._name
        return ''
    auto_id = property(_auto_id)
<|endoftext|>


<commit_before>import re, doctest, unittest
import sys
from urlparse import urlparse
from django.db import transaction
from django.core import management, mail
from django.db.models import get_apps
from django.test.client import Client

normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)

class OutputChecker(doctest.OutputChecker):
    def check_output(self, want, got, optionflags):
        ok = doctest.OutputChecker.check_output(self, want, got, optionflags)

        # Doctest does an exact string comparison of output, which means long
        # integers aren't equal to normal integers ("22L" vs. "22"). The
        # following code normalizes long integers so that they equal normal
        # integers.
        if not ok:
            return normalize_long_ints(want) == normalize_long_ints(got)
        return ok

class DocTestRunner(doctest.DocTestRunner):
    def __init__(self, *args, **kwargs):
        doctest.DocTestRunner.__init__(self, *args, **kwargs)
        self.optionflags = doctest.ELLIPSIS

    def report_unexpected_exception(self, out, test, example, exc_info):
        doctest.DocTestRunner.report_unexpected_exception(self,out,test,example,exc_info)

        # Rollback, in case of database errors. Otherwise they'd have
        # side effects on other tests.
        from django.db import transaction
        transaction.rollback_unless_managed()

class TestCase(unittest.TestCase):
    def _pre_setup(self):
        """Perform any pre-test setup. This includes:

            * If the Test Case class has a 'fixtures' member, clearing the
            database and installing the named fixtures at the start of each test.
            * Clearing the mail test outbox.

        """
        management.flush(verbosity=0, interactive=False)
        if hasattr(self, 'fixtures'):
            management.load_data(self.fixtures, verbosity=0)
        mail.outbox = []

    def __call__(self, result=None):
        """
        Wrapper around default __call__ method to perform common Django test
        set up. This means that user-defined Test Cases aren't required to
        include a call to super().setUp().
        """
        self.client = Client()
        self._pre_setup()
        super(TestCase, self).__call__(result)

    def assertRedirects(self, response, expected_path, status_code=302, target_status_code=200):
        """Assert that a response redirected to a specific URL, and that the
        redirect URL can be loaded.

        """
        self.assertEqual(response.status_code, status_code,
            "Response didn't redirect: Reponse code was %d (expected %d)" %
                (response.status_code, status_code))
        scheme, netloc, path, params, query, fragment = urlparse(response['Location'])
        self.assertEqual(path, expected_path,
            "Response redirected to '%s', expected '%s'" % (path, expected_path))
        redirect_response = self.client.get(path)
        self.assertEqual(redirect_response.status_code, target_status_code,
            "Couldn't retrieve redirection page '%s': response code was %d (expected %d)" %
                (path, response.status_code, status_code))

    def assertContains(self, response, text, count=1, status_code=200):
        """Assert that a response indicates that a page was retreived successfully,
        (i.e., the HTTP status code was as expected), and that ``text`` occurs ``count``
        times in the content of the response.

        """
        self.assertEqual(response.status_code, status_code,
            "Couldn't retrieve page: Response code was %d (expected %d)'" %
                (response.status_code, status_code))
        real_count = response.content.count(text)
        self.assertEqual(real_count, count,
            "Found %d instances of '%s' in response (expected %d)" % (real_count, text, count))

    def assertFormError(self, response, form, field, errors):
        "Assert that a form used to render the response has a specific field error"
        if not response.context:
            self.fail('Response did not use any contexts to render the response')

        # If there is a single context, put it into a list to simplify processing
        if not isinstance(response.context, list):
            contexts = [response.context]
        else:
            contexts = response.context

        # If a single error string is provided, make it a list to simplify processing
        if not isinstance(errors, list):
            errors = [errors]

        # Search all contexts for the error.
        found_form = False
        for i,context in enumerate(contexts):
            if form in context:
                found_form = True
                for err in errors:
                    if field:
                        if field in context[form].errors:
                            self.failUnless(err in context[form].errors[field],
                            "The field '%s' on form '%s' in context %d does not contain the error '%s' (actual errors: %s)" %
                                (field, form, i, err, list(context[form].errors[field])))
                        elif field in context[form].fields:
                            self.fail("The field '%s' on form '%s' in context %d contains no errors" %
                                (field, form, i))
                        else:
                            self.fail("The form '%s' in context %d does not contain the field '%s'" % (form, i, field))
                    else:
                        self.failUnless(err in context[form].non_field_errors(),
                            "The form '%s' in context %d does not contain the non-field error '%s' (actual errors: %s)" %
                                (form, i, err, list(context[form].non_field_errors())))
        if not found_form:
            self.fail("The form '%s' was not used to render the response" % form)

    def assertTemplateUsed(self, response, template_name):
        "Assert that the template with the provided name was used in rendering the response"
        if isinstance(response.template, list):
            template_names = [t.name for t in response.template]
            self.failUnless(template_name in template_names,
                "Template '%s' was not one of the templates used to render the response. Templates used: %s" %
                    (template_name, template_names))
        elif response.template:
            self.assertEqual(template_name, response.template.name,
                "Template '%s' was not used to render the response. Actual template was '%s'" %
                    (template_name, response.template.name))
        else:
            self.fail('No templates used to render the response')

    def assertTemplateNotUsed(self, response, template_name):
        "Assert that the template with the provided name was NOT used in rendering the response"
        if isinstance(response.template, list):
            self.failIf(template_name in [t.name for t in response.template],
                "Template '%s' was used unexpectedly in rendering the response" % template_name)
        elif response.template:
            self.assertNotEqual(template_name, response.template.name,
                "Template '%s' was used unexpectedly in rendering the response" % template_name)

<commit_msg>Removed a stray import that snuck into [5211].<commit_after>import re, doctest, unittest
from urlparse import urlparse
from django.db import transaction
from django.core import management, mail
from django.db.models import get_apps
from django.test.client import Client

normalize_long_ints = lambda s: re.sub(r'(?<![\w])(\d+)L(?![\w])', '\\1', s)

class OutputChecker(doctest.OutputChecker):
    def check_output(self, want, got, optionflags):
        ok = doctest.OutputChecker.check_output(self, want, got, optionflags)

        # Doctest does an exact string comparison of output, which means long
        # integers aren't equal to normal integers ("22L" vs. "22"). The
        # following code normalizes long integers so that they equal normal
        # integers.
        if not ok:
            return normalize_long_ints(want) == normalize_long_ints(got)
        return ok

class DocTestRunner(doctest.DocTestRunner):
    def __init__(self, *args, **kwargs):
        doctest.DocTestRunner.__init__(self, *args, **kwargs)
        self.optionflags = doctest.ELLIPSIS

    def report_unexpected_exception(self, out, test, example, exc_info):
        doctest.DocTestRunner.report_unexpected_exception(self,out,test,example,exc_info)

        # Rollback, in case of database errors. Otherwise they'd have
        # side effects on other tests.
        from django.db import transaction
        transaction.rollback_unless_managed()

class TestCase(unittest.TestCase):
    def _pre_setup(self):
        """Perform any pre-test setup. This includes:

            * If the Test Case class has a 'fixtures' member, clearing the
            database and installing the named fixtures at the start of each test.
            * Clearing the mail test outbox.

        """
        management.flush(verbosity=0, interactive=False)
        if hasattr(self, 'fixtures'):
            management.load_data(self.fixtures, verbosity=0)
        mail.outbox = []

    def __call__(self, result=None):
        """
        Wrapper around default __call__ method to perform common Django test
        set up. This means that user-defined Test Cases aren't required to
        include a call to super().setUp().
        """
        self.client = Client()
        self._pre_setup()
        super(TestCase, self).__call__(result)

    def assertRedirects(self, response, expected_path, status_code=302, target_status_code=200):
        """Assert that a response redirected to a specific URL, and that the
        redirect URL can be loaded.

        """
        self.assertEqual(response.status_code, status_code,
            "Response didn't redirect: Reponse code was %d (expected %d)" %
                (response.status_code, status_code))
        scheme, netloc, path, params, query, fragment = urlparse(response['Location'])
        self.assertEqual(path, expected_path,
            "Response redirected to '%s', expected '%s'" % (path, expected_path))
        redirect_response = self.client.get(path)
        self.assertEqual(redirect_response.status_code, target_status_code,
            "Couldn't retrieve redirection page '%s': response code was %d (expected %d)" %
                (path, response.status_code, status_code))

    def assertContains(self, response, text, count=1, status_code=200):
        """Assert that a response indicates that a page was retreived successfully,
        (i.e., the HTTP status code was as expected), and that ``text`` occurs ``count``
        times in the content of the response.

        """
        self.assertEqual(response.status_code, status_code,
            "Couldn't retrieve page: Response code was %d (expected %d)'" %
                (response.status_code, status_code))
        real_count = response.content.count(text)
        self.assertEqual(real_count, count,
            "Found %d instances of '%s' in response (expected %d)" % (real_count, text, count))

    def assertFormError(self, response, form, field, errors):
        "Assert that a form used to render the response has a specific field error"
        if not response.context:
            self.fail('Response did not use any contexts to render the response')

        # If there is a single context, put it into a list to simplify processing
        if not isinstance(response.context, list):
            contexts = [response.context]
        else:
            contexts = response.context

        # If a single error string is provided, make it a list to simplify processing
        if not isinstance(errors, list):
            errors = [errors]

        # Search all contexts for the error.
        found_form = False
        for i,context in enumerate(contexts):
            if form in context:
                found_form = True
                for err in errors:
                    if field:
                        if field in context[form].errors:
                            self.failUnless(err in context[form].errors[field],
                            "The field '%s' on form '%s' in context %d does not contain the error '%s' (actual errors: %s)" %
                                (field, form, i, err, list(context[form].errors[field])))
                        elif field in context[form].fields:
                            self.fail("The field '%s' on form '%s' in context %d contains no errors" %
                                (field, form, i))
                        else:
                            self.fail("The form '%s' in context %d does not contain the field '%s'" % (form, i, field))
                    else:
                        self.failUnless(err in context[form].non_field_errors(),
                            "The form '%s' in context %d does not contain the non-field error '%s' (actual errors: %s)" %
                                (form, i, err, list(context[form].non_field_errors())))
        if not found_form:
            self.fail("The form '%s' was not used to render the response" % form)

    def assertTemplateUsed(self, response, template_name):
        "Assert that the template with the provided name was used in rendering the response"
        if isinstance(response.template, list):
            template_names = [t.name for t in response.template]
            self.failUnless(template_name in template_names,
                "Template '%s' was not one of the templates used to render the response. Templates used: %s" %
                    (template_name, template_names))
        elif response.template:
            self.assertEqual(template_name, response.template.name,
                "Template '%s' was not used to render the response. Actual template was '%s'" %
                    (template_name, response.template.name))
        else:
            self.fail('No templates used to render the response')

    def assertTemplateNotUsed(self, response, template_name):
        "Assert that the template with the provided name was NOT used in rendering the response"
        if isinstance(response.template, list):
            self.failIf(template_name in [t.name for t in response.template],
                "Template '%s' was used unexpectedly in rendering the response" % template_name)
        elif response.template:
            self.assertNotEqual(template_name, response.template.name,
                "Template '%s' was used unexpectedly in rendering the response" % template_name)

<|endoftext|>


<commit_before>"""
Shortcuts
"""
from django.http.response import HttpResponseRedirectBase, \
    Http404, REASON_PHRASES, HttpResponse
from django.template.response import TemplateResponse
from django_ajax.response import JsonHttpResponse

def render_to_json(response):
    """
    Determine the appropriate content and create the JSON response
    """
    # determine the status code response
    if hasattr(response, 'status_code'):
        status_code = response.status_code
    elif issubclass(type(response), Http404):
        status_code = 404
    elif issubclass(type(response), Exception):
        status_code = 500
    else:
        status_code = 200

    # determine the content response
    if issubclass(type(response), HttpResponseRedirectBase):
        content = response['Location']
    elif issubclass(type(response), TemplateResponse):
        content = response.rendered_content
    elif issubclass(type(response), HttpResponse):
        content = response.content
    elif issubclass(type(response), Exception):
        content = unicode(response)
    else:
        content = response

    data = {
        'status': status_code,
        'statusText': REASON_PHRASES.get(status_code, 'UNKNOWN STATUS CODE'),
        'content': content
    }

    return JsonHttpResponse(data)

<commit_msg>Fixed render to json function for process fragments option<commit_after>"""
Shortcuts
"""
from django.http.response import HttpResponseRedirectBase, \
    Http404, REASON_PHRASES, HttpResponse
from django.template.response import TemplateResponse
from django.utils.encoding import force_unicode
from django_ajax.response import JsonHttpResponse

def render_to_json(response):
    """
    Determine the appropriate content and create the JSON response
    """
    # determine the status code
    if hasattr(response, 'status_code'):
        status_code = response.status_code
    elif issubclass(type(response), Http404):
        status_code = 404
    elif issubclass(type(response), Exception):
        status_code = 500
    else:
        status_code = 200

    # determine the content TODO: move to JSONEncoder class
    if issubclass(type(response), HttpResponseRedirectBase):
        content = response['Location']
    elif issubclass(type(response), TemplateResponse):
        content = response.rendered_content
    elif issubclass(type(response), HttpResponse):
        content = response.content
    elif issubclass(type(response), Exception):
        content = force_unicode(response)
    else:
        content = response

    data = {}

    # TODO:
    if isinstance(content, dict):
        for key in ['fragments', 'inner-fragments', 'append-fragments',
                    'prepend-fragments']:
            if key in content:
                data.update({
                    key: content.pop(key)
                })

    data.update({
        'status': status_code,
        'statusText': REASON_PHRASES.get(status_code, 'UNKNOWN STATUS CODE'),
        'content': content
    })

    return JsonHttpResponse(data)

<|endoftext|>


<commit_before>import datetime
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_noop
from django.core.urlresolvers import reverse
from django.conf import settings

from django_messages.models import Message
from django_messages.forms import ComposeForm
from django_messages.utils import format_quote

if "notification" in settings.INSTALLED_APPS:
    from notification import models as notification
else:
    notification = None

def inbox(request, **kwargs):
    """
    Displays a list of received messages for the current user.
    Optional Arguments:
        ``template_name``: name of the template to use.
        ``template_name_ajax``: name of the template to use when view is called through ajax.
    """
    template_name = kwargs.get("template_name", "django_messages/inbox.html")
    if request.is_ajax():
        template_name = kwargs.get(
            "template_name_ajax",
            "django_messages/inbox_ajax.html")

    message_list = Message.objects.inbox_for(request.user)
    return render_to_response(template_name, {
        'message_list': message_list,
    }, context_instance=RequestContext(request))
inbox = login_required(inbox)

def outbox(request, **kwargs):
    """
    Displays a list of sent messages by the current user.
    Optional arguments:
        ``template_name``: name of the template to use.
    """
    template_name = kwargs.get("template_name", "django_messages/outbox.html")
    if request.is_ajax():
        template_name = kwargs.get(
            "template_name_ajax",
            "django_messages/outbox_ajax.html")

    message_list = Message.objects.outbox_for(request.user)
    return render_to_response(template_name, {
        'message_list': message_list,
    }, context_instance=RequestContext(request))
outbox = login_required(outbox)

def trash(request, **kwargs):
    """
    Displays a list of deleted messages.
    Optional arguments:
        ``template_name``: name of the template to use
        ``template_name_ajax``: the template to use if request is ajax
    Hint: A Cron-Job could periodicly clean up old messages, which are deleted
    by sender and recipient.
    """
    template_name = kwargs.get("template_name", "django_messages/trash.html")
    if request.is_ajax():
        template_name = kwargs.get(
            "template_name_ajax",
            "django_messages/trash_ajax.html")

    message_list = Message.objects.trash_for(request.user)
    return render_to_response(template_name, {
        'message_list': message_list,
    }, context_instance=RequestContext(request))
trash = login_required(trash)

def compose(request, recipient=None, form_class=ComposeForm,
        template_name='django_messages/compose.html', success_url=None, recipient_filter=None, **kwargs):
    """
    Displays and handles the ``form_class`` form to compose new messages.
    Required Arguments: None
    Optional Arguments:
        ``recipient``: username of a `django.contrib.auth` User, who should
                       receive the message, optionally multiple usernames
                       could be separated by a '+'
        ``form_class``: the form-class to use
        ``template_name``: the template to use
        ``template_name_ajax``: the template to use if request is ajax
        ``success_url``: where to redirect after successfull submission
    """
    if request.is_ajax():
        template_name = kwargs.get(
            "template_name_ajax",
            "django_messages/compose_ajax.html")

    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.REQUEST.has_key('next'):
        success_url = request.REQUEST['next']

    if request.method == "POST":
        sender = request.user
        form = form_class(request.POST, recipient_filter=recipient_filter)
        if form.is_valid():
            form.save(sender=request.user)
            request.user.message_set.create(
                message=_(u"Message successfully sent."))
            return HttpResponseRedirect(success_url)
    else:
        form = form_class()
        if recipient is not None:
            recipients = [u for u in User.objects.filter(username__in=[r.strip() for r in recipient.split('+')])]
            form.fields['recipient'].initial = recipients
    return render_to_response(template_name, {
        'form': form,
        'success_url': success_url
    }, context_instance=RequestContext(request))
compose = login_required(compose)

def reply(request, message_id, form_class=ComposeForm,
        template_name='django_messages/compose.html', success_url=None,
        recipient_filter=None, quote_helper=format_quote, **kwargs):
    """
    Prepares the ``form_class`` form for writing a reply to a given message
    (specified via ``message_id``). Uses the ``format_quote`` helper from
    ``messages.utils`` to pre-format the quote. To change the quote format
    assign a different ``quote_helper`` kwarg in your url-conf.

    """
    parent = get_object_or_404(Message, id=message_id)

    if request.is_ajax():
        template_name = kwargs.get(
            "template_name_ajax",
            "django_messages/compose_ajax.html")

    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.GET.has_key('next'):
        success_url = request.GET['next']

    if parent.sender != request.user and parent.recipient != request.user:
        raise Http404

    if request.method == "POST":
        sender = request.user
        form = form_class(request.POST, recipient_filter=recipient_filter)
        if form.is_valid():
            form.save(sender=request.user, parent_msg=parent)
            request.user.message_set.create(
                message=_(u"Message successfully sent."))
            return HttpResponseRedirect(success_url)
    else:
        form = form_class(initial={
            'body': quote_helper(parent.sender, parent.body),
            'subject': _(u"Re: %(subject)s") % {'subject': parent.subject},
            'recipient': [parent.sender,]
            })
    return render_to_response(template_name, {
        'form': form,
        'success_url': success_url,
    }, context_instance=RequestContext(request))
reply = login_required(reply)

def delete(request, message_id, success_url=None):
    """
    Marks a message as deleted by sender or recipient. The message is not
    really removed from the database, because two users must delete a message
    before it's save to remove it completely.
    A cron-job should prune the database and remove old messages which are
    deleted by both users.
    As a side effect, this makes it easy to implement a trash with undelete.

    You can pass ?next=/foo/bar/ via the url to redirect the user to a different
    page (e.g. `/foo/bar/`) than ``success_url`` after deletion of the message.
    """
    user = request.user
    now = datetime.datetime.now()
    message = get_object_or_404(Message, id=message_id)
    deleted = False
    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.GET.has_key('next'):
        success_url = request.GET['next']
    if message.sender == user:
        message.sender_deleted_at = now
        deleted = True
    if message.recipient == user:
        message.recipient_deleted_at = now
        deleted = True
    if deleted:
        message.save()
        user.message_set.create(message=_(u"Message successfully deleted."))
        if notification:
            notification.send([user], "messages_deleted", {'message': message,})
        return HttpResponseRedirect(success_url)
    raise Http404
delete = login_required(delete)

def undelete(request, message_id, success_url=None):
    """
    Recovers a message from trash. This is achieved by removing the
    ``(sender|recipient)_deleted_at`` from the model.
    """
    user = request.user
    message = get_object_or_404(Message, id=message_id)
    undeleted = False
    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.GET.has_key('next'):
        success_url = request.GET['next']
    if message.sender == user:
        message.sender_deleted_at = None
        undeleted = True
    if message.recipient == user:
        message.recipient_deleted_at = None
        undeleted = True
    if undeleted:
        message.save()
        user.message_set.create(message=_(u"Message successfully recovered."))
        if notification:
            notification.send([user], "messages_recovered", {'message': message,})
        return HttpResponseRedirect(success_url)
    raise Http404
undelete = login_required(undelete)

def mark_as_read(request, message_id):
    if not request.is_ajax():
        raise Http404

    message = get_object_or_404(Message, id=message_id)

    if message.read_at is None and message.recipient == request.user:
        message.read_at = datetime.datetime.now()
        message.save()

    return HttpResponse()

def view(request, message_id, template_name='django_messages/view.html'):
    """
    Shows a single message.``message_id`` argument is required.
    The user is only allowed to see the message, if he is either
    the sender or the recipient. If the user is not allowed a 404
    is raised.
    If the user is the recipient and the message is unread
    ``read_at`` is set to the current datetime.
    """
    user = request.user
    now = datetime.datetime.now()
    message = get_object_or_404(Message, id=message_id)
    if (message.sender != user) and (message.recipient != user):
        raise Http404
    if message.read_at is None and message.recipient == user:
        message.read_at = now
        message.save()
    return render_to_response(template_name, {
        'message': message,
    }, context_instance=RequestContext(request))
view = login_required(view)
<commit_msg>Cleanup<commit_after>import datetime
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_noop
from django.core.urlresolvers import reverse
from django.conf import settings

from django_messages.models import Message
from django_messages.forms import ComposeForm
from django_messages.utils import format_quote

if "notification" in settings.INSTALLED_APPS:
    from notification import models as notification
else:
    notification = None

def inbox(request,
          template_name="django_messages/inbox.html",
          template_name_ajax="django_messages/inbox_ajax.html"):
    """
    Displays a list of received messages for the current user.
    Optional Arguments:
        ``template_name``: name of the template to use.
        ``template_name_ajax``: name of the template to use when view is called through ajax.
    """
    if request.is_ajax():
        template_name = template_name_ajax

    message_list = Message.objects.inbox_for(request.user)
    return render_to_response(template_name, {
        'message_list': message_list,
    }, context_instance=RequestContext(request))
inbox = login_required(inbox)

def outbox(request,
           template_name="django_messages/outbox.html",
           template_name_ajax="django_messages/outbox_ajax.html"):
    """
    Displays a list of sent messages by the current user.
    Optional arguments:
        ``template_name``: name of the template to use.
    """
    if request.is_ajax():
        template_name = template_name_ajax

    message_list = Message.objects.outbox_for(request.user)
    return render_to_response(template_name, {
        'message_list': message_list,
    }, context_instance=RequestContext(request))
outbox = login_required(outbox)

def trash(request,
          template_name="django_messages/trash.html",
          template_name_ajax="django_messages/trash_ajax.html"):
    """
    Displays a list of deleted messages.
    Optional arguments:
        ``template_name``: name of the template to use
        ``template_name_ajax``: the template to use if request is ajax
    Hint: A Cron-Job could periodicly clean up old messages, which are deleted
    by sender and recipient.
    """
    if request.is_ajax():
        template_name = template_name_ajax

    message_list = Message.objects.trash_for(request.user)
    return render_to_response(template_name, {
        'message_list': message_list,
    }, context_instance=RequestContext(request))
trash = login_required(trash)

def compose(request, recipient=None, form_class=ComposeForm,
            template_name='django_messages/compose.html',
            template_name_ajax='django_messages/compose_ajax.html',
            success_url=None, recipient_filter=None):
    """
    Displays and handles the ``form_class`` form to compose new messages.
    Required Arguments: None
    Optional Arguments:
        ``recipient``: username of a `django.contrib.auth` User, who should
                       receive the message, optionally multiple usernames
                       could be separated by a '+'
        ``form_class``: the form-class to use
        ``template_name``: the template to use
        ``template_name_ajax``: the template to use if request is ajax
        ``success_url``: where to redirect after successfull submission
    """
    if request.is_ajax():
        template_name = template_name_ajax

    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.REQUEST.has_key('next'):
        success_url = request.REQUEST['next']

    if request.method == "POST":
        sender = request.user
        form = form_class(request.POST, recipient_filter=recipient_filter)
        if form.is_valid():
            form.save(sender=request.user)
            request.user.message_set.create(
                message=_(u"Message successfully sent."))
            return HttpResponseRedirect(success_url)
    else:
        form = form_class()
        if recipient is not None:
            recipients = [u for u in User.objects.filter(username__in=[r.strip() for r in recipient.split('+')])]
            form.fields['recipient'].initial = recipients
    return render_to_response(template_name, {
        'form': form,
        'success_url': success_url
    }, context_instance=RequestContext(request))
compose = login_required(compose)

def reply(request, message_id, form_class=ComposeForm,
          template_name='django_messages/compose.html',
          template_name_ajax='django_messages/compose_ajax.html',
          success_url=None, recipient_filter=None, quote_helper=format_quote):
    """
    Prepares the ``form_class`` form for writing a reply to a given message
    (specified via ``message_id``). Uses the ``format_quote`` helper from
    ``messages.utils`` to pre-format the quote. To change the quote format
    assign a different ``quote_helper`` kwarg in your url-conf.

    """
    parent = get_object_or_404(Message, id=message_id)

    if request.is_ajax():
        template_name = template_name_ajax

    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.GET.has_key('next'):
        success_url = request.GET['next']

    if parent.sender != request.user and parent.recipient != request.user:
        raise Http404

    if request.method == "POST":
        sender = request.user
        form = form_class(request.POST, recipient_filter=recipient_filter)
        if form.is_valid():
            form.save(sender=request.user, parent_msg=parent)
            request.user.message_set.create(
                message=_(u"Message successfully sent."))
            return HttpResponseRedirect(success_url)
    else:
        form = form_class(initial={
            'body': quote_helper(parent.sender, parent.body),
            'subject': _(u"Re: %(subject)s") % {'subject': parent.subject},
            'recipient': [parent.sender,]
            })
    return render_to_response(template_name, {
        'form': form,
        'success_url': success_url,
    }, context_instance=RequestContext(request))
reply = login_required(reply)

def delete(request, message_id, success_url=None):
    """
    Marks a message as deleted by sender or recipient. The message is not
    really removed from the database, because two users must delete a message
    before it's save to remove it completely.
    A cron-job should prune the database and remove old messages which are
    deleted by both users.
    As a side effect, this makes it easy to implement a trash with undelete.

    You can pass ?next=/foo/bar/ via the url to redirect the user to a different
    page (e.g. `/foo/bar/`) than ``success_url`` after deletion of the message.
    """
    user = request.user
    now = datetime.datetime.now()
    message = get_object_or_404(Message, id=message_id)
    deleted = False
    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.GET.has_key('next'):
        success_url = request.GET['next']
    if message.sender == user:
        message.sender_deleted_at = now
        deleted = True
    if message.recipient == user:
        message.recipient_deleted_at = now
        deleted = True
    if deleted:
        message.save()
        user.message_set.create(message=_(u"Message successfully deleted."))
        if notification:
            notification.send([user], "messages_deleted", {'message': message,})
        return HttpResponseRedirect(success_url)
    raise Http404
delete = login_required(delete)

def undelete(request, message_id, success_url=None):
    """
    Recovers a message from trash. This is achieved by removing the
    ``(sender|recipient)_deleted_at`` from the model.
    """
    user = request.user
    message = get_object_or_404(Message, id=message_id)
    undeleted = False
    if success_url is None:
        success_url = reverse('messages_inbox')
    if request.GET.has_key('next'):
        success_url = request.GET['next']
    if message.sender == user:
        message.sender_deleted_at = None
        undeleted = True
    if message.recipient == user:
        message.recipient_deleted_at = None
        undeleted = True
    if undeleted:
        message.save()
        user.message_set.create(message=_(u"Message successfully recovered."))
        if notification:
            notification.send([user], "messages_recovered", {'message': message,})
        return HttpResponseRedirect(success_url)
    raise Http404
undelete = login_required(undelete)

def mark_as_read(request, message_id):
    if not request.is_ajax():
        raise Http404

    message = get_object_or_404(Message, id=message_id)

    if message.read_at is None and message.recipient == request.user:
        message.read_at = datetime.datetime.now()
        message.save()

    return HttpResponse()

@login_required
def view(request, message_id, template_name='django_messages/view.html'):
    """
    Shows a single message.``message_id`` argument is required.
    The user is only allowed to see the message, if he is either
    the sender or the recipient. If the user is not allowed a 404
    is raised.
    If the user is the recipient and the message is unread
    ``read_at`` is set to the current datetime.
    """
    user = request.user
    now = datetime.datetime.now()
    message = get_object_or_404(Message, id=message_id)
    if (message.sender != user) and (message.recipient != user):
        raise Http404
    if message.read_at is None and message.recipient == user:
        message.read_at = now
        message.save()
    return render_to_response(template_name, {
        'message': message,
    }, context_instance=RequestContext(request))

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# framework
from django.core.urlresolvers import reverse
from django.contrib import admin
from django.contrib.admin.views import main as admin_views
from django.utils.translation import ugettext as _
from django.http import Http404, HttpResponseRedirect

# module local
from . import models, forms, dataapi

class ChangeList(admin_views.ChangeList):
    @property
    def available_settings_models(self):
        return dataapi.data.type_names()

# Additional columns
def get_setting_value(obj):
    return dataapi.data.get(obj.name)
get_setting_value.short_description = _('Value')
# end

# Actions
def clear_cache(modeladmin, request, queryset):
    data = dataapi.data
    cache_keys = []
    add_key = cache_keys.append
    for name in queryset.values_list('name', flat=True):
        add_key(data.get._cache_key(name))
        add_key(data.exists._cache_key(name))
    data.cache.delete_many(cache_keys)
clear_cache.short_description = _("Clear cache for settings")
# end

class SettingAdmin(admin.ModelAdmin):
    model = models.Setting
    form = forms.SettingForm
    list_display = ('name', 'setting_type', get_setting_value)
    search_fields = ('name', 'setting_type__name')
    actions = [
        clear_cache
    ]

    def get_setting_model(self, obj, request):
        if obj:
            return obj.setting_object.__class__
        try:
            typename = request.REQUEST['typename']        # NOTE: both lines might
            return dataapi.data.model_for_name(typename)  # raise KeyError
        except KeyError:
            raise Http404

    def get_form(self, request, obj=None, **kwargs):
        Form = super(SettingAdmin, self).get_form(request, obj=obj, **kwargs)
        Form.setting_model = self.get_setting_model(obj, request)
        return Form

    def get_changelist(self, request, **kwargs):
        return ChangeList

    def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
        setting_model = self.get_setting_model(obj, request)
        context['setting_model_name'] = setting_model.__name__
        response = super(SettingAdmin, self).render_change_form(
            request, context, add=add, change=change, form_url=form_url, obj=obj)
        return response

    def _response_url(self, url, typename):
        return HttpResponseRedirect('%(url)s?typename=%(typename)s' % {
            'url': url,
            'typename': typename,
        })

    def response_add(self, request, obj, post_url_continue='../%s/'):
        response = super(SettingAdmin, self).response_add(
            request, obj, post_url_continue=post_url_continue)

        if '_addanother' in request.POST:
            typename = self.get_setting_model(obj, request).__name__
            return self._response_url(request.path, typename)

        return response

    def response_change(self, request, obj):
        response = super(SettingAdmin, self).response_change(request, obj)
        app_label = obj._meta.app_label
        module_name = obj._meta.module_name

        if '_addanother' in request.POST:
            url_name = 'admin:%s_%s_add' % (app_label, module_name)
            url = reverse(url_name, current_app=self.admin_site.name)
            typename = self.get_setting_model(obj, request).__name__
            return self._response_url(url, typename)

        return response

admin.site.register(models.Setting, SettingAdmin)
<commit_msg>admin: clear_cache action exception fix (closes #12)<commit_after># -*- coding: utf-8 -*-
# framework
from django.core.urlresolvers import reverse
from django.contrib import admin
from django.contrib.admin.views import main as admin_views
from django.utils.translation import ugettext as _
from django.http import Http404, HttpResponseRedirect

# module local
from . import models, forms, dataapi

class ChangeList(admin_views.ChangeList):
    @property
    def available_settings_models(self):
        return dataapi.data.type_names()

# Additional columns
def get_setting_value(obj):
    return dataapi.data.get(obj.name)
get_setting_value.short_description = _('Value')
# end

# Actions
def clear_cache(modeladmin, request, queryset):
    data = dataapi.data
    cache_keys = []
    add_key = cache_keys.append
    for name in queryset.values_list('name', flat=True):
        add_key(data.get._cache_key([name], {}))
        add_key(data.exists._cache_key([name], {}))
    data.cache.delete_many(cache_keys)
clear_cache.short_description = _("Clear cache for settings")
# end

class SettingAdmin(admin.ModelAdmin):
    model = models.Setting
    form = forms.SettingForm
    list_display = ('name', 'setting_type', get_setting_value)
    search_fields = ('name', 'setting_type__name')
    actions = [
        clear_cache
    ]

    def get_setting_model(self, obj, request):
        if obj:
            return obj.setting_object.__class__
        try:
            typename = request.REQUEST['typename']        # NOTE: both lines might
            return dataapi.data.model_for_name(typename)  # raise KeyError
        except KeyError:
            raise Http404

    def get_form(self, request, obj=None, **kwargs):
        Form = super(SettingAdmin, self).get_form(request, obj=obj, **kwargs)
        Form.setting_model = self.get_setting_model(obj, request)
        return Form

    def get_changelist(self, request, **kwargs):
        return ChangeList

    def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
        setting_model = self.get_setting_model(obj, request)
        context['setting_model_name'] = setting_model.__name__
        response = super(SettingAdmin, self).render_change_form(
            request, context, add=add, change=change, form_url=form_url, obj=obj)
        return response

    def _response_url(self, url, typename):
        return HttpResponseRedirect('%(url)s?typename=%(typename)s' % {
            'url': url,
            'typename': typename,
        })

    def response_add(self, request, obj, post_url_continue='../%s/'):
        response = super(SettingAdmin, self).response_add(
            request, obj, post_url_continue=post_url_continue)

        if '_addanother' in request.POST:
            typename = self.get_setting_model(obj, request).__name__
            return self._response_url(request.path, typename)

        return response

    def response_change(self, request, obj):
        response = super(SettingAdmin, self).response_change(request, obj)
        app_label = obj._meta.app_label
        module_name = obj._meta.module_name

        if '_addanother' in request.POST:
            url_name = 'admin:%s_%s_add' % (app_label, module_name)
            url = reverse(url_name, current_app=self.admin_site.name)
            typename = self.get_setting_model(obj, request).__name__
            return self._response_url(url, typename)

        return response

admin.site.register(models.Setting, SettingAdmin)
<|endoftext|>