<commit_before># Copyright 2013-2017 The Meson development team

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

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

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

# This file contains the detection logic for external dependencies useful for
# development purposes, such as testing, debugging, etc..

import os
import re

from .. import mlog
from .. import mesonlib
from ..mesonlib import version_compare, stringlistify, extract_as_list
from .base import (
    DependencyException, ExternalDependency, PkgConfigDependency,
    strip_system_libdirs, ConfigToolDependency,
)

class GTestDependency(ExternalDependency):
    def __init__(self, environment, kwargs):
        super().__init__('gtest', environment, 'cpp', kwargs)
        self.main = kwargs.get('main', False)
        self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src']
        self.detect()

    def detect(self):
        gtest_detect = self.clib_compiler.find_library("gtest", self.env, [])
        gtest_main_detect = self.clib_compiler.find_library("gtest_main", self.env, [])
        if gtest_detect and (not self.main or gtest_main_detect):
            self.is_found = True
            self.compile_args = []
            self.link_args = gtest_detect
            if self.main:
                self.link_args += gtest_main_detect
            self.sources = []
            self.prebuilt = True
        elif self.detect_srcdir():
            self.is_found = True
            self.compile_args = ['-I' + d for d in self.src_include_dirs]
            self.link_args = []
            if self.main:
                self.sources = [self.all_src, self.main_src]
            else:
                self.sources = [self.all_src]
            self.prebuilt = False
        else:
            self.is_found = False

    def detect_srcdir(self):
        for s in self.src_dirs:
            if os.path.exists(s):
                self.src_dir = s
                self.all_src = mesonlib.File.from_absolute_file(
                    os.path.join(self.src_dir, 'gtest-all.cc'))
                self.main_src = mesonlib.File.from_absolute_file(
                    os.path.join(self.src_dir, 'gtest_main.cc'))
                self.src_include_dirs = [os.path.normpath(os.path.join(self.src_dir, '..')),
                                         os.path.normpath(os.path.join(self.src_dir, '../include')),
                                         ]
                return True
        return False

    def need_threads(self):
        return True

    def log_info(self):
        if self.prebuilt:
            return 'prebuilt'
        else:
            return 'building self'

class GMockDependency(ExternalDependency):
    def __init__(self, environment, kwargs):
        super().__init__('gmock', environment, 'cpp', kwargs)
        # GMock may be a library or just source.
        # Work with both.
        gmock_detect = self.clib_compiler.find_library("gmock", self.env, [])
        if gmock_detect:
            self.is_found = True
            self.compile_args = []
            self.link_args = gmock_detect
            self.sources = []
            self.prebuilt = True
            return

        for d in ['/usr/src/googletest/googlemock/src', '/usr/src/gmock/src', '/usr/src/gmock']:
            if os.path.exists(d):
                self.is_found = True
                # Yes, we need both because there are multiple
                # versions of gmock that do different things.
                d2 = os.path.normpath(os.path.join(d, '..'))
                self.compile_args = ['-I' + d, '-I' + d2, '-I' + os.path.join(d2, 'include')]
                self.link_args = []
                all_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock-all.cc'))
                main_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock_main.cc'))
                if kwargs.get('main', False):
                    self.sources = [all_src, main_src]
                else:
                    self.sources = [all_src]
                self.prebuilt = False
                return

        self.is_found = False

    def log_info(self):
        if self.prebuilt:
            return 'prebuilt'
        else:
            return 'building self'

class LLVMDependency(ConfigToolDependency):
    """
    LLVM uses a special tool, llvm-config, which has arguments for getting
    c args, cxx args, and ldargs as well as version.
    """

    # Ordered list of llvm-config binaries to try. Start with base, then try
    # newest back to oldest (3.5 is arbitrary), and finally the devel version.
    # Please note that llvm-config-6.0 is a development snapshot and it should
    # not be moved to the beginning of the list. The only difference between
    # llvm-config-7 and llvm-config-devel is that the former is used by
    # Debian and the latter is used by FreeBSD.
    tools = [
        'llvm-config', # base
        'llvm-config-6.0', 'llvm-config60',
        'llvm-config-5.0', 'llvm-config50',
        'llvm-config-4.0', 'llvm-config40',
        'llvm-config-3.9', 'llvm-config39',
        'llvm-config-3.8', 'llvm-config38',
        'llvm-config-3.7', 'llvm-config37',
        'llvm-config-3.6', 'llvm-config36',
        'llvm-config-3.5', 'llvm-config35',
        'llvm-config-7',   'llvm-config-devel', # development snapshot
    ]
    tool_name = 'llvm-config'
    __cpp_blacklist = {'-DNDEBUG'}

    def __init__(self, environment, kwargs):
        # It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0
        # the C linker works fine if only using the C API.
        super().__init__('LLVM', environment, 'cpp', kwargs)
        self.provided_modules = []
        self.required_modules = set()
        self.module_details = []
        if not self.is_found:
            return
        self.static = kwargs.get('static', False)

        self.provided_modules = self.get_config_value(['--components'], 'modules')
        modules = stringlistify(extract_as_list(kwargs, 'modules'))
        self.check_components(modules)
        opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
        self.check_components(opt_modules, required=False)

        cargs = set(self.get_config_value(['--cppflags'], 'compile_args'))
        self.compile_args = list(cargs.difference(self.__cpp_blacklist))

        if version_compare(self.version, '>= 3.9'):
            self._set_new_link_args()
        else:
            self._set_old_link_args()
        self.link_args = strip_system_libdirs(environment, self.link_args)
        self.link_args = self.__fix_bogus_link_args(self.link_args)

    @staticmethod
    def __fix_bogus_link_args(args):
        """This function attempts to fix bogus link arguments that llvm-config
        generates.

        Currently it works around the following:
            - FreeBSD: when statically linking -l/usr/lib/libexecinfo.so will
              be generated, strip the -l in cases like this.
        """
        new_args = []
        for arg in args:
            if arg.startswith('-l') and arg.endswith('.so'):
                new_args.append(arg.lstrip('-l'))
            else:
                new_args.append(arg)
        return new_args

    def _set_new_link_args(self):
        """How to set linker args for LLVM versions >= 3.9"""
        if ((mesonlib.is_dragonflybsd() or mesonlib.is_freebsd()) and not
                self.static and version_compare(self.version, '>= 4.0')):
            # llvm-config on DragonFly BSD and FreeBSD for versions 4.0, 5.0,
            # and 6.0 have an error when generating arguments for shared mode
            # linking, even though libLLVM.so is installed, because for some
            # reason the tool expects to find a .so for each static library.
            # This works around that.
            self.link_args = self.get_config_value(['--ldflags'], 'link_args')
            self.link_args.append('-lLLVM')
            return
        link_args = ['--link-static', '--system-libs'] if self.static else ['--link-shared']
        self.link_args = self.get_config_value(
            ['--libs', '--ldflags'] + link_args + list(self.required_modules),
            'link_args')

    def _set_old_link_args(self):
        """Setting linker args for older versions of llvm.

        Old versions of LLVM bring an extra level of insanity with them.
        llvm-config will provide the correct arguments for static linking, but
        not for shared-linnking, we have to figure those out ourselves, because
        of course we do.
        """
        if self.static:
            self.link_args = self.get_config_value(
                ['--libs', '--ldflags', '--system-libs'] + list(self.required_modules),
                'link_args')
        else:
            # llvm-config will provide arguments for static linking, so we get
            # to figure out for ourselves what to link with. We'll do that by
            # checking in the directory provided by --libdir for a library
            # called libLLVM-<ver>.(so|dylib|dll)
            libdir = self.get_config_value(['--libdir'], 'link_args')[0]

            expected_name = 'libLLVM-{}'.format(self.version)
            re_name = re.compile(r'{}.(so|dll|dylib)'.format(expected_name))

            for file_ in os.listdir(libdir):
                if re_name.match(file_):
                    self.link_args = ['-L{}'.format(libdir),
                                      '-l{}'.format(os.path.splitext(file_.lstrip('lib'))[0])]
                    break
            else:
                raise DependencyException(
                    'Could not find a dynamically linkable library for LLVM.')

    def check_components(self, modules, required=True):
        """Check for llvm components (modules in meson terms).

        The required option is whether the module is required, not whether LLVM
        is required.
        """
        for mod in sorted(set(modules)):
            status = ''

            if mod not in self.provided_modules:
                if required:
                    self.is_found = False
                    if self.required:
                        raise DependencyException(
                            'Could not find required LLVM Component: {}'.format(mod))
                    status = '(missing)'
                else:
                    status = '(missing but optional)'
            else:
                self.required_modules.add(mod)

            self.module_details.append(mod + status)

    def need_threads(self):
        return True

    def log_details(self):
        if self.module_details:
            return 'modules: ' + ', '.join(self.module_details)
        return ''

class ValgrindDependency(PkgConfigDependency):
    '''
    Consumers of Valgrind usually only need the compile args and do not want to
    link to its (static) libraries.
    '''
    def __init__(self, env, kwargs):
        super().__init__('valgrind', env, kwargs)

    def get_link_args(self, **kwargs):
        return []
<commit_msg>Prefer pkgconfig for `GTestDependency`<commit_after># Copyright 2013-2017 The Meson development team

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

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

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

# This file contains the detection logic for external dependencies useful for
# development purposes, such as testing, debugging, etc..

import functools
import os
import re

from .. import mesonlib
from ..mesonlib import version_compare, stringlistify, extract_as_list
from .base import (
    DependencyException, DependencyMethods, ExternalDependency, PkgConfigDependency,
    strip_system_libdirs, ConfigToolDependency,
)

class GTestDependency(ExternalDependency):
    def __init__(self, environment, kwargs):
        super().__init__('gtest', environment, 'cpp', kwargs)
        self.main = kwargs.get('main', False)
        self.src_dirs = ['/usr/src/gtest/src', '/usr/src/googletest/googletest/src']
        self.detect()

    def detect(self):
        gtest_detect = self.clib_compiler.find_library("gtest", self.env, [])
        gtest_main_detect = self.clib_compiler.find_library("gtest_main", self.env, [])
        if gtest_detect and (not self.main or gtest_main_detect):
            self.is_found = True
            self.compile_args = []
            self.link_args = gtest_detect
            if self.main:
                self.link_args += gtest_main_detect
            self.sources = []
            self.prebuilt = True
        elif self.detect_srcdir():
            self.is_found = True
            self.compile_args = ['-I' + d for d in self.src_include_dirs]
            self.link_args = []
            if self.main:
                self.sources = [self.all_src, self.main_src]
            else:
                self.sources = [self.all_src]
            self.prebuilt = False
        else:
            self.is_found = False

    def detect_srcdir(self):
        for s in self.src_dirs:
            if os.path.exists(s):
                self.src_dir = s
                self.all_src = mesonlib.File.from_absolute_file(
                    os.path.join(self.src_dir, 'gtest-all.cc'))
                self.main_src = mesonlib.File.from_absolute_file(
                    os.path.join(self.src_dir, 'gtest_main.cc'))
                self.src_include_dirs = [os.path.normpath(os.path.join(self.src_dir, '..')),
                                         os.path.normpath(os.path.join(self.src_dir, '../include')),
                                         ]
                return True
        return False

    def need_threads(self):
        return True

    def log_info(self):
        if self.prebuilt:
            return 'prebuilt'
        else:
            return 'building self'

    @classmethod
    def _factory(cls, environment, kwargs):
        methods = cls._process_method_kw(kwargs)
        candidates = []

        if DependencyMethods.PKGCONFIG in methods:
            pcname = 'gtest_main' if kwargs.get('main', False) else 'gtest'
            candidates.append(functools.partial(PkgConfigDependency, pcname, environment, kwargs))

        if DependencyMethods.SYSTEM in methods:
            candidates.append(functools.partial(GTestDependency, environment, kwargs))

        return candidates

    @staticmethod
    def get_methods():
        return [DependencyMethods.PKGCONFIG, DependencyMethods.SYSTEM]

class GMockDependency(ExternalDependency):
    def __init__(self, environment, kwargs):
        super().__init__('gmock', environment, 'cpp', kwargs)
        # GMock may be a library or just source.
        # Work with both.
        gmock_detect = self.clib_compiler.find_library("gmock", self.env, [])
        if gmock_detect:
            self.is_found = True
            self.compile_args = []
            self.link_args = gmock_detect
            self.sources = []
            self.prebuilt = True
            return

        for d in ['/usr/src/googletest/googlemock/src', '/usr/src/gmock/src', '/usr/src/gmock']:
            if os.path.exists(d):
                self.is_found = True
                # Yes, we need both because there are multiple
                # versions of gmock that do different things.
                d2 = os.path.normpath(os.path.join(d, '..'))
                self.compile_args = ['-I' + d, '-I' + d2, '-I' + os.path.join(d2, 'include')]
                self.link_args = []
                all_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock-all.cc'))
                main_src = mesonlib.File.from_absolute_file(os.path.join(d, 'gmock_main.cc'))
                if kwargs.get('main', False):
                    self.sources = [all_src, main_src]
                else:
                    self.sources = [all_src]
                self.prebuilt = False
                return

        self.is_found = False

    def log_info(self):
        if self.prebuilt:
            return 'prebuilt'
        else:
            return 'building self'

class LLVMDependency(ConfigToolDependency):
    """
    LLVM uses a special tool, llvm-config, which has arguments for getting
    c args, cxx args, and ldargs as well as version.
    """

    # Ordered list of llvm-config binaries to try. Start with base, then try
    # newest back to oldest (3.5 is arbitrary), and finally the devel version.
    # Please note that llvm-config-6.0 is a development snapshot and it should
    # not be moved to the beginning of the list. The only difference between
    # llvm-config-7 and llvm-config-devel is that the former is used by
    # Debian and the latter is used by FreeBSD.
    tools = [
        'llvm-config', # base
        'llvm-config-6.0', 'llvm-config60',
        'llvm-config-5.0', 'llvm-config50',
        'llvm-config-4.0', 'llvm-config40',
        'llvm-config-3.9', 'llvm-config39',
        'llvm-config-3.8', 'llvm-config38',
        'llvm-config-3.7', 'llvm-config37',
        'llvm-config-3.6', 'llvm-config36',
        'llvm-config-3.5', 'llvm-config35',
        'llvm-config-7',   'llvm-config-devel', # development snapshot
    ]
    tool_name = 'llvm-config'
    __cpp_blacklist = {'-DNDEBUG'}

    def __init__(self, environment, kwargs):
        # It's necessary for LLVM <= 3.8 to use the C++ linker. For 3.9 and 4.0
        # the C linker works fine if only using the C API.
        super().__init__('LLVM', environment, 'cpp', kwargs)
        self.provided_modules = []
        self.required_modules = set()
        self.module_details = []
        if not self.is_found:
            return
        self.static = kwargs.get('static', False)

        self.provided_modules = self.get_config_value(['--components'], 'modules')
        modules = stringlistify(extract_as_list(kwargs, 'modules'))
        self.check_components(modules)
        opt_modules = stringlistify(extract_as_list(kwargs, 'optional_modules'))
        self.check_components(opt_modules, required=False)

        cargs = set(self.get_config_value(['--cppflags'], 'compile_args'))
        self.compile_args = list(cargs.difference(self.__cpp_blacklist))

        if version_compare(self.version, '>= 3.9'):
            self._set_new_link_args()
        else:
            self._set_old_link_args()
        self.link_args = strip_system_libdirs(environment, self.link_args)
        self.link_args = self.__fix_bogus_link_args(self.link_args)

    @staticmethod
    def __fix_bogus_link_args(args):
        """This function attempts to fix bogus link arguments that llvm-config
        generates.

        Currently it works around the following:
            - FreeBSD: when statically linking -l/usr/lib/libexecinfo.so will
              be generated, strip the -l in cases like this.
        """
        new_args = []
        for arg in args:
            if arg.startswith('-l') and arg.endswith('.so'):
                new_args.append(arg.lstrip('-l'))
            else:
                new_args.append(arg)
        return new_args

    def _set_new_link_args(self):
        """How to set linker args for LLVM versions >= 3.9"""
        if ((mesonlib.is_dragonflybsd() or mesonlib.is_freebsd()) and not
                self.static and version_compare(self.version, '>= 4.0')):
            # llvm-config on DragonFly BSD and FreeBSD for versions 4.0, 5.0,
            # and 6.0 have an error when generating arguments for shared mode
            # linking, even though libLLVM.so is installed, because for some
            # reason the tool expects to find a .so for each static library.
            # This works around that.
            self.link_args = self.get_config_value(['--ldflags'], 'link_args')
            self.link_args.append('-lLLVM')
            return
        link_args = ['--link-static', '--system-libs'] if self.static else ['--link-shared']
        self.link_args = self.get_config_value(
            ['--libs', '--ldflags'] + link_args + list(self.required_modules),
            'link_args')

    def _set_old_link_args(self):
        """Setting linker args for older versions of llvm.

        Old versions of LLVM bring an extra level of insanity with them.
        llvm-config will provide the correct arguments for static linking, but
        not for shared-linnking, we have to figure those out ourselves, because
        of course we do.
        """
        if self.static:
            self.link_args = self.get_config_value(
                ['--libs', '--ldflags', '--system-libs'] + list(self.required_modules),
                'link_args')
        else:
            # llvm-config will provide arguments for static linking, so we get
            # to figure out for ourselves what to link with. We'll do that by
            # checking in the directory provided by --libdir for a library
            # called libLLVM-<ver>.(so|dylib|dll)
            libdir = self.get_config_value(['--libdir'], 'link_args')[0]

            expected_name = 'libLLVM-{}'.format(self.version)
            re_name = re.compile(r'{}.(so|dll|dylib)'.format(expected_name))

            for file_ in os.listdir(libdir):
                if re_name.match(file_):
                    self.link_args = ['-L{}'.format(libdir),
                                      '-l{}'.format(os.path.splitext(file_.lstrip('lib'))[0])]
                    break
            else:
                raise DependencyException(
                    'Could not find a dynamically linkable library for LLVM.')

    def check_components(self, modules, required=True):
        """Check for llvm components (modules in meson terms).

        The required option is whether the module is required, not whether LLVM
        is required.
        """
        for mod in sorted(set(modules)):
            status = ''

            if mod not in self.provided_modules:
                if required:
                    self.is_found = False
                    if self.required:
                        raise DependencyException(
                            'Could not find required LLVM Component: {}'.format(mod))
                    status = '(missing)'
                else:
                    status = '(missing but optional)'
            else:
                self.required_modules.add(mod)

            self.module_details.append(mod + status)

    def need_threads(self):
        return True

    def log_details(self):
        if self.module_details:
            return 'modules: ' + ', '.join(self.module_details)
        return ''

class ValgrindDependency(PkgConfigDependency):
    '''
    Consumers of Valgrind usually only need the compile args and do not want to
    link to its (static) libraries.
    '''
    def __init__(self, env, kwargs):
        super().__init__('valgrind', env, kwargs)

    def get_link_args(self, **kwargs):
        return []
<|endoftext|>


<commit_before>#!/usr/bin/env python3
#
# Copyright (c) 2018 Aaron LI <aly@aaronly.me>
# MIT license
#

"""
Calculate the spectrograms of the FITS cube.

If the discrete Fourier transform (DFT/FFT) performed, output the real,
imaginary, and magnitude spectrograms.  If the discrete cosine transform
(DCT) performed, then output only the magnitude spectrogram since it's
real numbered.

The transform is applied along the frequency axis, while the two spatial
dimensions are flattened.
"""

import sys
import argparse
import logging

import numpy as np
from scipy import signal
from scipy import fftpack
from astropy.io import fits

logging.basicConfig(level=logging.INFO,
                    format="[%(levelname)s:%(lineno)d] %(message)s")
logger = logging.getLogger()

class Spectrogram:
    def __init__(self, cube):
        cube = np.array(cube, dtype=float)  # [Freq, Y, X]
        nfreq, ny, nx = cube.shape
        self.data = cube.reshape((nfreq, ny*nx))
        logger.info('Cube: %d frequencies, %d pixels' % self.data.shape)

    @property
    def nfreq(self):
        return self.data.shape[0]

    @property
    def npix(self):
        return self.data.shape[1]

    def set_window(self, window):
        if window.upper() == 'NONE':
            return
        logger.info('Generating %s window ...' % window)
        wfunc = getattr(signal.windows, window)
        w = wfunc(self.nfreq, sym=False)
        logger.info('Applying window ...')
        self.data *= w[:, np.newaxis]

    def calc_cosine(self):
        logger.info('Calculating DCT ...')
        return fftpack.dct(self.data, axis=0, norm='ortho')

    def calc_fourier(self):
        logger.info('Calculating FFT ...')
        z = fftpack.fftshift(fftpack.fft(self.data, axis=0), axis=0)
        return (np.abs(z), np.real(z), np.imag(z))

def main():
    parser = argparse.ArgumentParser(
        description='Calculate spectrogram of an image cube')
    parser.add_argument('-C', '--clobber', action='store_true')
    parser.add_argument('-w', '--window', required=True,
                        choices=['none', 'nuttall', 'hanning'],
                        help='window function')
    parser.add_argument('-t', '--type', required=True,
                        choices=['cosine', 'fourier'],
                        help='spectrogram type')
    parser.add_argument('-i', '--infile', required=True,
                        help='input image cube')
    parser.add_argument('-M', '--out-mag', dest='outmag', required=True,
                        help='output magnitude spectrogram')
    parser.add_argument('-R', '--out-real', dest='outreal',
                        help='output real spectrogram (type "fourier")')
    parser.add_argument('-I', '--out-imag', dest='outimag',
                        help='output imaginary spectrogram (type "fourier")')
    args = parser.parse_args()

    if args.type == 'fourier':
        assert (args.outreal and args.outimag), '--real and --imag required'

    cube = fits.open(args.infile)[0].data
    logger.info("Cube shape: %dx%dx%d" % cube.shape)

    header = fits.Header()
    header.add_history(' '.join(sys.argv))
    header['SP_TYPE'] = (args.type, 'cosine (DCT) or fourier (FFT)')

    spectrogram = Spectrogram(cube)
    spectrogram.set_window(args.window)
    header['SP_WIND'] = (args.window, 'window function along frequency')

    if args.type == 'cosine':
        sp_mag = spectrogram.calc_cosine()
        header['SP_DATA'] = 'magnitude'
        fits.PrimaryHDU(data=sp_mag, header=header).writeto(
            args.outmag, overwrite=args.clobber)
        logger.info('Wrote magnitude spectrogram to: %s' % args.outmag)
    else:
        sp_mag, sp_real, sp_imag = spectrogram.calc_fourier()
        header['SP_DATA'] = 'magnitude'
        fits.PrimaryHDU(data=sp_mag, header=header).writeto(
            args.outmag, overwrite=args.clobber)
        logger.info('Wrote magnitude spectrogram to: %s' % args.outmag)
        header['SP_DATA'] = 'real'
        fits.PrimaryHDU(data=sp_real, header=header).writeto(
            args.outreal, overwrite=args.clobber)
        logger.info('Wrote real spectrogram to: %s' % args.outreal)
        header['SP_DATA'] = 'imaginary'
        fits.PrimaryHDU(data=sp_imag, header=header).writeto(
            args.outimag, overwrite=args.clobber)
        logger.info('Wrote imaginary spectrogram to: %s' % args.outimag)

if __name__ == '__main__':
    main()
<commit_msg>astro/spectrogram.py: Fix the wrong argument in fftshift()<commit_after>#!/usr/bin/env python3
#
# Copyright (c) 2018 Aaron LI <aly@aaronly.me>
# MIT license
#

"""
Calculate the spectrograms of the FITS cube.

If the discrete Fourier transform (DFT/FFT) performed, output the real,
imaginary, and magnitude spectrograms.  If the discrete cosine transform
(DCT) performed, then output only the magnitude spectrogram since it's
real numbered.

The transform is applied along the frequency axis, while the two spatial
dimensions are flattened.
"""

import sys
import argparse
import logging

import numpy as np
from scipy import signal
from scipy import fftpack
from astropy.io import fits

logging.basicConfig(level=logging.INFO,
                    format="[%(levelname)s:%(lineno)d] %(message)s")
logger = logging.getLogger()

class Spectrogram:
    def __init__(self, cube):
        cube = np.array(cube, dtype=float)  # [Freq, Y, X]
        nfreq, ny, nx = cube.shape
        self.data = cube.reshape((nfreq, ny*nx))
        logger.info('Cube: %d frequencies, %d pixels' % self.data.shape)

    @property
    def nfreq(self):
        return self.data.shape[0]

    @property
    def npix(self):
        return self.data.shape[1]

    def set_window(self, window):
        if window.upper() == 'NONE':
            return
        logger.info('Generating %s window ...' % window)
        wfunc = getattr(signal.windows, window)
        w = wfunc(self.nfreq, sym=False)
        logger.info('Applying window ...')
        self.data *= w[:, np.newaxis]

    def calc_cosine(self):
        logger.info('Calculating DCT ...')
        return fftpack.dct(self.data, axis=0, norm='ortho')

    def calc_fourier(self):
        logger.info('Calculating FFT ...')
        z = fftpack.fftshift(fftpack.fft(self.data, axis=0), axes=0)
        return (np.abs(z), np.real(z), np.imag(z))

def main():
    parser = argparse.ArgumentParser(
        description='Calculate spectrogram of an image cube')
    parser.add_argument('-C', '--clobber', action='store_true')
    parser.add_argument('-w', '--window', required=True,
                        choices=['none', 'nuttall', 'hanning'],
                        help='window function')
    parser.add_argument('-t', '--type', required=True,
                        choices=['cosine', 'fourier'],
                        help='spectrogram type')
    parser.add_argument('-i', '--infile', required=True,
                        help='input image cube')
    parser.add_argument('-M', '--out-mag', dest='outmag', required=True,
                        help='output magnitude spectrogram')
    parser.add_argument('-R', '--out-real', dest='outreal',
                        help='output real spectrogram (type "fourier")')
    parser.add_argument('-I', '--out-imag', dest='outimag',
                        help='output imaginary spectrogram (type "fourier")')
    args = parser.parse_args()

    if args.type == 'fourier':
        assert (args.outreal and args.outimag), '--real and --imag required'

    cube = fits.open(args.infile)[0].data
    logger.info("Cube shape: %dx%dx%d" % cube.shape)

    header = fits.Header()
    header.add_history(' '.join(sys.argv))
    header['SP_TYPE'] = (args.type, 'cosine (DCT) or fourier (FFT)')

    spectrogram = Spectrogram(cube)
    spectrogram.set_window(args.window)
    header['SP_WIND'] = (args.window, 'window function along frequency')

    if args.type == 'cosine':
        sp_mag = spectrogram.calc_cosine()
        header['SP_DATA'] = 'magnitude'
        fits.PrimaryHDU(data=sp_mag, header=header).writeto(
            args.outmag, overwrite=args.clobber)
        logger.info('Wrote magnitude spectrogram to: %s' % args.outmag)
    else:
        sp_mag, sp_real, sp_imag = spectrogram.calc_fourier()
        header['SP_DATA'] = 'magnitude'
        fits.PrimaryHDU(data=sp_mag, header=header).writeto(
            args.outmag, overwrite=args.clobber)
        logger.info('Wrote magnitude spectrogram to: %s' % args.outmag)
        header['SP_DATA'] = 'real'
        fits.PrimaryHDU(data=sp_real, header=header).writeto(
            args.outreal, overwrite=args.clobber)
        logger.info('Wrote real spectrogram to: %s' % args.outreal)
        header['SP_DATA'] = 'imaginary'
        fits.PrimaryHDU(data=sp_imag, header=header).writeto(
            args.outimag, overwrite=args.clobber)
        logger.info('Wrote imaginary spectrogram to: %s' % args.outimag)

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


<commit_before>"""
    gui/filter
    ~~~~~~~~~~~~~~~~~~~~

    Graphical user interface for picasso.filter

    :author: Joerg Schnitzbauer, 2015
"""

import sys
import traceback
from PyQt4 import QtCore, QtGui
import h5py
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg
import matplotlib.pyplot as plt
import numpy as np
import os.path

plt.style.use('ggplot')

class TableModel(QtCore.QAbstractTableModel):

    def __init__(self, locs, parent=None):
        super().__init__(parent)
        self.locs = locs

    def columnCount(self, parent):
        return len(self.locs[0])

    def rowCount(self, parent):
        return self.locs.shape[0]

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            data = self.locs[index.row()][index.column()]
            return str(data)
        return None

    def headerData(self, section, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.locs.dtype.names[section]
            elif orientation == QtCore.Qt.Vertical:
                return section
        return None

class TableView(QtGui.QTableView):

    def __init__(self, window, parent=None):
        super().__init__(parent)
        self.window = window

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        event.accept()

    def dropEvent(self, event):
        urls = event.mimeData().urls()
        path = urls[0].toLocalFile()
        extension = os.path.splitext(path)[1].lower()
        if extension == '.hdf5':
            self.window.open(path)

class Window(QtGui.QMainWindow):

    def __init__(self):
        super().__init__()
        # Init GUI
        self.setWindowTitle('Picasso: Filter')
        self.resize(1100, 750)
        this_directory = os.path.dirname(os.path.realpath(__file__))
        icon_path = os.path.join(this_directory, 'filter.ico')
        icon = QtGui.QIcon(icon_path)
        self.setWindowIcon(icon)
        menu_bar = self.menuBar()
        file_menu = menu_bar.addMenu('File')
        open_action = file_menu.addAction('Open')
        open_action.setShortcut(QtGui.QKeySequence.Open)
        open_action.triggered.connect(self.open_file_dialog)
        file_menu.addAction(open_action)
        plot_menu = menu_bar.addMenu('Plot')
        histogram_action = plot_menu.addAction('Histogram')
        histogram_action.setShortcut('Ctrl+H')
        histogram_action.triggered.connect(self.plot_histogram)
        filter_menu = menu_bar.addMenu('Filter')
        self.table_view = TableView(self, self)
        self.table_view.setAcceptDrops(True)
        self.setCentralWidget(self.table_view)

    def open_file_dialog(self):
        path = QtGui.QFileDialog.getOpenFileName(self, 'Open localizations', filter='*.hdf5')
        if path:
            self.open(path)

    def open(self, path):
        with h5py.File(path) as hdf:
            self.locs = hdf['locs'][...]
        table_model = TableModel(self.locs, self)
        self.table_view.setModel(table_model)

    def plot_histogram(self):
        selection_model = self.table_view.selectionModel()
        indices = selection_model.selectedColumns()
        if len(indices) > 0:
            for index in indices:
                index = index.column()
                column = self.locs.dtype.names[index]
                data = self.locs[column]
                data = data[np.isfinite(data)]
                figure = plt.Figure()
                figure.suptitle(column)
                axes = figure.add_subplot(111)
                axes.hist(data, bins=int(len(self.locs)/1000))
                canvas = FigureCanvasQTAgg(figure)
                canvas.setWindowTitle('Histogram')
                canvas.show()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()

    def excepthook(type, value, tback):
        message = ''.join(traceback.format_exception(type, value, tback))
        errorbox = QtGui.QMessageBox.critical(window, 'An error occured', message)
        errorbox.exec_()
        sys.__excepthook__(type, value, tback)
    sys.excepthook = excepthook

    sys.exit(app.exec_())
<commit_msg>navigation bar in histogram window<commit_after>"""
    gui/filter
    ~~~~~~~~~~~~~~~~~~~~

    Graphical user interface for picasso.filter

    :author: Joerg Schnitzbauer, 2015
"""

import sys
import traceback
from PyQt4 import QtCore, QtGui
import h5py
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg, NavigationToolbar2QT
import matplotlib.pyplot as plt
import numpy as np
import os.path

plt.style.use('ggplot')

class TableModel(QtCore.QAbstractTableModel):

    def __init__(self, locs, parent=None):
        super().__init__(parent)
        self.locs = locs

    def columnCount(self, parent):
        return len(self.locs[0])

    def rowCount(self, parent):
        return self.locs.shape[0]

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            data = self.locs[index.row()][index.column()]
            return str(data)
        return None

    def headerData(self, section, orientation, role):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self.locs.dtype.names[section]
            elif orientation == QtCore.Qt.Vertical:
                return section
        return None

class TableView(QtGui.QTableView):

    def __init__(self, window, parent=None):
        super().__init__(parent)
        self.window = window

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        event.accept()

    def dropEvent(self, event):
        urls = event.mimeData().urls()
        path = urls[0].toLocalFile()
        extension = os.path.splitext(path)[1].lower()
        if extension == '.hdf5':
            self.window.open(path)

class Window(QtGui.QMainWindow):

    def __init__(self):
        super().__init__()
        # Init GUI
        self.setWindowTitle('Picasso: Filter')
        self.resize(1100, 750)
        this_directory = os.path.dirname(os.path.realpath(__file__))
        icon_path = os.path.join(this_directory, 'filter.ico')
        icon = QtGui.QIcon(icon_path)
        self.setWindowIcon(icon)
        menu_bar = self.menuBar()
        file_menu = menu_bar.addMenu('File')
        open_action = file_menu.addAction('Open')
        open_action.setShortcut(QtGui.QKeySequence.Open)
        open_action.triggered.connect(self.open_file_dialog)
        file_menu.addAction(open_action)
        plot_menu = menu_bar.addMenu('Plot')
        histogram_action = plot_menu.addAction('Histogram')
        histogram_action.setShortcut('Ctrl+H')
        histogram_action.triggered.connect(self.plot_histogram)
        filter_menu = menu_bar.addMenu('Filter')
        self.table_view = TableView(self, self)
        self.table_view.setAcceptDrops(True)
        self.setCentralWidget(self.table_view)

    def open_file_dialog(self):
        path = QtGui.QFileDialog.getOpenFileName(self, 'Open localizations', filter='*.hdf5')
        if path:
            self.open(path)

    def open(self, path):
        with h5py.File(path) as hdf:
            self.locs = hdf['locs'][...]
        table_model = TableModel(self.locs, self)
        self.table_view.setModel(table_model)

    def plot_histogram(self):
        selection_model = self.table_view.selectionModel()
        indices = selection_model.selectedColumns()
        if len(indices) > 0:
            for index in indices:
                index = index.column()
                column = self.locs.dtype.names[index]
                data = self.locs[column]
                data = data[np.isfinite(data)]
                figure = plt.Figure()
                figure.suptitle(column)
                axes = figure.add_subplot(111)
                axes.hist(data, bins=int(len(self.locs)/1000), rwidth=1, linewidth=0)
                window = QtGui.QWidget()
                vbox = QtGui.QVBoxLayout()
                window.setLayout(vbox)
                canvas = FigureCanvasQTAgg(figure)
                vbox.addWidget(canvas)
                vbox.addWidget(NavigationToolbar2QT(canvas, window))
                window.setWindowTitle('Histogram')
                window.show()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.show()

    def excepthook(type, value, tback):
        message = ''.join(traceback.format_exception(type, value, tback))
        errorbox = QtGui.QMessageBox.critical(window, 'An error occured', message)
        errorbox.exec_()
        sys.__excepthook__(type, value, tback)
    sys.excepthook = excepthook

    sys.exit(app.exec_())
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import unittest

import responses

from slacker import (
    API_BASE_URL,
    Channels,
)

class TestUtils(unittest.TestCase):
    @responses.activate
    def test_get_channel_id(self):
        response = {
            'ok': 'true',
            'channels': [
                {'name': 'general', 'id': 'C111'},
                {'name': 'random', 'id': 'C222'}
            ]
        }
        responses.add(
            responses.GET,
            API_BASE_URL.format(api='channels.list'),
            json=response,
            status=200
        )
        channels = Channels(token='aaa')
        self.assertEqual(
            'C111', channels.get_channel_id('general')
        )

    @responses.activate
    def test_get_channel_id_without_channel(self):
        response = {
            'ok': 'true',
            'channels': [
                {'name': 'general', 'id': 'C111'},
                {'name': 'random', 'id': 'C222'}
            ]
        }
        responses.add(
            responses.GET,
            API_BASE_URL.format(api='channels.list'),
            json=response,
            status=200
        )
        channels = Channels(token='aaa')
        self.assertEqual(
            None, channels.get_channel_id('fake_group')
        )
<commit_msg>Fix Yoda conditions<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import unittest

import responses

from slacker import (
    API_BASE_URL,
    Channels,
)

class TestUtils(unittest.TestCase):
    @responses.activate
    def test_get_channel_id(self):
        response = {
            'ok': 'true',
            'channels': [
                {'name': 'general', 'id': 'C111'},
                {'name': 'random', 'id': 'C222'}
            ]
        }
        responses.add(
            responses.GET,
            API_BASE_URL.format(api='channels.list'),
            json=response,
            status=200
        )
        channels = Channels(token='aaa')
        self.assertEqual(channels.get_channel_id('general'), 'C111')

    @responses.activate
    def test_get_channel_id_without_channel(self):
        response = {
            'ok': 'true',
            'channels': [
                {'name': 'general', 'id': 'C111'},
                {'name': 'random', 'id': 'C222'}
            ]
        }
        responses.add(
            responses.GET,
            API_BASE_URL.format(api='channels.list'),
            json=response,
            status=200
        )
        channels = Channels(token='aaa')
        self.assertEqual(channels.get_channel_id('fake_group'), None)
<|endoftext|>


<commit_before>"""
Report to show mapping of Places to each other, in a tree format.

Usage:
    $ python -m lib.query.place.tree
    # => print results to console.
"""
from lib import database as db

def printTree():
    """
    Print out data of all records in Place table.

    Records are grouped in a visual tree structure as child and parent objects.
    No items are repeated, except where two towns happen to have the same name
    in a minority of cases.

    There should only be one world record in Supername table, but allow
    for more.
    """
    supers = db.Supername.select()

    for s in supers:
        continents = s.hasContinents
        print("* {name} ({count} continents)".format(
            name=s.name,
            count=len(continents)
        ))

        for continent in continents:
            countries = continent.hasCountries
            print("  * {name} ({count} countries)".format(
                name=continent.name,
                count=len(countries)
            ))

            for country in countries:
                towns = country.hasTowns
                print("    * {name} ({count} towns)".format(
                    name=country.name,
                    count=len(towns)
                ))

                for town in towns:
                    print("      * {name}".format(name=town.name))

if __name__ == '__main__':
    printTree()
<commit_msg>refactor: Update tree.py<commit_after>"""
Report to show mapping of Places to each other, in a tree format.

Usage:
    $ python -m lib.db_query.place.tree
    # => print results to console.
"""
from lib import database as db

def printTree():
    """
    Print out data of all records in Place table.

    Records are grouped in a visual tree structure as child and parent objects.
    No items are repeated, except where two towns happen to have the same name
    in a minority of cases.

    There should only be one world record in Supername table, but allow
    for more.
    """
    supers = db.Supername.select()

    for s in supers:
        continents = s.hasContinents
        print("* {name} ({count} continents)".format(
            name=s.name,
            count=len(continents)
        ))

        for continent in continents:
            countries = continent.hasCountries
            print(f"  * {continent.name} ({len(countries)} countries)")

            for country in countries:
                towns = country.hasTowns
                print(f"    * {country.name} ({len(towns)} towns)")

                for town in towns:
                    print("      * {town.name}")

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


<commit_before>#!/usr/bin/python
#
# Copyright (c) 2010 rPath, Inc.
#
# This program is distributed under the terms of the Common Public License,
# version 1.0. A copy of this license should have been distributed with this
# source file in a file called LICENSE. If it is not present, the license
# is always available at http://www.rpath.com/permanent/licenses/CPL-1.0.
#
# This program is distributed in the hope that it will be useful, but
# without any warranty; without even the implied warranty of merchantability
# or fitness for a particular purpose. See the Common Public License for
# full details.
#

import codecs
import os
import sys
import textwrap
import time
from mercurial import hg, ui

PRODUCT_NAME = "Conary Policy"
HEADINGS = [
        ('feature', 'New Features'),
        ('bugfix', 'Bug Fixes'),
        ('internal', 'Internal Changes'),
        ]
KINDS = set(x[0] for x in HEADINGS)
NEWSDIR = 'NEWS.src'

def main():
    rootdir = os.path.realpath(__file__ + '/../..')
    os.chdir(rootdir)

    if not os.path.isdir(NEWSDIR):
        sys.exit("Can't find news directory")

    repo = hg.repository(ui.ui(), '.')

    args = sys.argv[1:]
    if args:
        command = args.pop(0)
    else:
        command = 'preview'

    if command == 'generate':
        generate(repo)
    elif command == 'preview':
        out, htmlOut, _ = preview(repo)
        print 'Text Version:\n'
        for line in out:
            print line
        print 'Html Version:\n'
        for line in htmlOut:
            print line
    else:
        sys.exit("Usage: %s <preview|generate>" % sys.argv[0])

def preview(repo, modifiedOK=True):
    mod, add, rem, del_, unk, ign, cln = repo.status(clean=True)
    ok = set(cln)
    bad = set(mod + add + rem + del_)

    kind_map = {}
    files = set()
    for filename in os.listdir(NEWSDIR):
        path = '/'.join((NEWSDIR, filename))
        if filename[0] == '.' or '.' not in filename:
            continue
        issue, kind = filename.rsplit('.', 1)
        if kind not in KINDS:
            print >> sys.stderr, "Ignoring '%s' due to unknown type '%s'" % (
                    filename, kind)
            continue

        if path in bad:
            if modifiedOK:
                print >> sys.stderr, "warning: '%s' is modified." % (path,)
                modified = time.time()
            else:
                sys.exit("File '%s' is modified and must be committed first." %
                        (path,))
        elif path not in ok:
            if modifiedOK:
                print >> sys.stderr, "warning: '%s' is not checked in." % (
                        path,)
                modified = time.time()
            else:
                sys.exit("File '%s' is not checked in and must be "
                        "committed first." % (path,))
        else:
            files.add(path)
            modified = _lastModified(repo, path)

        entries = [x.replace('\n', ' ') for x in
                   codecs.open(path, 'r', 'utf8').read().split('\n\n')]
        for n, line in enumerate(entries):
            entry = line.strip()
            if entry:
                kind_map.setdefault(kind, []).append((modified, issue, n,
                    entry))

    out = ['Changes in %s:' % _getVersion()]
    htmlOut = ['
%s %s is a maintainence release
' % (PRODUCT_NAME,
                                                           _getVersion())]
    for kind, heading in HEADINGS:
        entries = kind_map.get(kind, ())
        if not entries:
            continue
        out.append('  o %s:' % heading)
        htmlOut.append('%s:' % heading)
        htmlOut.append("
")
        for _, issue, _, entry in sorted(entries):
            htmlEntry = '
' + entry
            if not issue.startswith('misc-'):
                entry += ' (%s)' % issue
                htmlEntry += ' (%s)' % (issue,issue)
            lines = textwrap.wrap(entry, 66)
            out.append('    * %s' % (lines.pop(0),))
            for line in lines:
                out.append('      %s' % (line,))
            htmlEntry += '
'
            htmlOut.append(htmlEntry)
        out.append('')
        htmlOut.append('
')
    return out, htmlOut, files

def generate(repo):
    version = _getVersion()
    old = open('NEWS').read()
    if '@NEW@' in old:
        sys.exit("error: NEWS contains a @NEW@ section")
    elif ('Changes in %s:' % version) in old:
        sys.exit("error: NEWS already contains a %s section" % version)

    lines, htmlLines, files = preview(repo, modifiedOK=False)
    new = '\n'.join(lines) + '\n'
    newHtml = '\n'.join(htmlLines) + '\n'

    doc = new + old
    open('NEWS', 'w').write(doc)
    open('NEWS.html', 'w').write(newHtml)

    sys.stdout.write(new)
    print >> sys.stderr, "Updated NEWS"
    print >> sys.stderr, "Wrote NEWS.html"

    repo.remove(files, unlink=True)
    print >> sys.stderr, "Deleted %s news fragments" % len(files)

def _lastModified(repo, path):
    filenodes = []
    for cp in repo[None].parents():
        if not cp:
            continue
        filenodes.append(cp.filenode(path))
    assert len(filenodes) == 1
    fl = repo.file(path)
    ctx = repo[fl.linkrev(fl.rev(filenodes[0]))]
    return ctx.date()[0]

def _getVersion():
    f = os.popen("make show-version")
    return f.read().strip()

main()
<commit_msg>Update news script<commit_after>#!/usr/bin/python
#
# Copyright (c) 2010 rPath, Inc.
#
# This program is distributed under the terms of the Common Public License,
# version 1.0. A copy of this license should have been distributed with this
# source file in a file called LICENSE. If it is not present, the license
# is always available at http://www.rpath.com/permanent/licenses/CPL-1.0.
#
# This program is distributed in the hope that it will be useful, but
# without any warranty; without even the implied warranty of merchantability
# or fitness for a particular purpose. See the Common Public License for
# full details.
#

import codecs
import os
import re
import sys
import textwrap
import time
from mercurial import hg, ui

PRODUCT_NAME = "Conary Policy"
HEADINGS = [
        ('feature', 'New Features'),
        ('api', 'API Changes'),
        ('bugfix', 'Bug Fixes'),
        ('internal', 'Internal Changes'),
        ]
KINDS = set(x[0] for x in HEADINGS)
NEWSDIR = 'NEWS.src'

RE_ISSUE = re.compile('^[A-Z0-9]+-\d+')

def main():
    rootdir = os.path.realpath(__file__ + '/../..')
    os.chdir(rootdir)

    if not os.path.isdir(NEWSDIR):
        sys.exit("Can't find news directory")

    repo = hg.repository(ui.ui(), '.')

    args = sys.argv[1:]
    if args:
        command = args.pop(0)
    else:
        command = 'preview'

    if command == 'generate':
        generate(repo)
    elif command == 'preview':
        out, htmlOut, _ = preview(repo)
        print 'Text Version:\n'
        for line in out:
            print line
        print 'Html Version:\n'
        for line in htmlOut:
            print line
    else:
        sys.exit("Usage: %s <preview|generate>" % sys.argv[0])

def preview(repo, modifiedOK=True):
    mod, add, rem, del_, unk, ign, cln = repo.status(clean=True)
    ok = set(cln)
    bad = set(mod + add + rem + del_)

    kind_map = {}
    files = set()
    for filename in os.listdir(NEWSDIR):
        path = '/'.join((NEWSDIR, filename))
        if filename[0] == '.' or '.' not in filename:
            continue
        issue, kind = filename.rsplit('.', 1)
        if kind not in KINDS:
            print >> sys.stderr, "Ignoring '%s' due to unknown type '%s'" % (
                    filename, kind)
            continue

        if path in bad:
            if modifiedOK:
                print >> sys.stderr, "warning: '%s' is modified." % (path,)
                modified = time.time()
            else:
                sys.exit("File '%s' is modified and must be committed first." %
                        (path,))
        elif path not in ok:
            if modifiedOK:
                print >> sys.stderr, "warning: '%s' is not checked in." % (
                        path,)
                modified = time.time()
            else:
                sys.exit("File '%s' is not checked in and must be "
                        "committed first." % (path,))
        else:
            files.add(path)
            modified = _firstModified(repo, path)

        entries = [x.replace('\n', ' ') for x in
                   codecs.open(path, 'r', 'utf8').read().split('\n\n')]
        for n, line in enumerate(entries):
            entry = line.strip()
            if entry:
                kind_map.setdefault(kind, []).append((modified, issue, n,
                    entry))

    out = ['Changes in %s:' % _getVersion()]
    htmlOut = ['
%s %s is a maintenance release
' % (PRODUCT_NAME,
                                                           _getVersion())]
    for kind, heading in HEADINGS:
        entries = kind_map.get(kind, ())
        if not entries:
            continue
        out.append('  o %s:' % heading)
        htmlOut.append('%s:' % heading)
        htmlOut.append("
")
        for _, issue, _, entry in sorted(entries):
            htmlEntry = '
' + entry
            if RE_ISSUE.match(issue):
                entry += ' (%s)' % issue
                htmlEntry += ' (%s)' % (issue,issue)
            lines = textwrap.wrap(entry, 66)
            out.append('    * %s' % (lines.pop(0),))
            for line in lines:
                out.append('      %s' % (line,))
            htmlEntry += '
'
            htmlOut.append(htmlEntry)
        out.append('')
        htmlOut.append('
')
    return out, htmlOut, files

def generate(repo):
    version = _getVersion()
    old = codecs.open('NEWS', 'r', 'utf8').read()
    if '@NEW@' in old:
        sys.exit("error: NEWS contains a @NEW@ section")
    elif ('Changes in %s:' % version) in old:
        sys.exit("error: NEWS already contains a %s section" % version)

    lines, htmlLines, files = preview(repo, modifiedOK=False)
    new = '\n'.join(lines) + '\n'
    newHtml = '\n'.join(htmlLines) + '\n'

    doc = new + old
    codecs.open('NEWS', 'w', 'utf8').write(doc)
    codecs.open('NEWS.html', 'w', 'utf8').write(newHtml)

    sys.stdout.write(new)
    print >> sys.stderr, "Updated NEWS"
    print >> sys.stderr, "Wrote NEWS.html"

    wlock = repo.wlock()
    try:
        for name in files:
            os.unlink(name)
            repo.dirstate.remove(name)
    finally:
        wlock.release()
    print >> sys.stderr, "Deleted %s news fragments" % len(files)

def _firstModified(repo, path):
    fl = repo.file(path)
    ctx = repo[fl.linkrev(0)]
    return ctx.date()[0]

def _getVersion():
    f = os.popen("make show-version")
    return f.read().strip()

main()
<|endoftext|>


<commit_before>from core.data_structures.vector import Vector
from core.drawing.drawing_consts import LIGHT_OFFSET, LIGHT_RADIUS
from core.drawing.drawing_helpers import draw_circle
from core.drawing.drawing_consts import GREEN, RED
from collections import namedtuple

"""Structure for lists of colors"""
RoadSizeVector = namedtuple('ColorsVector', ['top', 'left', 'bottom', 'right'])

class LightsPainter:
    def __init__(self, top_location, left_location, bottom_location, right_location):
        """
        :param top_location: upper lights location start
        :param left_location: left lights location start
        :param bottom_location: bottom lights location start
        :param right_location: right lights location start
        :type top_location: Vector
        :type left_location: Vector
        :type bottom_location: Vector
        :type right_location: Vector
        """
        self.__top_vector = Vector(0, -(LIGHT_OFFSET + LIGHT_RADIUS))
        self.__left_vector = Vector(-(LIGHT_OFFSET + LIGHT_RADIUS), 0)
        self.__down_vector = Vector(0, (LIGHT_OFFSET + LIGHT_RADIUS))
        self.__right_vector = Vector((LIGHT_OFFSET + LIGHT_RADIUS), 0)

        self.__top_location = top_location + self.__top_vector + self.__left_vector
        self.__left_location = left_location + self.__down_vector + self.__left_vector
        self.__bottom_location = bottom_location + self.__down_vector + self.__right_vector
        self.__right_location = right_location + self.__top_vector + self.__right_vector

    def draw_empty(self, screen):
        self.__draw_top(screen)
        self.__draw_left(screen)
        self.__draw_bottom(screen)
        self.__draw_right(screen)

    def __draw_top(self, screen, array=[GREEN]):
        """

        :param screen:
        :param array:
        :type array: list[tuple[tuple(int,int,int),int]]
        :return:
        """
        draw_circle(screen, self.__top_location, LIGHT_RADIUS)

    def __draw_left(self, screen, array=[GREEN, RED, GREEN]):
        """

        :param screen:
        :param array:
        :type array: list[tuple[tuple(int,int,int),int]]
        :return:
        """
        curr_location = self.__left_location.copy()
        for color in array:
            draw_circle(screen, curr_location, LIGHT_RADIUS, color)
            curr_location += self.__down_vector * 2

    def __draw_bottom(self, screen, array=[GREEN, GREEN]):
        """

        :param screen:
        :param array:
        :type array: list[tuple[tuple(int,int,int),int]]
        :return:
        """
        curr_location = self.__bottom_location.copy()
        for color in array:
            draw_circle(screen, curr_location, LIGHT_RADIUS, color)
            curr_location += self.__right_vector * 2

    def __draw_right(self, screen, array=[GREEN]):
        """

        :param screen:
        :param array:
        :type array: list[tuple[tuple(int,int,int),int]]
        :return:
        """
        draw_circle(screen, self.__right_location, LIGHT_RADIUS)

    def refresh(self, screen, colors_vector):
        """
        Draws all lights
        :param screen:
        :param colors_vector:
        :type colors_vector: RoadSizeVector
        :return:
        """
<commit_msg>RoadColorsVector name fix<commit_after>from core.data_structures.vector import Vector
from core.drawing.drawing_consts import LIGHT_OFFSET, LIGHT_RADIUS
from core.drawing.drawing_helpers import draw_circle
from core.drawing.drawing_consts import GREEN, RED
from collections import namedtuple

"""Structure for lists of colors"""
RoadColorsVector = namedtuple('ColorsVector', ['top', 'left', 'bottom', 'right'])

class LightsPainter:
    def __init__(self, top_location, left_location, bottom_location, right_location):
        """
        :param top_location: upper lights location start
        :param left_location: left lights location start
        :param bottom_location: bottom lights location start
        :param right_location: right lights location start
        :type top_location: Vector
        :type left_location: Vector
        :type bottom_location: Vector
        :type right_location: Vector
        """
        self.__top_vector = Vector(0, -(LIGHT_OFFSET + LIGHT_RADIUS))
        self.__left_vector = Vector(-(LIGHT_OFFSET + LIGHT_RADIUS), 0)
        self.__down_vector = Vector(0, (LIGHT_OFFSET + LIGHT_RADIUS))
        self.__right_vector = Vector((LIGHT_OFFSET + LIGHT_RADIUS), 0)

        self.__top_location = top_location + self.__top_vector + self.__left_vector
        self.__left_location = left_location + self.__down_vector + self.__left_vector
        self.__bottom_location = bottom_location + self.__down_vector + self.__right_vector
        self.__right_location = right_location + self.__top_vector + self.__right_vector

    def draw_empty(self, screen):
        self.__draw_top(screen)
        self.__draw_left(screen)
        self.__draw_bottom(screen)
        self.__draw_right(screen)

    def __draw_top(self, screen, array=[GREEN]):
        """

        :param screen:
        :param array:
        :type colors_vector: RoadColorsVector
        :return:
        """
        draw_circle(screen, self.__top_location, LIGHT_RADIUS)

    def __draw_left(self, screen, array=[GREEN, RED, GREEN]):
        """

        :param screen:
        :param array:
        :type colors_vector: RoadColorsVector
        :return:
        """
        curr_location = self.__left_location.copy()
        for color in array:
            draw_circle(screen, curr_location, LIGHT_RADIUS, color)
            curr_location += self.__down_vector * 2

    def __draw_bottom(self, screen, array=[GREEN, GREEN]):
        """

        :param screen:
        :param array:
        :type colors_vector: RoadColorsVector
        :return:
        """
        curr_location = self.__bottom_location.copy()
        for color in array:
            draw_circle(screen, curr_location, LIGHT_RADIUS, color)
            curr_location += self.__right_vector * 2

    def __draw_right(self, screen, array=[GREEN]):
        """

        :param screen:
        :param array:
        :type colors_vector: RoadColorsVector
        :return:
        """
        draw_circle(screen, self.__right_location, LIGHT_RADIUS)

    def refresh(self, screen, colors_vector):
        """
        Draws all lights
        :param screen:
        :param colors_vector:
        :type colors_vector: RoadColorsVector
        :return:
        """
<|endoftext|>


<commit_before>"""voting models."""

import os
import re
import uuid

from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone

SECRET_LENGTH = 8 # Length in bytes of the Election.secret field.

def _validate_messageid(value):
    """Validate value as a Usenet Message-ID."""
    if len(value) > 250 or not re.match(r"""
            <
            [-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+
            (?:\.[-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+)*
            @
            (?:
                [-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+
                (?:\.[-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+)*
            |
                \[[!-=?-Z^-~]*\]
            )
            >$
            """, value, re.VERBOSE):
        raise ValidationError("Enter a valid Message-ID.", code="invalid")

class MessageIDField(models.CharField):
    """Field type to accept and validate Usenet Message-IDs."""
    default_validators = [_validate_messageid]
    description = "Usenet Message-ID"

    def __init__(self, *args, **kwargs):
        # max_length=250 to be compliant with RFC 5536 s3.1.3
        kwargs["max_length"] = kwargs.get("max_length", 250)
        super().__init__(*args, **kwargs)

class Votetaker(models.Model):
    """Votetaker model - effectively an extension to the django user."""
    user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True)
    role = models.CharField(
        max_length=128, blank=True,
        help_text="The votetaker's 'job title', if any.")
    public_email = models.EmailField(
        blank=True,
        help_text="If specified, this is the email address that will be"
        " displayed on public pages. Otherwise, the django User email"
        " address will be used.")
    contact = models.TextField(
        blank=True,
        help_text="Private contact details for the votetaker. These will"
        " never be displayed on any public pages.")

    def __str__(self):
        return self.user.get_full_name()

class Statement(models.Model):
    """Statement model."""
    title = models.CharField(max_length=254)
    slug = models.SlugField()
    release_date = models.DateField(db_index=True)
    msgid = MessageIDField(
        help_text="The Message-ID of the published statement.")
    statement = models.TextField(editable=False)

    class Meta:
        ordering = ("-release_date",)

def _generate_secret():
    """Generate a value for the 'Election.secret' field."""
    return os.urandom(SECRET_LENGTH)

def _validate_shortname(value):
    """Validate value as an Election.shortname."""
    if not re.match(r"[a-z][a-z0-9]{2,7}$", value):
        raise ValidationError(
            "Enter a valid short name (between 3 and 8 lower-case letters and"
            " numbers, starting with a letter.", code="invalid")

class Election(models.Model):
    """Election model."""
    SETUP = "setup"
    ACTIVE = "active"
    COUNT = "count"
    RESULT = "result"
    ABANDONED = "abandoned"
    title = models.CharField(max_length=254)
    shortname = models.CharField(
        "Short name", max_length=8, unique=True,
        validators=[_validate_shortname],
        help_text="This will be used as the username part of the email"
        " address for voters to request their ballot key.")
    votetaker = models.ForeignKey(Votetaker)
    secondary = models.ForeignKey(Votetaker, null=True, blank=True,
                                  related_name="secondary_election_set")
    votetype = models.CharField(
        max_length=64,
        help_text="This is just a helpful classification of what sort of"
        " election this is. Its value does not affect the operation of the"
        " election.")
    proposal = models.TextField(
        help_text="This text is displayed to the voter when they are filling"
        " in their vote. It should match the rationale, summary of discussion,"
        " changes from the last RFD, and proposal, from the CFV.")
    cfv_date = models.DateField(
        "CFV Date", blank=True, null=True, db_index=True,
        help_text="Votes received before this date will not be accepted.")
    cfv_end_date = models.DateField(
        "CFV end date", blank=True, null=True,
        help_text="Votes received after this date will not be accepted.")
    cfv_msgid = MessageIDField(
        blank=True,
        help_text="Fill this in with the Message-ID (including angle brackets)"
        " of the CFV once it appears.")
    cfv = models.TextField(editable=False)
    result_date = models.DateField(
        blank=True, null=True,
        help_text="Fill this in with the date the results posting appears.")
    result_msgid = MessageIDField(
        blank=True,
        help_text="Fill this in with the Message-ID (including angle brackets)"
        " of the results posting once it appears.")
    result = models.TextField(editable=False)
    uk_vote = models.BooleanField(
        "uk.* vote", default=True,
        help_text="Un-tick this box if this election is not an official uk.*"
        " election following a CFV in uk.net.news.announce.")
    hidden = models.BooleanField(
        default=False,
        help_text="Tick this box to hide this vote completely from public"
        " pages (e.g. for testing).")
    status = models.CharField(
        max_length=2, default=SETUP, choices=(
            (SETUP, "Setting up"),
            (ACTIVE, "Voting in progress"),
            (COUNT, "Counting in progress"),
            (RESULT, "Result issued"),
            (ABANDONED, "Abandoned"),
        ),
        help_text=" It is vital to keep this status up-to-date. If the election"
        " is not in the 'Voting in progress' status then votes will not be"
        " accepted.")
    secret = models.BinaryField(
        max_length=SECRET_LENGTH, default=_generate_secret)

    class Meta:
        ordering = ("-cfv_date",)

    def __str__(self):
        return self.title

    def accepting_votes(self):
        """Returns true if this election is currently accepting votes."""
        if (self.status != self.ACTIVE or not self.cfv_date or
                not self.cfv_end_date):
            return False
        today = timezone.now().date()
        return self.cfv_date <= today <= self.cfv_end_date

class Question(models.Model):
    """Question model."""
    YESNO = "yesno"
    STV = "stv"
    CONDORCET = "condorcet"
    FREEFORM = "freeform"
    election = models.ForeignKey(Election)
    question = models.CharField(
        max_length=254,
        help_text="The question the voter is answering.")
    method = models.CharField(
        max_length=16, choices=(
            (YESNO, "Yes/no"),
            (STV, "Single transferable vote"),
            (CONDORCET, "Condorcet"),
            (FREEFORM, "Free-form answer")
        ))
    details = models.TextField(
        blank=True,
        help_text="This text, if any, is displayed next to the question.")

    class Meta:
        order_with_respect_to = "election"

    def __str__(self):
        return self.question

class Choice(models.Model):
    """Choice model."""
    question = models.ForeignKey(Question)
    choice = models.CharField(max_length=254)

    def __str__(self):
        return self.choice

class Voter(models.Model):
    """Voter model."""
    key = models.UUIDField(default=uuid.uuid4, editable=False)
    election = models.ForeignKey(Election, editable=False)
    email = models.EmailField(
        db_index=True,
        help_text="The address the ballot key was emailed to.")
    creation_date = models.DateTimeField(
        auto_now_add=True,
        help_text="The date/time this voter first requested a ballot key for"
        " this election.")
    vote_date = models.DateTimeField(
        blank=True,
        help_text="The date/time of the most recent vote submitted by this"
        " voter for this election.")
    name = models.CharField(
        max_length=128, blank=True, db_index=True,
        help_text="The voter's 'name', as supplied by them.")
    posting_address = models.CharField(
        max_length=128, blank=True, db_index=True,
        help_text="The voter's 'usual posting address', as supplied by them.")
    comments = models.TextField(
        blank=True,
        help_text="Any additional comments added by the voter.")
    accepted = models.BooleanField(
        default=False,
        help_text="Tick to accept the vote.")
    notes = models.TextField(
        blank=True,
        help_text="Private notes by the votetaker.")
    email_headers = models.TextField(
        help_text="The headers of the first email received requesting"
        " a ballot key.")

    def __str__(self):
        return self.email

class VoterIPAddress(models.Model):
    """Model for the IP addresses seen in use by a voter."""
    voter = models.ForeignKey(Voter)
    creation_date = models.DateTimeField(auto_now_add=True)
    ip_address = models.GenericIPAddressField(
        "IP address", unpack_ipv4=True, db_index=True)
    fingerprint = models.CharField(max_length=128, db_index=True)
    headers = models.TextField("HTTP headers")
    asn_info = models.CharField("AS info", max_length=250, db_index=True)
    browser_info = models.TextField()

    def __str__(self):
        return str(self.ip_address)

class Vote(models.Model):
    """Vote model."""
    voter = models.ForeignKey(Voter)
    choice = models.ForeignKey(Choice)

    def __str__(self):
        return str(self.choice)
<commit_msg>Tidy up model field human-readable names<commit_after>"""voting models."""

import os
import re
import uuid

from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone

SECRET_LENGTH = 8 # Length in bytes of the Election.secret field.

def _validate_messageid(value):
    """Validate value as a Usenet Message-ID."""
    if len(value) > 250 or not re.match(r"""
            <
            [-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+
            (?:\.[-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+)*
            @
            (?:
                [-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+
                (?:\.[-0-9A-Za-z!#$%&'*+/=?^_`{|}~]+)*
            |
                \[[!-=?-Z^-~]*\]
            )
            >$
            """, value, re.VERBOSE):
        raise ValidationError("Enter a valid Message-ID.", code="invalid")

class MessageIDField(models.CharField):
    """Field type to accept and validate Usenet Message-IDs."""
    default_validators = [_validate_messageid]
    description = "Usenet Message-ID"

    def __init__(self, *args, **kwargs):
        # max_length=250 to be compliant with RFC 5536 s3.1.3
        kwargs["max_length"] = kwargs.get("max_length", 250)
        super().__init__(*args, **kwargs)

class Votetaker(models.Model):
    """Votetaker model - effectively an extension to the django user."""
    user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True)
    role = models.CharField(
        max_length=128, blank=True,
        help_text="The votetaker's 'job title', if any.")
    public_email = models.EmailField(
        blank=True,
        help_text="If specified, this is the email address that will be"
        " displayed on public pages. Otherwise, the django User email"
        " address will be used.")
    contact = models.TextField(
        blank=True,
        help_text="Private contact details for the votetaker. These will"
        " never be displayed on any public pages.")

    def __str__(self):
        return self.user.get_full_name()

class Statement(models.Model):
    """Statement model."""
    title = models.CharField(max_length=254)
    slug = models.SlugField()
    release_date = models.DateField(db_index=True)
    msgid = MessageIDField(
        "Message-ID",
        help_text="The Message-ID of the published statement.")
    statement = models.TextField(editable=False)

    class Meta:
        ordering = ("-release_date",)

def _generate_secret():
    """Generate a value for the 'Election.secret' field."""
    return os.urandom(SECRET_LENGTH)

def _validate_shortname(value):
    """Validate value as an Election.shortname."""
    if not re.match(r"[a-z][a-z0-9]{2,7}$", value):
        raise ValidationError(
            "Enter a valid short name (between 3 and 8 lower-case letters and"
            " numbers, starting with a letter.", code="invalid")

class Election(models.Model):
    """Election model."""
    SETUP = "setup"
    ACTIVE = "active"
    COUNT = "count"
    RESULT = "result"
    ABANDONED = "abandoned"
    title = models.CharField(max_length=254)
    shortname = models.CharField(
        "Short name", max_length=8, unique=True,
        validators=[_validate_shortname],
        help_text="This will be used as the username part of the email"
        " address for voters to request their ballot key.")
    votetaker = models.ForeignKey(Votetaker)
    secondary = models.ForeignKey(Votetaker, null=True, blank=True,
                                  related_name="secondary_election_set")
    votetype = models.CharField(
        "Vote type", max_length=64,
        help_text="This is just a helpful classification of what sort of"
        " election this is. Its value does not affect the operation of the"
        " election.")
    proposal = models.TextField(
        help_text="This text is displayed to the voter when they are filling"
        " in their vote. It should match the rationale, summary of discussion,"
        " changes from the last RFD, and proposal, from the CFV.")
    cfv_date = models.DateField(
        "CFV date", blank=True, null=True, db_index=True,
        help_text="Votes received before this date will not be accepted.")
    cfv_end_date = models.DateField(
        "CFV end date", blank=True, null=True,
        help_text="Votes received after this date will not be accepted.")
    cfv_msgid = MessageIDField(
        "CFV Message-ID", blank=True,
        help_text="Fill this in with the Message-ID (including angle brackets)"
        " of the CFV once it appears.")
    cfv = models.TextField("CFV", editable=False)
    result_date = models.DateField(
        blank=True, null=True,
        help_text="Fill this in with the date the results posting appears.")
    result_msgid = MessageIDField(
        "Result Message-ID", blank=True,
        help_text="Fill this in with the Message-ID (including angle brackets)"
        " of the results posting once it appears.")
    result = models.TextField(editable=False)
    uk_vote = models.BooleanField(
        "uk.* vote", default=True,
        help_text="Un-tick this box if this election is not an official uk.*"
        " election whose CFV will be posted in uk.net.news.announce.")
    hidden = models.BooleanField(
        default=False,
        help_text="Tick this box to hide this vote completely from public"
        " pages (e.g. for testing).")
    status = models.CharField(
        max_length=10, default=SETUP, choices=(
            (SETUP, "Setting up"),
            (ACTIVE, "Voting in progress"),
            (COUNT, "Counting in progress"),
            (RESULT, "Result issued"),
            (ABANDONED, "Abandoned"),
        ),
        help_text=" It is vital to keep this status up-to-date. If the election"
        " is not in the 'Voting in progress' status then votes will not be"
        " accepted.")
    secret = models.BinaryField(
        max_length=SECRET_LENGTH, default=_generate_secret)

    class Meta:
        ordering = ("-cfv_date",)

    def __str__(self):
        return self.title

    def accepting_votes(self):
        """Returns true if this election is currently accepting votes."""
        if (self.status != self.ACTIVE or not self.cfv_date or
                not self.cfv_end_date):
            return False
        today = timezone.now().date()
        return self.cfv_date <= today <= self.cfv_end_date

class Question(models.Model):
    """Question model."""
    YESNO = "yesno"
    STV = "stv"
    CONDORCET = "condorcet"
    FREEFORM = "freeform"
    election = models.ForeignKey(Election)
    question = models.CharField(
        max_length=254,
        help_text="The question the voter is answering.")
    method = models.CharField(
        max_length=16, choices=(
            (YESNO, "Yes/no"),
            (STV, "Single transferable vote"),
            (CONDORCET, "Condorcet"),
            (FREEFORM, "Free-form answer")
        ))
    details = models.TextField(
        blank=True,
        help_text="This text, if any, is displayed next to the question.")

    class Meta:
        order_with_respect_to = "election"

    def __str__(self):
        return self.question

class Choice(models.Model):
    """Choice model."""
    question = models.ForeignKey(Question)
    choice = models.CharField(max_length=254)

    def __str__(self):
        return self.choice

class Voter(models.Model):
    """Voter model."""
    key = models.UUIDField(default=uuid.uuid4, editable=False)
    election = models.ForeignKey(Election, editable=False)
    email = models.EmailField(
        db_index=True,
        help_text="The address the ballot key was emailed to.")
    creation_date = models.DateTimeField(
        auto_now_add=True,
        help_text="The date/time this voter first requested a ballot key for"
        " this election.")
    vote_date = models.DateTimeField(
        blank=True,
        help_text="The date/time of the most recent vote submitted by this"
        " voter for this election.")
    name = models.CharField(
        max_length=128, blank=True, db_index=True,
        help_text="The voter's 'name', as supplied by them.")
    posting_address = models.CharField(
        max_length=128, blank=True, db_index=True,
        help_text="The voter's 'usual posting address', as supplied by them.")
    comments = models.TextField(
        blank=True,
        help_text="Any additional comments added by the voter.")
    accepted = models.BooleanField(
        default=False,
        help_text="Tick to accept the vote.")
    notes = models.TextField(
        blank=True,
        help_text="Private notes by the votetaker.")
    email_headers = models.TextField(
        help_text="The headers of the first email received requesting"
        " a ballot key.")

    def __str__(self):
        return self.email

class VoterIPAddress(models.Model):
    """Model for the IP addresses seen in use by a voter."""
    voter = models.ForeignKey(Voter)
    creation_date = models.DateTimeField(auto_now_add=True)
    ip_address = models.GenericIPAddressField(
        "IP address", unpack_ipv4=True, db_index=True)
    fingerprint = models.CharField(max_length=128, db_index=True)
    headers = models.TextField("HTTP headers")
    asn_info = models.CharField("AS info", max_length=250, db_index=True)
    browser_info = models.TextField()

    def __str__(self):
        return str(self.ip_address)

class Vote(models.Model):
    """Vote model."""
    voter = models.ForeignKey(Voter)
    choice = models.ForeignKey(Choice)

    def __str__(self):
        return str(self.choice)
<|endoftext|>


<commit_before>import inspect
import urlparse

from redis import Redis as BaseRedis

__all__ = ('Redis', )

class Redis(BaseRedis):
    """
    Simple object to initialize redis client using settings from Flask
    application.
    """
    def __init__(self, app=None):
        """
        Overwrite default ``Redis.__init__`` method, read all necessary
        settings from Flask app config instead of positional and keyword args.

        The possible settings are:

        * REDIS_HOST
        * REDIS_PORT
        * REDIS_DB
        * REDIS_PASSWORD
        * REDIS_SOCKET_TIMEOUT
        * REDIS_CONNECTION_POOL
        * REDIS_CHARSET
        * REDIS_ERRORS
        * REDIS_UNIX_SOCKET_PATH

        You also could initialize ``Redis`` instance without sending ``app``
        object, but do this after with ``init_app`` method, like::

            from flask import Flask
            from flask.ext.redis import Redis

            app = Flask(__name__)

            redis = Redis()
            redis.init_app(app)

        .. warning:: Please note, if you'll initialize extension that way, make
           sure that before ``init_app`` call all real Redis method's would be
           return ``AttributeError`` exception cause of no ``connection_pool``
           attribute, which setup on ``Redis`` instance init.

        Advanced usage
        --------------

        If you want to use this extension on Heroku or other build services
        where redis URL stored in environment var you could to determine full
        URL to redis server.

        For example, for Heroku apps which used ``REDISTOGO_URL`` environ app,
        you'll need to update your project settings with::

            import os

            REDIS_URL = 'redis://localhost:6379/0'
            REDIS_URL = os.environ.get('REDISTOGO_URL', REDIS_URL)

        """
        if app is not None:
            self.init_app(app)

        setattr(self, '_flask_app', app)

    def init_app(self, app):
        """
        Actual method to read redis settings from app configuration.
        """
        converters = {'port': int}
        url = app.config.get('REDIS_URL')

        if url:
            urlparse.uses_netloc.append('redis')
            url = urlparse.urlparse(url)

            # URL could contains host, port, user, password and db
            # values. Store their to config
            app.config['REDIS_HOST'] = url.hostname
            app.config['REDIS_PORT'] = url.port
            app.config['REDIS_USER'] = url.username
            app.config['REDIS_PASSWORD'] = url.password
            db = url.path.replace('/', '')
            app.config['REDIS_DB'] = db if db.isdigit() else None

        spec = inspect.getargspec(BaseRedis.__init__)
        args = set(spec.args).difference(set(['self']))
        kwargs = {}

        for arg in args:
            redis_arg = 'REDIS_%s' % arg.upper()

            if not redis_arg in app.config:
                continue

            value = app.config.get(redis_arg)

            if arg in converters:
                value = converters[arg](value)

            kwargs.update({arg: value})

        super(Redis, self).__init__(**kwargs)
<commit_msg>Refactor ``Redis`` instance, implement ``config_prefix`` keyword argument for ``init_app``, do not inherit from ``redis.Redis`` class anymore, store redis connection in ``Redis.connection`` attribute.<commit_after>import inspect
import urlparse

from redis import Redis as BaseRedis

__all__ = ('Redis', )

class Redis(object):
    """
    Simple object to initialize redis client using settings from Flask
    application.
    """
    def __init__(self, app=None, config_prefix=None):
        """
        Overwrite default ``Redis.__init__`` method, read all necessary
        settings from Flask app config instead of positional and keyword args.

        The possible settings are:

        * REDIS_HOST
        * REDIS_PORT
        * REDIS_DB
        * REDIS_PASSWORD
        * REDIS_SOCKET_TIMEOUT
        * REDIS_CONNECTION_POOL
        * REDIS_CHARSET
        * REDIS_ERRORS
        * REDIS_UNIX_SOCKET_PATH

        You also could initialize ``Redis`` instance without sending ``app``
        object, but do this after with ``init_app`` method, like::

            from flask import Flask
            from flask.ext.redis import Redis

            app = Flask(__name__)

            redis = Redis()
            redis.init_app(app)

        .. warning:: Please note, if you'll initialize extension that way, make
           sure that before ``init_app`` call all real Redis method's would be
           return ``AttributeError`` exception cause of no ``connection_pool``
           attribute, which setup on ``Redis`` instance init.

        Advanced usage
        --------------

        If you want to use this extension on Heroku or other build services
        where redis URL stored in environment var you could to determine full
        URL to redis server.

        For example, for Heroku apps which used ``REDISTOGO_URL`` environ app,
        you'll need to update your project settings with::

            import os

            REDIS_URL = 'redis://localhost:6379/0'
            REDIS_URL = os.environ.get('REDISTOGO_URL', REDIS_URL)

        """
        if app is not None:
            self.init_app(app, config_prefix)

    def init_app(self, app, config_prefix=None):
        """
        Actual method to read redis settings from app configuration.
        """
        if not 'redis' in app.extensions:
            app.extensions['redis'] = {}

        self.config_prefix = config_prefix = config_prefix or 'REDIS'

        if config_prefix in app.extensions['redis']:
            raise ValueError('Already registered config prefix {0!r}.'.
                             format(config_prefix))

        converters = {'port': int}
        key = lambda suffix: u'{0}_{1}'.format(config_prefix, suffix)
        url = app.config.get(key('URL'))

        if url:
            urlparse.uses_netloc.append('redis')
            url = urlparse.urlparse(url)

            # URL could contains host, port, user, password and db
            # values. Store their to config
            app.config[key('HOST')] = url.hostname
            app.config[key('PORT')] = url.port
            app.config[key('USER')] = url.username
            app.config[key('PASSWORD')] = url.password
            db = url.path.replace('/', '')
            app.config[key('DB')] = db if db.isdigit() else None

        spec = inspect.getargspec(BaseRedis.__init__)
        args = set(spec.args).difference(set(['self']))
        kwargs = {}

        for arg in args:
            redis_arg = key(arg.upper())

            if not redis_arg in app.config:
                continue

            value = app.config.get(redis_arg)

            if arg in converters:
                value = converters[arg](value)

            kwargs.update({arg: value})

        self.connection = redis = BaseRedis(**kwargs)
        app.extensions['redis'][config_prefix] = redis

        self._include_redis_methods(redis)

    def _include_redis_methods(self, redis):
        """
        Include redis methods as current instance methods.
        """
        for attr in dir(redis):
            value = getattr(redis, attr)
            if attr.startswith('_') or not callable(value):
                continue
            self.__dict__[attr] = value
<|endoftext|>


<commit_before>from bolt import Bolt

#Creating all test cases

#Creating a client
client = Bolt('768d64d5-05b2-463b-95bc-98eedfc5abe7', 'BOLT3432361')

#Testing digitalWrite
result = client.digitalWrite('0','HIGH')

#Testing digitalRead
#result = client.digitalRead('0')

#Testing analogWrite
#result = client.analogWrite('A0','127')

#Testing analogRead
#result = client.analogRead('A0')

#Testing UART commands

#result = client.serialBegin('9600')
#result = client.serialRead('12')
#result = client.serialWrite('hello')

#Version check
#result = client.version()

#Device Restart
#result = client.restart()

#Device status
#result = client.isAlive()

print(result)
<commit_msg>Removing the reference file used for building the main testing file<commit_after><|endoftext|>