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

from __future__ import print_function, unicode_literals

import os
import sys
import re

import click

if __package__ is None:
    from __init__ import __version__
    from utils import command, CommandError, chdir, git, ProgError
else:
    from . import __version__
    from .utils import (command, CommandError, chdir, git, ProgError, decode_utf8,
                        current_branch)

click.disable_unicode_literals_warning = True

def echo(*args):
    click.echo(u' '.join(args))

def info(*args):
    click.secho(u' '.join(args), fg='blue')

def error(*args, **kwargs):
    click.secho(u' '.join(args), fg='red')
    exitcode = kwargs.get('exitcode', 1)
    if exitcode is not None:
        sys.exit(exitcode)

@click.group(context_settings={
    'allow_extra_args': True,
    'ignore_unknown_options': True,
    'help_option_names':['-h','--help'],
})
@click.version_option(__version__)
@click.option('--with-color/--no-color',
              default=True,
              help='Enable/disable colored output')
@click.pass_context
def cli(ctx, with_color):
    """Utility to manage git externals, meant to be used as a drop-in
    replacement to svn externals

    This script works by cloning externals found in the `git_externals.json`
    file into `.git/externals` and symlinks them to recreate the wanted
    directory layout.
    """
    from git_externals import is_git_repo, externals_json_path, externals_root_path

    if not is_git_repo():
        error("{} is not a git repository!".format(os.getcwd()), exitcode=2)

    if ctx.invoked_subcommand != 'add' and not os.path.exists(externals_json_path()):
        error("Unable to find", externals_json_path(), exitcode=1)

    if not os.path.exists(externals_root_path()):
        if ctx.invoked_subcommand not in set(['update', 'add']):
            error('You must first run git-externals update/add', exitcode=2)
    else:
        if with_color:
            enable_colored_output()

        if ctx.invoked_subcommand is None:
            gitext_st(())

@cli.command('foreach')
@click.option('--recursive/--no-recursive', help='If --recursive is specified, this command will recurse into nested externals', default=True)
@click.argument('subcommand', nargs=-1, required=True)
def gitext_foreach(recursive, subcommand):
    """Evaluates an arbitrary shell command in each checked out external
    """
    from git_externals import externals_sanity_check, get_repo_name, foreach_externals_dir, root_path

    externals_sanity_check()

    def run_command(rel_url, ext_path, targets):
        try:
            info("External {}".format(get_repo_name(rel_url)))
            output = decode_utf8(command(*subcommand))
            info("Ok: CWD: {}, cmd: {}".format(os.getcwd(), subcommand))
            echo(output)
        except CommandError as err:
            info("Command error {} CWD: {}, cmd: {}".format(err, os.getcwd(), subcommand))
            error(str(err), exitcode=err.errcode)

    foreach_externals_dir(root_path(), run_command, recursive=recursive)

@cli.command('update')
@click.option('--recursive/--no-recursive', help='Do not call git-externals update recursively', default=True)
@click.option('--gitsvn/--no-gitsvn', help='use git-svn (or simply svn) to checkout SVN repositories (only needed at first checkout)', default=True)
@click.option('--reset', help='Reset repo, overwrite local modifications', is_flag=True)
def gitext_update(recursive, gitsvn, reset):
    """Update the working copy cloning externals if needed and create the desired layout using symlinks
    """
    from git_externals import externals_sanity_check, root_path, is_workingtree_clean, foreach_externals, gitext_up

    externals_sanity_check()
    root = root_path()

    if reset:
        git('reset', '--hard')

    # Aggregate in a list the `clean flags` of all working trees (root + externals)
    clean = [is_workingtree_clean(root, fail_on_empty=False)]
    foreach_externals(root,
        lambda u, p, r: clean.append(is_workingtree_clean(p, fail_on_empty=False)),
        recursive=recursive)

    if reset or all(clean):
        # Proceed with update if everything is clean
        try:
            gitext_up(recursive, reset=reset, use_gitsvn=gitsvn)
        except ProgError as e:
            error(str(e), exitcode=e.errcode)
    else:
        echo("Cannot perform git externals update because one or more repositories contain some local modifications")
        echo("Run:\tgit externals status\tto have more information")

@cli.command('status')
@click.option(
    '--porcelain',
    is_flag=True,
    help='Print output using the porcelain format, useful mostly for scripts')
@click.option(
    '--verbose/--no-verbose',
    is_flag=True,
    help='Show the full output of git status, instead of showing only the modifications regarding tracked file')
@click.argument('externals', nargs=-1)
def gitext_st(porcelain, verbose, externals):
    """Call git status on the given externals"""
    from git_externals import foreach_externals_dir, root_path, \
                              is_workingtree_clean, get_repo_name

    def get_status(rel_url, ext_path, targets):
        try:
            if porcelain:
                echo(rel_url)
                click.echo(git('status', '--porcelain'))
            elif verbose or not is_workingtree_clean(ext_path):
                info("External {}".format(get_repo_name(rel_url)))
                echo(git('status', '--untracked-files=no' if not verbose else ''))
        except CommandError as err:
            error(str(err), exitcode=err.errcode)

    foreach_externals_dir(root_path(), get_status, recursive=True, only=externals)

@cli.command('diff')
@click.argument('external', nargs=-1)
def gitext_diff(external):
    """Call git diff on the given externals"""
    from git_externals import iter_externals
    for _ in iter_externals(external):
        click.echo(git('diff'))

@cli.command('add')
@click.argument('external',
                metavar='URL')
@click.argument('src', metavar='PATH')
@click.argument('dst', metavar='PATH')
@click.option('--branch', '-b', default=None, help='Checkout the given branch')
@click.option('--tag', '-t', default=None, help='Checkout the given tag')
@click.option('--ref', '-r', default=None, help='Checkout the given commit sha')
@click.option('--vcs', '-c', default='auto', help='Version Control System (default: autodetect)',
              type=click.Choice(['svn', 'git', 'auto']))
def gitext_add(external, src, dst, branch, tag, ref, vcs):
    """Add a git external to the current repo.

    Be sure to add '/' to `src` if it's a directory!
    It's possible to add multiple `dst` to the same `src`, however you cannot mix different branches, tags or refs
    for the same external.

    It's safe to use this command to add `src` to an already present external, as well as adding
    `dst` to an already present `src`.

    It requires one of --branch or --tag.
    """
    from git_externals import load_gitexts, dump_gitexts, normalize_gitexts, print_gitext_info

    git_externals = load_gitexts()

    if branch is None and tag is None:
        error('Please specifiy at least a branch or a tag', exitcode=3)

    if external not in git_externals:
        git_externals[external] = {'targets': {src: [dst]}}
        if branch is not None:
            git_externals[external]['branch'] = branch
            git_externals[external]['ref'] = ref
        else:
            git_externals[external]['tag'] = tag
        if vcs == 'auto':
            git_externals.update(normalize_gitexts({external: git_externals[external]}))
        else:
            git_externals[external]['vcs'] = vcs

    else:
        if branch is not None:
            if 'branch' not in git_externals[external]:
                error(
                    '{} is bound to tag {}, cannot set it to branch {}'.format(
                        external, git_externals[external]['tag'], branch),
                    exitcode=4)

            if ref != git_externals[external]['ref']:
                error('{} is bound to ref {}, cannot set it to ref {}'.format(
                    external, git_externals[external]['ref'], ref),
                    exitcode=4)

        elif 'tag' not in git_externals[external]:
            error('{} is bound to branch {}, cannot set it to tag {}'.format(
                external, git_externals[external]['branch'], tag),
                exitcode=4)

        if dst not in git_externals[external]['targets'].setdefault(src, []):
            git_externals[external]['targets'][src].append(dst)

    print_gitext_info(external, git_externals[external], root_dir='.')
    dump_gitexts(git_externals)

@cli.command('freeze')
@click.argument('externals', nargs=-1, metavar='NAME')
def gitext_freeze(externals):
    """Freeze the externals revision"""
    from git_externals import load_gitexts, dump_gitexts, foreach_externals_dir, root_path
    git_externals = load_gitexts()
    re_from_git_svn_id = re.compile("git-svn-id:.*@(\d+)")
    re_from_svnversion = re.compile("(\d+):(\d+)")

    def get_version(rel_url, ext_path, refs):
        if 'tag' in refs:
            return

        if git_externals[rel_url]["vcs"] == "svn":
            revision = command('svnversion', '-c').strip()
            match = re_from_svnversion.search(revision)
            if match:
                revision = "svn:r" + match.group(2)  # 565:56555 -> svn:r56555
            else:
                message = git("log", "--format=%b", "--grep", "git-svn-id:", "-1")
                match = re_from_git_svn_id.search(message)
                if match:
                    revision = "svn:r" + match.group(1)
                else:
                    error("Unsupported external format, should be svn or git-svn repo")
        else:
            branch_name = current_branch()
            remote_name = git("config", "branch.%s.remote" % branch_name)
            revision = git("log", "%s/%s" % (remote_name, branch_name), "-1", "--format=%H")

        info("Freeze {0} at {1}".format(rel_url, revision))
        git_externals[rel_url]["ref"] = revision

    foreach_externals_dir(root_path(), get_version, only=externals)

    dump_gitexts(git_externals)

@cli.command('remove')
@click.argument('external', nargs=-1, metavar='URL')
def gitext_remove(external):
    """Remove the externals at the given repository URLs """
    from git_externals import load_gitexts, dump_gitexts

    git_externals = load_gitexts()

    for ext in external:
        if ext in git_externals:
            del git_externals[ext]

    dump_gitexts(git_externals)

@cli.command('info')
@click.argument('externals', nargs=-1)
@click.option('--recursive/--no-recursive', default=True,
              help='Top level externals in which recurse into')
def gitext_info(externals, recursive):
    """Print some info about the externals."""
    from git_externals import gitext_recursive_info
    gitext_recursive_info('.', recursive=recursive, externals=externals)

def enable_colored_output():
    from git_externals import externals_root_path, get_entries

    for entry in get_entries():
        with chdir(os.path.join(externals_root_path(), entry)):
            git('config', 'color.ui', 'always')

def main():
    cli()

if __name__ == '__main__':
    main()
<commit_msg>cli: add --messages option to `freeze` command<commit_after>#!/usr/bin/env python

from __future__ import print_function, unicode_literals

import os
import sys
import re

import click

if __package__ is None:
    from __init__ import __version__
    from utils import command, CommandError, chdir, git, ProgError
else:
    from . import __version__
    from .utils import (command, CommandError, chdir, git, ProgError, decode_utf8,
                        current_branch)

click.disable_unicode_literals_warning = True

def echo(*args):
    click.echo(u' '.join(args))

def info(*args):
    click.secho(u' '.join(args), fg='blue')

def error(*args, **kwargs):
    click.secho(u' '.join(args), fg='red')
    exitcode = kwargs.get('exitcode', 1)
    if exitcode is not None:
        sys.exit(exitcode)

@click.group(context_settings={
    'allow_extra_args': True,
    'ignore_unknown_options': True,
    'help_option_names':['-h','--help'],
})
@click.version_option(__version__)
@click.option('--with-color/--no-color',
              default=True,
              help='Enable/disable colored output')
@click.pass_context
def cli(ctx, with_color):
    """Utility to manage git externals, meant to be used as a drop-in
    replacement to svn externals

    This script works by cloning externals found in the `git_externals.json`
    file into `.git/externals` and symlinks them to recreate the wanted
    directory layout.
    """
    from git_externals import is_git_repo, externals_json_path, externals_root_path

    if not is_git_repo():
        error("{} is not a git repository!".format(os.getcwd()), exitcode=2)

    if ctx.invoked_subcommand != 'add' and not os.path.exists(externals_json_path()):
        error("Unable to find", externals_json_path(), exitcode=1)

    if not os.path.exists(externals_root_path()):
        if ctx.invoked_subcommand not in set(['update', 'add']):
            error('You must first run git-externals update/add', exitcode=2)
    else:
        if with_color:
            enable_colored_output()

        if ctx.invoked_subcommand is None:
            gitext_st(())

@cli.command('foreach')
@click.option('--recursive/--no-recursive', help='If --recursive is specified, this command will recurse into nested externals', default=True)
@click.argument('subcommand', nargs=-1, required=True)
def gitext_foreach(recursive, subcommand):
    """Evaluates an arbitrary shell command in each checked out external
    """
    from git_externals import externals_sanity_check, get_repo_name, foreach_externals_dir, root_path

    externals_sanity_check()

    def run_command(rel_url, ext_path, targets):
        try:
            info("External {}".format(get_repo_name(rel_url)))
            output = decode_utf8(command(*subcommand))
            info("Ok: CWD: {}, cmd: {}".format(os.getcwd(), subcommand))
            echo(output)
        except CommandError as err:
            info("Command error {} CWD: {}, cmd: {}".format(err, os.getcwd(), subcommand))
            error(str(err), exitcode=err.errcode)

    foreach_externals_dir(root_path(), run_command, recursive=recursive)

@cli.command('update')
@click.option('--recursive/--no-recursive', help='Do not call git-externals update recursively', default=True)
@click.option('--gitsvn/--no-gitsvn', help='use git-svn (or simply svn) to checkout SVN repositories (only needed at first checkout)', default=True)
@click.option('--reset', help='Reset repo, overwrite local modifications', is_flag=True)
def gitext_update(recursive, gitsvn, reset):
    """Update the working copy cloning externals if needed and create the desired layout using symlinks
    """
    from git_externals import externals_sanity_check, root_path, is_workingtree_clean, foreach_externals, gitext_up

    externals_sanity_check()
    root = root_path()

    if reset:
        git('reset', '--hard')

    # Aggregate in a list the `clean flags` of all working trees (root + externals)
    clean = [is_workingtree_clean(root, fail_on_empty=False)]
    foreach_externals(root,
        lambda u, p, r: clean.append(is_workingtree_clean(p, fail_on_empty=False)),
        recursive=recursive)

    if reset or all(clean):
        # Proceed with update if everything is clean
        try:
            gitext_up(recursive, reset=reset, use_gitsvn=gitsvn)
        except ProgError as e:
            error(str(e), exitcode=e.errcode)
    else:
        echo("Cannot perform git externals update because one or more repositories contain some local modifications")
        echo("Run:\tgit externals status\tto have more information")

@cli.command('status')
@click.option(
    '--porcelain',
    is_flag=True,
    help='Print output using the porcelain format, useful mostly for scripts')
@click.option(
    '--verbose/--no-verbose',
    is_flag=True,
    help='Show the full output of git status, instead of showing only the modifications regarding tracked file')
@click.argument('externals', nargs=-1)
def gitext_st(porcelain, verbose, externals):
    """Call git status on the given externals"""
    from git_externals import foreach_externals_dir, root_path, \
                              is_workingtree_clean, get_repo_name

    def get_status(rel_url, ext_path, targets):
        try:
            if porcelain:
                echo(rel_url)
                click.echo(git('status', '--porcelain'))
            elif verbose or not is_workingtree_clean(ext_path):
                info("External {}".format(get_repo_name(rel_url)))
                echo(git('status', '--untracked-files=no' if not verbose else ''))
        except CommandError as err:
            error(str(err), exitcode=err.errcode)

    foreach_externals_dir(root_path(), get_status, recursive=True, only=externals)

@cli.command('diff')
@click.argument('external', nargs=-1)
def gitext_diff(external):
    """Call git diff on the given externals"""
    from git_externals import iter_externals
    for _ in iter_externals(external):
        click.echo(git('diff'))

@cli.command('add')
@click.argument('external',
                metavar='URL')
@click.argument('src', metavar='PATH')
@click.argument('dst', metavar='PATH')
@click.option('--branch', '-b', default=None, help='Checkout the given branch')
@click.option('--tag', '-t', default=None, help='Checkout the given tag')
@click.option('--ref', '-r', default=None, help='Checkout the given commit sha')
@click.option('--vcs', '-c', default='auto', help='Version Control System (default: autodetect)',
              type=click.Choice(['svn', 'git', 'auto']))
def gitext_add(external, src, dst, branch, tag, ref, vcs):
    """Add a git external to the current repo.

    Be sure to add '/' to `src` if it's a directory!
    It's possible to add multiple `dst` to the same `src`, however you cannot mix different branches, tags or refs
    for the same external.

    It's safe to use this command to add `src` to an already present external, as well as adding
    `dst` to an already present `src`.

    It requires one of --branch or --tag.
    """
    from git_externals import load_gitexts, dump_gitexts, normalize_gitexts, print_gitext_info

    git_externals = load_gitexts()

    if branch is None and tag is None:
        error('Please specifiy at least a branch or a tag', exitcode=3)

    if external not in git_externals:
        git_externals[external] = {'targets': {src: [dst]}}
        if branch is not None:
            git_externals[external]['branch'] = branch
            git_externals[external]['ref'] = ref
        else:
            git_externals[external]['tag'] = tag
        if vcs == 'auto':
            git_externals.update(normalize_gitexts({external: git_externals[external]}))
        else:
            git_externals[external]['vcs'] = vcs

    else:
        if branch is not None:
            if 'branch' not in git_externals[external]:
                error(
                    '{} is bound to tag {}, cannot set it to branch {}'.format(
                        external, git_externals[external]['tag'], branch),
                    exitcode=4)

            if ref != git_externals[external]['ref']:
                error('{} is bound to ref {}, cannot set it to ref {}'.format(
                    external, git_externals[external]['ref'], ref),
                    exitcode=4)

        elif 'tag' not in git_externals[external]:
            error('{} is bound to branch {}, cannot set it to tag {}'.format(
                external, git_externals[external]['branch'], tag),
                exitcode=4)

        if dst not in git_externals[external]['targets'].setdefault(src, []):
            git_externals[external]['targets'][src].append(dst)

    print_gitext_info(external, git_externals[external], root_dir='.')
    dump_gitexts(git_externals)

@cli.command('freeze')
@click.option('--messages', '-m', is_flag=True, help="List commit messages")
@click.argument('externals', nargs=-1, metavar='NAME')
def gitext_freeze(externals, messages):
    """Freeze the externals revision"""
    from git_externals import load_gitexts, dump_gitexts, foreach_externals_dir, root_path, resolve_revision
    git_externals = load_gitexts()
    re_from_git_svn_id = re.compile("git-svn-id:.*@(\d+)")
    re_from_svnversion = re.compile("(\d+):(\d+)")

    def get_version(rel_url, ext_path, refs):
        if 'tag' in refs:
            return

        if git_externals[rel_url]["vcs"] == "svn":
            revision = command('svnversion', '-c').strip()
            match = re_from_svnversion.search(revision)
            if match:
                revision = "svn:r" + match.group(2)  # 565:56555 -> svn:r56555
            else:
                message = git("log", "--format=%b", "--grep", "git-svn-id:", "-1")
                match = re_from_git_svn_id.search(message)
                if match:
                    revision = "svn:r" + match.group(1)
                else:
                    error("Unsupported external format, should be svn or git-svn repo")
        else:
            branch_name = current_branch()
            remote_name = git("config", "branch.%s.remote" % branch_name)
            revision = git("log", "%s/%s" % (remote_name, branch_name), "-1", "--format=%H")

        info("Freeze {0} at {1}".format(rel_url, revision))
        if messages:
            old = resolve_revision(git_externals[rel_url]["ref"])
            new = resolve_revision(revision)
            git("svn", "log", "--oneline", "{}..{}".format(old, new), capture=False)
        git_externals[rel_url]["ref"] = revision

    foreach_externals_dir(root_path(), get_version, only=externals)

    dump_gitexts(git_externals)

@cli.command('remove')
@click.argument('external', nargs=-1, metavar='URL')
def gitext_remove(external):
    """Remove the externals at the given repository URLs """
    from git_externals import load_gitexts, dump_gitexts

    git_externals = load_gitexts()

    for ext in external:
        if ext in git_externals:
            del git_externals[ext]

    dump_gitexts(git_externals)

@cli.command('info')
@click.argument('externals', nargs=-1)
@click.option('--recursive/--no-recursive', default=True,
              help='Top level externals in which recurse into')
def gitext_info(externals, recursive):
    """Print some info about the externals."""
    from git_externals import gitext_recursive_info
    gitext_recursive_info('.', recursive=recursive, externals=externals)

def enable_colored_output():
    from git_externals import externals_root_path, get_entries

    for entry in get_entries():
        with chdir(os.path.join(externals_root_path(), entry)):
            git('config', 'color.ui', 'always')

def main():
    cli()

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


<commit_before>import os
import json
import matplotlib
matplotlib.use('TkAgg')
import tkinter as tk
import tkinter.filedialog
from tkinter import ttk
import click

from . import pipe

STANDARD_MARGIN = (3, 3, 12, 12)

class Launch(tk.Tk):
    def __init__(self, params_dict=None):
        super().__init__()
        self.title('Skeleton analysis tool')
        self.crop_radius = tk.IntVar(value=0, name='Crop radius')
        self.smooth_radius = tk.DoubleVar(value=0.1, name='Smoothing radius')
        self.threshold_radius = tk.DoubleVar(value=50e-9,
                                             name='Threshold radius')
        self.brightness_offset = tk.DoubleVar(value=0.075,
                                              name='Brightness offset')
        self.image_format = tk.StringVar(value='auto',
                                         name='Image format')
        self.scale_metadata_path = tk.StringVar(value='Scan/PixelHeight',
                                                name='Scale metadata path')
        self.save_skeleton_plots = tk.BooleanVar(value=True,
                                                 name='Save skeleton plot?')
        self.skeleton_plot_prefix = tk.StringVar(value='skeleton-plot-',
                                         name='Prefix for skeleton plots')
        self.full_output_filename = tk.StringVar(value='skeleton.csv',
                                                 name='Full stats filename')
        self.image_output_filename = tk.StringVar(value='images-stats.csv',
                                                  name='Image stats filename')
        self.parameters = [
            self.crop_radius,
            self.smooth_radius,
            self.threshold_radius,
            self.brightness_offset,
            self.image_format,
            self.scale_metadata_path,
            self.save_skeleton_plots,
            self.skeleton_plot_prefix,
            self.full_output_filename,
            self.image_output_filename,
        ]

        self.input_files = []
        self.output_folder = None

        if params_dict is None:
            params_dict = {}
        self.params_dict = params_dict.copy()
        self.parameter_config(params_dict)

        # allow resizing
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        self.create_main_frame()

    def parameter_config(self, params_dict):
        """Set parameter values from a config dictionary."""
        if isinstance(params_dict, str):
            if params_dict.startswith('{'):  # JSON string
                params_dict = json.loads(params_dict)
            else:  # config file
                with open(params_dict) as params_fin:
                    params_dict = json.load(params_fin)
            self.params_dict.update(params_dict)
        name2param = {p._name.lower(): p for p in self.parameters}
        for param, value in self.params_dict.items():
            if param.lower() in name2param:
                name2param[param].set(value)
                params_dict.pop(param)
        for param, value in params_dict.copy().items():
            if param.lower() == 'input files':
                self.input_files = value
                params_dict.pop(param)
            elif param.lower() == 'output folder':
                self.output_folder = os.path.expanduser(value)
                params_dict.pop(param)
        for param in params_dict:
            print(f'Parameter not recognised: {param}')

    def create_main_frame(self):
        main = ttk.Frame(master=self, padding=STANDARD_MARGIN)
        main.grid(row=0, column=0, sticky='nsew')
        self.create_parameters_frame(main)
        self.create_buttons_frame(main)
        main.pack()

    def create_parameters_frame(self, parent):
        parameters = ttk.Frame(master=parent, padding=STANDARD_MARGIN)
        parameters.grid(sticky='nsew')

        heading = ttk.Label(parameters, text='Analysis parameters')
        heading.grid(column=0, row=0, sticky='n')

        for i, param in enumerate(self.parameters, start=1):
            param_label = ttk.Label(parameters, text=param._name)
            param_label.grid(row=i, column=0, sticky='nsew')
            if type(param) == tk.BooleanVar:
                param_entry = ttk.Checkbutton(parameters, variable=param)
            else:
                param_entry = ttk.Entry(parameters, textvariable=param)
            param_entry.grid(row=i, column=1, sticky='nsew')

    def create_buttons_frame(self, parent):
        buttons = ttk.Frame(master=parent, padding=STANDARD_MARGIN)
        buttons.grid(sticky='nsew')
        actions = [
            ('Choose files', self.choose_input_files),
            ('Choose output folder', self.choose_output_folder),
            ('Run', self.run)
        ]
        for col, (action_name, action) in enumerate(actions):
            button = ttk.Button(buttons, text=action_name,
                                command=action)
            button.grid(row=0, column=col)

    def choose_input_files(self):
        self.input_files = tk.filedialog.askopenfilenames()
        if len(self.input_files) > 0 and self.output_folder is None:
            self.output_folder = os.path.dirname(self.input_files[0])

    def choose_output_folder(self):
        self.output_folder = \
                tk.filedialog.askdirectory(initialdir=self.output_folder)

    def run(self):
        print('Input files:')
        for file in self.input_files:
            print('  ', file)
        print('Parameters:')
        for param in self.parameters:
            p = param.get()
            print('  ', param, type(p), p)
        print('Output:', self.output_folder)
        save_skeleton = ('' if not self.save_skeleton_plots.get() else
                         self.skeleton_plot_prefix.get())
        result_full, result_image = pipe.process_images(
                self.input_files, self.image_format.get(),
                self.threshold_radius.get(),
                self.smooth_radius.get(),
                self.brightness_offset.get(),
                self.scale_metadata_path.get(),
                save_skeleton,
                self.output_folder,
                crop_radius=self.crop_radius.get())
        result_full.to_csv(os.path.join(self.output_folder,
                                        self.full_output_filename.get()))
        result_image.to_csv(os.path.join(self.output_folder,
                                         self.image_output_filename.get()))

@click.command()
@click.option('-c', '--config', default='',
              help='JSON configuration file.')
def launch(config):
    params = json.load(open(config)) if config else None
    app = Launch(params)
    app.mainloop()
<commit_msg>Add button to select config file<commit_after>import os
import json
import matplotlib
matplotlib.use('TkAgg')
import tkinter as tk
import tkinter.filedialog
from tkinter import ttk
import click

from . import pipe

STANDARD_MARGIN = (3, 3, 12, 12)

class Launch(tk.Tk):
    def __init__(self, params_dict=None):
        super().__init__()
        self.title('Skeleton analysis tool')
        self.crop_radius = tk.IntVar(value=0, name='Crop radius')
        self.smooth_radius = tk.DoubleVar(value=0.1, name='Smoothing radius')
        self.threshold_radius = tk.DoubleVar(value=50e-9,
                                             name='Threshold radius')
        self.brightness_offset = tk.DoubleVar(value=0.075,
                                              name='Brightness offset')
        self.image_format = tk.StringVar(value='auto',
                                         name='Image format')
        self.scale_metadata_path = tk.StringVar(value='Scan/PixelHeight',
                                                name='Scale metadata path')
        self.save_skeleton_plots = tk.BooleanVar(value=True,
                                                 name='Save skeleton plot?')
        self.skeleton_plot_prefix = tk.StringVar(value='skeleton-plot-',
                                         name='Prefix for skeleton plots')
        self.full_output_filename = tk.StringVar(value='skeleton.csv',
                                                 name='Full stats filename')
        self.image_output_filename = tk.StringVar(value='images-stats.csv',
                                                  name='Image stats filename')
        self.parameters = [
            self.crop_radius,
            self.smooth_radius,
            self.threshold_radius,
            self.brightness_offset,
            self.image_format,
            self.scale_metadata_path,
            self.save_skeleton_plots,
            self.skeleton_plot_prefix,
            self.full_output_filename,
            self.image_output_filename,
        ]

        self.input_files = []
        self.output_folder = None

        if params_dict is None:
            params_dict = {}
        self.params_dict = params_dict.copy()
        self.parameter_config(params_dict)

        # allow resizing
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)

        self.create_main_frame()

    def parameter_config(self, params_dict):
        """Set parameter values from a config dictionary."""
        if isinstance(params_dict, str):
            if params_dict.startswith('{'):  # JSON string
                params_dict = json.loads(params_dict)
            else:  # config file
                with open(params_dict) as params_fin:
                    params_dict = json.load(params_fin)
            self.params_dict.update(params_dict)
        name2param = {p._name.lower(): p for p in self.parameters}
        for param, value in self.params_dict.items():
            if param.lower() in name2param:
                name2param[param].set(value)
                params_dict.pop(param)
        for param, value in params_dict.copy().items():
            if param.lower() == 'input files':
                self.input_files = value
                params_dict.pop(param)
            elif param.lower() == 'output folder':
                self.output_folder = os.path.expanduser(value)
                params_dict.pop(param)
        for param in params_dict:
            print(f'Parameter not recognised: {param}')

    def create_main_frame(self):
        main = ttk.Frame(master=self, padding=STANDARD_MARGIN)
        main.grid(row=0, column=0, sticky='nsew')
        self.create_parameters_frame(main)
        self.create_buttons_frame(main)
        main.pack()

    def create_parameters_frame(self, parent):
        parameters = ttk.Frame(master=parent, padding=STANDARD_MARGIN)
        parameters.grid(sticky='nsew')

        heading = ttk.Label(parameters, text='Analysis parameters')
        heading.grid(column=0, row=0, sticky='n')

        for i, param in enumerate(self.parameters, start=1):
            param_label = ttk.Label(parameters, text=param._name)
            param_label.grid(row=i, column=0, sticky='nsew')
            if type(param) == tk.BooleanVar:
                param_entry = ttk.Checkbutton(parameters, variable=param)
            else:
                param_entry = ttk.Entry(parameters, textvariable=param)
            param_entry.grid(row=i, column=1, sticky='nsew')

    def create_buttons_frame(self, parent):
        buttons = ttk.Frame(master=parent, padding=STANDARD_MARGIN)
        buttons.grid(sticky='nsew')
        actions = [
            ('Choose config', self.choose_config_file),
            ('Choose files', self.choose_input_files),
            ('Choose output folder', self.choose_output_folder),
            ('Run', self.run)
        ]
        for col, (action_name, action) in enumerate(actions):
            button = ttk.Button(buttons, text=action_name,
                                command=action)
            button.grid(row=0, column=col)

    def choose_config_file(self):
        config_file = tk.filedialog.askopenfilename()
        self.parameter_config(config_file)

    def choose_input_files(self):
        self.input_files = tk.filedialog.askopenfilenames()
        if len(self.input_files) > 0 and self.output_folder is None:
            self.output_folder = os.path.dirname(self.input_files[0])

    def choose_output_folder(self):
        self.output_folder = \
                tk.filedialog.askdirectory(initialdir=self.output_folder)

    def run(self):
        print('Input files:')
        for file in self.input_files:
            print('  ', file)
        print('Parameters:')
        for param in self.parameters:
            p = param.get()
            print('  ', param, type(p), p)
        print('Output:', self.output_folder)
        save_skeleton = ('' if not self.save_skeleton_plots.get() else
                         self.skeleton_plot_prefix.get())
        result_full, result_image = pipe.process_images(
                self.input_files, self.image_format.get(),
                self.threshold_radius.get(),
                self.smooth_radius.get(),
                self.brightness_offset.get(),
                self.scale_metadata_path.get(),
                save_skeleton,
                self.output_folder,
                crop_radius=self.crop_radius.get())
        result_full.to_csv(os.path.join(self.output_folder,
                                        self.full_output_filename.get()))
        result_image.to_csv(os.path.join(self.output_folder,
                                         self.image_output_filename.get()))

@click.command()
@click.option('-c', '--config', default='',
              help='JSON configuration file.')
def launch(config):
    params = json.load(open(config)) if config else None
    app = Launch(params)
    app.mainloop()
<|endoftext|>


<commit_before>from __future__ import division
from io import BytesIO
from PIL import Image

import math
import numpy
from six import PY3

from ._image import window_batch_bchw
from . import ExpectsAxisLabels, SourcewiseTransformer
from .. import config

class ImagesFromBytes(SourcewiseTransformer):
    """Load from a stream of image-formatted data represented as bytes.

    Parameters
    ----------
    data_stream : instance of :class:`AbstractDataStream`
        The wrapped data stream.
    which_sources : tuple of str
        Which sources to apply the mapping to.
    color_mode : str, optional
        Mode to pass to PIL for color space conversion. Default is RGB.
        If `None`, no coercion is performed.

    Notes
    -----
    Images are returned as NumPy arrays converted from PIL objects.
    If `color_mode` is RGB, then the array is transposed from the
    `(height, width, channel)` dimension layout native to PIL to the
    `(channel, height, width)` layout that is pervasive in the world of
    convolutional networks.

    This SourcewiseTransformer supports streams returning single examples
    as `bytes` objects (`str` on Python 2.x) as well as streams that
    return iterables containing such objects. In the case of an
    iterable, a list of loaded images is returned.

    """
    def __init__(self, data_stream, which_sources, color_mode='RGB', **kwargs):
        kwargs.setdefault('produces_examples', data_stream.produces_examples)
        super(ImagesFromBytes, self).__init__(data_stream, which_sources,
                                              **kwargs)
        self.color_mode = color_mode

    def transform_source_example(self, example, source_name):
        if PY3:
            bytes_type = bytes
        else:
            bytes_type = str
        if not isinstance(example, bytes_type):
            raise TypeError("expected {} object".format(bytes_type.__name__))
        pil_image = Image.open(BytesIO(example))
        if self.color_mode is not None:
            pil_image = pil_image.convert(self.color_mode)
        image = numpy.array(pil_image)
        if self.color_mode == 'RGB':
            # Transpose to `(channels, height, width)` layout.
            return image.transpose(2, 0, 1)
        else:
            return image

    def transform_source_batch(self, batch, source_name):
        return [self.transform_source_example(im, source_name) for im in batch]

class MinimumImageDimensions(SourcewiseTransformer, ExpectsAxisLabels):
    """Resize (lists of) images to minimum dimensions.

    Parameters
    ----------
    data_stream : instance of :class:`AbstractDataStream`
        The data stream to wrap.
    minimum_shape : 2-tuple
        The minimum `(height, width)` dimensions every image must have.
        Images whose height and width are larger than these dimensions
        are passed through as-is.
    resample : str, optional
        Resampling filter for PIL to use to upsample any images requiring
        it. Options include 'nearest' (default), 'bilinear', and 'bicubic'.
        See the PIL documentation for more detailed information.

    Notes
    -----
    This transformer expects stream sources returning individual images,
    represented as 2- or 3-dimensional arrays, or lists of the same.
    The format of the stream is unaltered.

    """
    def __init__(self, data_stream, minimum_shape, resample='nearest',
                 **kwargs):
        self.minimum_shape = minimum_shape
        try:
            self.resample = getattr(Image, resample.upper())
        except AttributeError:
            raise ValueError("unknown resampling filter '{}'".format(resample))
        kwargs.setdefault('produces_examples', data_stream.produces_examples)
        kwargs.setdefault('axis_labels', data_stream.axis_labels)
        super(MinimumImageDimensions, self).__init__(data_stream, **kwargs)

    def transform_source_batch(self, batch, source_name):
        self.verify_axis_labels(('batch', 'channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        return [self._example_transform(im, source_name) for im in batch]

    def transform_source_example(self, example, source_name):
        self.verify_axis_labels(('channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        return self._example_transform(example, source_name)

    def _example_transform(self, example, _):
        if example.ndim > 3 or example.ndim < 2:
            raise NotImplementedError
        min_height, min_width = self.minimum_shape
        original_height, original_width = example.shape[-2:]
        if original_height < min_height or original_width < min_width:
            dt = example.dtype
            # If we're dealing with a colour image, swap around the axes
            # to be in the format that PIL needs.
            if example.ndim == 3:
                im = example.tranpose(2, 0, 1)
            else:
                im = example
            im = Image.fromarray(im)
            width, height = im.size
            multiplier = max(1, min_width / width, min_height / height)
            width = int(math.ceil(width * multiplier))
            height = int(math.ceil(height * multiplier))
            im = numpy.array(im.resize((width, height))).astype(dt)
            # If necessary, undo the axis swap from earlier.
            if im.ndim == 3:
                example = im.transpose(2, 0, 1)
            else:
                example = im
        return example

class RandomFixedSizeCrop(SourcewiseTransformer, ExpectsAxisLabels):
    """Randomly crop images to a fixed window size.

    Parameters
    ----------
    data_stream : :class:`AbstractDataStream`
        The data stream to wrap.
    window_shape : tuple
        The `(height, width)` tuple representing the size of the output
        window.

    Notes
    -----
    This transformer expects to act on stream sources which provide one of

     * Single images represented as 3-dimensional ndarrays, with layout
       `(n_channels, height, width)`.
     * Batches of images represented as lists of 3-dimensional ndarrays,
       possibly of different shapes (i.e. images of differing
       heights/widths).
     * Batches of images represented as 4-dimensional ndarrays, with
       layout `(batch, n_channels, height, width)`.

    The format of the stream will be un-altered, i.e. if lists are
    yielded by `data_stream` then lists will be yielded by this
    transformer.

    """
    def __init__(self, data_stream, window_shape, **kwargs):
        self.window_shape = window_shape
        self.rng = kwargs.pop('rng', None)
        self.warned_axis_labels = False
        if self.rng is None:
            self.rng = numpy.random.RandomState(config.default_seed)
        kwargs.setdefault('produces_examples', data_stream.produces_examples)
        kwargs.setdefault('axis_labels', data_stream.axis_labels)
        super(RandomFixedSizeCrop, self).__init__(data_stream, **kwargs)

    def transform_source_batch(self, source, source_name):
        self.verify_axis_labels(('batch', 'channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        windowed_height, windowed_width = self.window_shape
        if isinstance(source, list):
            return [self.transform_source_example(im, source_name)
                    for im in source]
        elif isinstance(source, numpy.ndarray) and source.ndim == 4:
            # Hardcoded assumption of (batch, channels, height, width).
            # This is what the fast Cython code supports.
            out = numpy.empty(source.shape[:2] + self.window_shape,
                              dtype=source.dtype)
            batch_size = source.shape[0]
            image_height, image_width = source.shape[2:]
            max_h_off = image_height - windowed_height
            max_w_off = image_width - windowed_width
            if max_h_off < 0 or max_w_off < 0:
                raise ValueError("Got ndarray batch with image dimensions {} "
                                 "but requested window shape of {}".format(
                                     source.shape[2:], self.window_shape))
            offsets_w = self.rng.random_integers(0, max_w_off, size=batch_size)
            offsets_h = self.rng.random_integers(0, max_h_off, size=batch_size)
            window_batch_bchw(source, offsets_h, offsets_w, out)
            return out
        else:
            raise ValueError("uninterpretable batch format; expected a list "
                             "of arrays with ndim = 3, or an array with "
                             "ndim = 4")

    def transform_source_example(self, example, source_name):
        self.verify_axis_labels(('channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        windowed_height, windowed_width = self.window_shape
        if not isinstance(example, numpy.ndarray) or example.ndim != 3:
            raise ValueError("uninterpretable example format; expected "
                             "ndarray with ndim = 3")
        image_height, image_width = example.shape[1:]
        if image_height < windowed_height or image_width < windowed_width:
            raise ValueError("can't obtain ({}, {}) window from image "
                             "dimensions ({}, {})".format(
                                 windowed_height, windowed_width,
                                 image_height, image_width))
        if image_height - windowed_height > 0:
            off_h = self.rng.random_integers(0, image_height - windowed_height)
        else:
            off_h = 0
        if image_width - windowed_width > 0:
            off_w = self.rng.random_integers(0, image_width - windowed_width)
        else:
            off_w = 0
        return example[:, off_h:off_h + windowed_height,
                       off_w:off_w + windowed_width]
<commit_msg>Reorder/standardize imports.<commit_after>from __future__ import division
from io import BytesIO
import math

import numpy
from PIL import Image
from six import PY3

from ._image import window_batch_bchw
from . import ExpectsAxisLabels, SourcewiseTransformer
from .. import config

class ImagesFromBytes(SourcewiseTransformer):
    """Load from a stream of image-formatted data represented as bytes.

    Parameters
    ----------
    data_stream : instance of :class:`AbstractDataStream`
        The wrapped data stream.
    which_sources : tuple of str
        Which sources to apply the mapping to.
    color_mode : str, optional
        Mode to pass to PIL for color space conversion. Default is RGB.
        If `None`, no coercion is performed.

    Notes
    -----
    Images are returned as NumPy arrays converted from PIL objects.
    If `color_mode` is RGB, then the array is transposed from the
    `(height, width, channel)` dimension layout native to PIL to the
    `(channel, height, width)` layout that is pervasive in the world of
    convolutional networks.

    This SourcewiseTransformer supports streams returning single examples
    as `bytes` objects (`str` on Python 2.x) as well as streams that
    return iterables containing such objects. In the case of an
    iterable, a list of loaded images is returned.

    """
    def __init__(self, data_stream, which_sources, color_mode='RGB', **kwargs):
        kwargs.setdefault('produces_examples', data_stream.produces_examples)
        super(ImagesFromBytes, self).__init__(data_stream, which_sources,
                                              **kwargs)
        self.color_mode = color_mode

    def transform_source_example(self, example, source_name):
        if PY3:
            bytes_type = bytes
        else:
            bytes_type = str
        if not isinstance(example, bytes_type):
            raise TypeError("expected {} object".format(bytes_type.__name__))
        pil_image = Image.open(BytesIO(example))
        if self.color_mode is not None:
            pil_image = pil_image.convert(self.color_mode)
        image = numpy.array(pil_image)
        if self.color_mode == 'RGB':
            # Transpose to `(channels, height, width)` layout.
            return image.transpose(2, 0, 1)
        else:
            return image

    def transform_source_batch(self, batch, source_name):
        return [self.transform_source_example(im, source_name) for im in batch]

class MinimumImageDimensions(SourcewiseTransformer, ExpectsAxisLabels):
    """Resize (lists of) images to minimum dimensions.

    Parameters
    ----------
    data_stream : instance of :class:`AbstractDataStream`
        The data stream to wrap.
    minimum_shape : 2-tuple
        The minimum `(height, width)` dimensions every image must have.
        Images whose height and width are larger than these dimensions
        are passed through as-is.
    resample : str, optional
        Resampling filter for PIL to use to upsample any images requiring
        it. Options include 'nearest' (default), 'bilinear', and 'bicubic'.
        See the PIL documentation for more detailed information.

    Notes
    -----
    This transformer expects stream sources returning individual images,
    represented as 2- or 3-dimensional arrays, or lists of the same.
    The format of the stream is unaltered.

    """
    def __init__(self, data_stream, minimum_shape, resample='nearest',
                 **kwargs):
        self.minimum_shape = minimum_shape
        try:
            self.resample = getattr(Image, resample.upper())
        except AttributeError:
            raise ValueError("unknown resampling filter '{}'".format(resample))
        kwargs.setdefault('produces_examples', data_stream.produces_examples)
        kwargs.setdefault('axis_labels', data_stream.axis_labels)
        super(MinimumImageDimensions, self).__init__(data_stream, **kwargs)

    def transform_source_batch(self, batch, source_name):
        self.verify_axis_labels(('batch', 'channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        return [self._example_transform(im, source_name) for im in batch]

    def transform_source_example(self, example, source_name):
        self.verify_axis_labels(('channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        return self._example_transform(example, source_name)

    def _example_transform(self, example, _):
        if example.ndim > 3 or example.ndim < 2:
            raise NotImplementedError
        min_height, min_width = self.minimum_shape
        original_height, original_width = example.shape[-2:]
        if original_height < min_height or original_width < min_width:
            dt = example.dtype
            # If we're dealing with a colour image, swap around the axes
            # to be in the format that PIL needs.
            if example.ndim == 3:
                im = example.tranpose(2, 0, 1)
            else:
                im = example
            im = Image.fromarray(im)
            width, height = im.size
            multiplier = max(1, min_width / width, min_height / height)
            width = int(math.ceil(width * multiplier))
            height = int(math.ceil(height * multiplier))
            im = numpy.array(im.resize((width, height))).astype(dt)
            # If necessary, undo the axis swap from earlier.
            if im.ndim == 3:
                example = im.transpose(2, 0, 1)
            else:
                example = im
        return example

class RandomFixedSizeCrop(SourcewiseTransformer, ExpectsAxisLabels):
    """Randomly crop images to a fixed window size.

    Parameters
    ----------
    data_stream : :class:`AbstractDataStream`
        The data stream to wrap.
    window_shape : tuple
        The `(height, width)` tuple representing the size of the output
        window.

    Notes
    -----
    This transformer expects to act on stream sources which provide one of

     * Single images represented as 3-dimensional ndarrays, with layout
       `(n_channels, height, width)`.
     * Batches of images represented as lists of 3-dimensional ndarrays,
       possibly of different shapes (i.e. images of differing
       heights/widths).
     * Batches of images represented as 4-dimensional ndarrays, with
       layout `(batch, n_channels, height, width)`.

    The format of the stream will be un-altered, i.e. if lists are
    yielded by `data_stream` then lists will be yielded by this
    transformer.

    """
    def __init__(self, data_stream, window_shape, **kwargs):
        self.window_shape = window_shape
        self.rng = kwargs.pop('rng', None)
        self.warned_axis_labels = False
        if self.rng is None:
            self.rng = numpy.random.RandomState(config.default_seed)
        kwargs.setdefault('produces_examples', data_stream.produces_examples)
        kwargs.setdefault('axis_labels', data_stream.axis_labels)
        super(RandomFixedSizeCrop, self).__init__(data_stream, **kwargs)

    def transform_source_batch(self, source, source_name):
        self.verify_axis_labels(('batch', 'channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        windowed_height, windowed_width = self.window_shape
        if isinstance(source, list):
            return [self.transform_source_example(im, source_name)
                    for im in source]
        elif isinstance(source, numpy.ndarray) and source.ndim == 4:
            # Hardcoded assumption of (batch, channels, height, width).
            # This is what the fast Cython code supports.
            out = numpy.empty(source.shape[:2] + self.window_shape,
                              dtype=source.dtype)
            batch_size = source.shape[0]
            image_height, image_width = source.shape[2:]
            max_h_off = image_height - windowed_height
            max_w_off = image_width - windowed_width
            if max_h_off < 0 or max_w_off < 0:
                raise ValueError("Got ndarray batch with image dimensions {} "
                                 "but requested window shape of {}".format(
                                     source.shape[2:], self.window_shape))
            offsets_w = self.rng.random_integers(0, max_w_off, size=batch_size)
            offsets_h = self.rng.random_integers(0, max_h_off, size=batch_size)
            window_batch_bchw(source, offsets_h, offsets_w, out)
            return out
        else:
            raise ValueError("uninterpretable batch format; expected a list "
                             "of arrays with ndim = 3, or an array with "
                             "ndim = 4")

    def transform_source_example(self, example, source_name):
        self.verify_axis_labels(('channel', 'height', 'width'),
                                self.data_stream.axis_labels[source_name],
                                source_name)
        windowed_height, windowed_width = self.window_shape
        if not isinstance(example, numpy.ndarray) or example.ndim != 3:
            raise ValueError("uninterpretable example format; expected "
                             "ndarray with ndim = 3")
        image_height, image_width = example.shape[1:]
        if image_height < windowed_height or image_width < windowed_width:
            raise ValueError("can't obtain ({}, {}) window from image "
                             "dimensions ({}, {})".format(
                                 windowed_height, windowed_width,
                                 image_height, image_width))
        if image_height - windowed_height > 0:
            off_h = self.rng.random_integers(0, image_height - windowed_height)
        else:
            off_h = 0
        if image_width - windowed_width > 0:
            off_w = self.rng.random_integers(0, image_width - windowed_width)
        else:
            off_w = 0
        return example[:, off_h:off_h + windowed_height,
                       off_w:off_w + windowed_width]
<|endoftext|>


<commit_before>import os
import linecache

from hashlib import sha256
import pprint
import urllib

from django.conf import settings
from django.db import models
import json

class Request(models.Model):
    method = models.CharField(max_length=7)
    path = models.CharField(max_length=255)
    get_json = models.TextField()
    post_json = models.TextField()
    cookies_json = models.TextField()
    meta_json = models.TextField()

    def to_markdown(self):
        request_uri = [self.path]
        get_params = json.loads(self.get_json)
        if get_params:
            get_params = dict(
                (k.encode('utf8'), v.encode('utf8'))
                for k, v in get_params.iteritems()
            )
            request_uri += ['?', urllib.urlencode(get_params)]
        request_uri = ''.join(request_uri)
        return '''
### Request: %(method)s %(request_uri)s
POST
```
%(post_params)s
```
COOKIE
```
%(cookie_params)s
```
META
```
%(meta_params)s
```
''' % dict(
            method=self.method,
            request_uri=request_uri,
            post_params=pprint.pformat(json.loads(self.post_json), width=1),
            cookie_params=pprint.pformat(json.loads(self.cookies_json), width=1),
            meta_params=pprint.pformat(json.loads(self.meta_json), width=1)
        )

    @staticmethod
    def foo():
        pass

    @classmethod
    def create_from_request(cls, request):
        meta_dict = dict((k, v) for k, v in request.META.iteritems() if k.startswith('HTTP_'))
        return cls.objects.create(
            method=request.method,
            path=request.META['PATH_INFO'].split('?')[0],
            get_json=json.dumps(request.GET),
            post_json=json.dumps(request.POST),
            cookies_json=json.dumps(request.COOKIES),
            meta_json=json.dumps(meta_dict)
        )

class Signature(models.Model):
    hash = models.CharField(max_length=64, unique=True)
    file_name = models.CharField(max_length=255)
    line = models.CharField(max_length=255)
    line_number = models.IntegerField()
    issue_number = models.IntegerField(null=True)

    def __repr__(self):
        return '<Signature: "%s">' % str(self)

    def __str__(self):
        return self.make_string(self.file_name, self.line)

    @staticmethod
    def make_string(file_name, line):
        return '%s#%s' % (file_name, line)

    @classmethod
    def get_or_create_from_frame(cls, error_frame):
        short_file_name = file_name = error_frame.f_code.co_filename
        line_number = error_frame.f_lineno
        line = linecache.getline(file_name, line_number).strip()
        if not file_name.startswith('.'):
            short_file_name = file_name[len(os.getcwd()):]
        hash_ = sha256(cls.make_string(short_file_name, line)).hexdigest()
        return cls.objects.get_or_create(
            hash=hash_,
            defaults=dict(file_name=short_file_name, line=line, line_number=line_number)
        )

class ErrorLog(models.Model):
    type = models.CharField(max_length=255)
    message = models.CharField(max_length=255)
    signature = models.ForeignKey(Signature)
    request = models.OneToOneField(Request)
    stack_trace = models.TextField()
    local_variables = models.TextField()
    logged_at = models.DateTimeField(auto_now_add=True)

    @property
    def title(self):
        return '%s: %s' % (self.type, self.message)

    @property
    def body(self):
        return '''## Error Info
Error on %(filename)s:%(line_no)d
%(line)s
```
%(stack_trace)s
```

Local variables
```
%(local_variables)s
```
## Request Info
%(request)s
Logged at: %(logged_at)s''' % dict(
            filename=self.signature.file_name.encode('utf8'),
            line_no=self.signature.line_number,
            line=self.signature.line,
            stack_trace=self.stack_trace.encode('utf8'),
            logged_at=self.logged_at,
            local_variables=self.local_variables,
            request=self.request.to_markdown().encode('utf8')
        )

    @classmethod
    def create_from_record(cls, record):
        error_frame = get_error_frame(record.exc_info[2])
        signature, _ = Signature.get_or_create_from_frame(error_frame)
        local_variables = (
            '%s: %s' % (k, str(v).replace('\n', '\n\t'))
            for k, v in error_frame.f_locals.iteritems()
        )
        log = cls.objects.create(
            type=record.exc_info[0].__name__,
            message=str(record.exc_info[1]),
            signature=signature,
            request=Request.create_from_request(record.request),
            local_variables='\n'.join(local_variables),
            stack_trace=record.exc_text
        )
        return log

def get_error_frame(initial_tb):
    def is_controllable(tb):
        filename = tb.tb_frame.f_code.co_filename
        if filename.startswith('.'):
            filename = filename.replace('.', os.getcwd(), 1)
        for app_name in settings.INSTALLED_APPS:
            expected_path = os.path.join(os.getcwd(), app_name.replace('.', os.path.sep))
            if os.path.exists(expected_path) and filename.startswith(expected_path):
                return True
        return False

    current_tb = initial_tb
    have_seen_controllable = False
    while current_tb.tb_next:
        if is_controllable(current_tb):
            have_seen_controllable = True
        if have_seen_controllable and not is_controllable(current_tb.tb_next):
            break
        current_tb = current_tb.tb_next

    return current_tb.tb_frame
<commit_msg>UnicodeEncodeError fixed<commit_after>import os
import linecache

from hashlib import sha256
import pprint
import urllib

from django.conf import settings
from django.db import models
import json

class Request(models.Model):
    method = models.CharField(max_length=7)
    path = models.CharField(max_length=255)
    get_json = models.TextField()
    post_json = models.TextField()
    cookies_json = models.TextField()
    meta_json = models.TextField()

    def to_markdown(self):
        request_uri = [self.path]
        get_params = json.loads(self.get_json)
        if get_params:
            get_params = dict(
                (k.encode('utf8'), v.encode('utf8'))
                for k, v in get_params.iteritems()
            )
            request_uri += ['?', urllib.urlencode(get_params)]
        request_uri = ''.join(request_uri)
        return '''
### Request: %(method)s %(request_uri)s
POST
```
%(post_params)s
```
COOKIE
```
%(cookie_params)s
```
META
```
%(meta_params)s
```
''' % dict(
            method=self.method,
            request_uri=request_uri,
            post_params=pprint.pformat(json.loads(self.post_json), width=1),
            cookie_params=pprint.pformat(json.loads(self.cookies_json), width=1),
            meta_params=pprint.pformat(json.loads(self.meta_json), width=1)
        )

    @staticmethod
    def foo():
        pass

    @classmethod
    def create_from_request(cls, request):
        meta_dict = dict((k, v) for k, v in request.META.iteritems() if k.startswith('HTTP_'))
        return cls.objects.create(
            method=request.method,
            path=request.META['PATH_INFO'].split('?')[0],
            get_json=json.dumps(request.GET),
            post_json=json.dumps(request.POST),
            cookies_json=json.dumps(request.COOKIES),
            meta_json=json.dumps(meta_dict)
        )

class Signature(models.Model):
    hash = models.CharField(max_length=64, unique=True)
    file_name = models.CharField(max_length=255)
    line = models.CharField(max_length=255)
    line_number = models.IntegerField()
    issue_number = models.IntegerField(null=True)

    def __repr__(self):
        return '<Signature: "%s">' % str(self)

    def __str__(self):
        return self.make_string(self.file_name, self.line)

    @staticmethod
    def make_string(file_name, line):
        return '%s#%s' % (file_name, line)

    @classmethod
    def get_or_create_from_frame(cls, error_frame):
        short_file_name = file_name = error_frame.f_code.co_filename
        line_number = error_frame.f_lineno
        line = linecache.getline(file_name, line_number).strip()
        if not file_name.startswith('.'):
            short_file_name = file_name[len(os.getcwd()):]
        hash_ = sha256(cls.make_string(short_file_name, line)).hexdigest()
        return cls.objects.get_or_create(
            hash=hash_,
            defaults=dict(file_name=short_file_name, line=line, line_number=line_number)
        )

class ErrorLog(models.Model):
    type = models.CharField(max_length=255)
    message = models.CharField(max_length=255)
    signature = models.ForeignKey(Signature)
    request = models.OneToOneField(Request)
    stack_trace = models.TextField()
    local_variables = models.TextField()
    logged_at = models.DateTimeField(auto_now_add=True)

    @property
    def title(self):
        return '%s: %s' % (self.type, self.message)

    @property
    def body(self):
        return '''## Error Info
Error on %(filename)s:%(line_no)d
%(line)s
```
%(stack_trace)s
```

Local variables
```
%(local_variables)s
```
## Request Info
%(request)s
Logged at: %(logged_at)s''' % dict(
            filename=self.signature.file_name.encode('utf8'),
            line_no=self.signature.line_number,
            line=self.signature.line,
            stack_trace=self.stack_trace.encode('utf8'),
            logged_at=self.logged_at,
            local_variables=self.local_variables,
            request=self.request.to_markdown().encode('utf8')
        )

    @classmethod
    def create_from_record(cls, record):
        error_frame = get_error_frame(record.exc_info[2])
        signature, _ = Signature.get_or_create_from_frame(error_frame)
        local_variables = (
            '%s: %s' % (k, v.encode('utf8').replace('\n', '\n\t'))
            for k, v in error_frame.f_locals.iteritems()
        )
        log = cls.objects.create(
            type=record.exc_info[0].__name__,
            message=str(record.exc_info[1]),
            signature=signature,
            request=Request.create_from_request(record.request),
            local_variables='\n'.join(local_variables),
            stack_trace=record.exc_text
        )
        return log

def get_error_frame(initial_tb):
    def is_controllable(tb):
        filename = tb.tb_frame.f_code.co_filename
        if filename.startswith('.'):
            filename = filename.replace('.', os.getcwd(), 1)
        for app_name in settings.INSTALLED_APPS:
            expected_path = os.path.join(os.getcwd(), app_name.replace('.', os.path.sep))
            if os.path.exists(expected_path) and filename.startswith(expected_path):
                return True
        return False

    current_tb = initial_tb
    have_seen_controllable = False
    while current_tb.tb_next:
        if is_controllable(current_tb):
            have_seen_controllable = True
        if have_seen_controllable and not is_controllable(current_tb.tb_next):
            break
        current_tb = current_tb.tb_next

    return current_tb.tb_frame
<|endoftext|>


<commit_before>from django.core.exceptions import PermissionDenied
from django.contrib.auth.signals import user_logged_out
from django.contrib.auth import login, load_backend, BACKEND_SESSION_KEY
from django.dispatch import receiver
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.utils.http import is_safe_url

from compat import get_user_model, import_string
from compat import resolve_url

from hijack import settings as hijack_settings
from hijack.signals import post_superuser_login
from hijack.signals import post_superuser_logout

def get_used_backend(request):
    backend_str = request.session[BACKEND_SESSION_KEY]
    backend = load_backend(backend_str)
    return backend

def release_hijack(request):
    hijack_history = request.session.get('hijack_history', False)

    if not hijack_history:
        raise PermissionDenied

    if hijack_history:
        user_pk = hijack_history.pop()
        user = get_object_or_404(get_user_model(), pk=user_pk)
        backend = get_used_backend(request)
        user.backend = "%s.%s" % (backend.__module__,
                                  backend.__class__.__name__)
        login(request, user)
    if hijack_history:
        request.session['hijack_history'] = hijack_history
        request.session['is_hijacked_user'] = True
        request.session['display_hijack_warning'] = True
    else:
        try:
            del request.session['hijack_history']
            del request.session['is_hijacked_user']
            del request.session['display_hijack_warning']
        except KeyError:
            pass
    request.session.modified = True
    return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGOUT_REDIRECT_URL)

def is_authorized(hijacker, hijacked):
    """Checks if the user has the correct permission to Hijack another user.

    By default only superusers are allowed to hijack.

    An exception is made to allow staff members to hijack when
    HIJACK_AUTHORIZE_STAFF is enabled in the Django settings.

    By default it prevents staff users from hijacking other staff users.
    This can be disabled by enabling the HIJACK_AUTHORIZE_STAFF_TO_HIJACK_STAFF
    setting in the Django settings.

    Staff users can never hijack superusers. Also, hijacked users must have is_active==True.
    """
    if not hijacked.is_active:
        return False

    if hijacked.is_superuser and not hijacker.is_superuser:
        return False

    if hijacker.is_superuser:
        return True

    if hijacker.is_staff and hijack_settings.HIJACK_AUTHORIZE_STAFF:
        if hijacked.is_staff and not hijack_settings.HIJACK_AUTHORIZE_STAFF_TO_HIJACK_STAFF:
            return False
        return True

    return False

def check_hijack_authorization(request, user):
    check_authorization = import_string(hijack_settings.HIJACK_AUTHORIZATION_CHECK)
    is_authorized = check_authorization(request.user, user)
    if not is_authorized:
        raise PermissionDenied

def login_user(request, user):
    ''' hijack mechanism '''
    hijack_history = [request.user._meta.pk.value_to_string(request.user)]
    if request.session.get('hijack_history'):
        hijack_history = request.session['hijack_history'] + hijack_history

    check_hijack_authorization(request, user)

    backend = get_used_backend(request)
    user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
    last_login = user.last_login  # Save last_login to reset it after hijack login
    login(request, user)
    user.last_login = last_login
    user.save()
    post_superuser_login.send(sender=None, user_id=user.pk)
    request.session['hijack_history'] = hijack_history
    request.session['is_hijacked_user'] = True
    request.session['display_hijack_warning'] = True
    request.session.modified = True
    return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGIN_REDIRECT_URL)

@receiver(user_logged_out)
def logout_user(sender, **kwargs):
    ''' wraps logout signal '''
    user = kwargs['user']
    if hasattr(user, 'id'):
        post_superuser_logout.send(sender=None, user_id=user.pk)

def redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGIN_REDIRECT_URL):
    redirect_to = request.GET.get('next', '')
    if not is_safe_url(redirect_to):
        redirect_to = default_url
    return HttpResponseRedirect(resolve_url(redirect_to))
<commit_msg>Refactor default authorization check<commit_after>from django.core.exceptions import PermissionDenied
from django.contrib.auth.signals import user_logged_out
from django.contrib.auth import login, load_backend, BACKEND_SESSION_KEY
from django.dispatch import receiver
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.utils.http import is_safe_url

from compat import get_user_model, import_string
from compat import resolve_url

from hijack import settings as hijack_settings
from hijack.signals import post_superuser_login
from hijack.signals import post_superuser_logout

def get_used_backend(request):
    backend_str = request.session[BACKEND_SESSION_KEY]
    backend = load_backend(backend_str)
    return backend

def release_hijack(request):
    hijack_history = request.session.get('hijack_history', False)

    if not hijack_history:
        raise PermissionDenied

    if hijack_history:
        user_pk = hijack_history.pop()
        user = get_object_or_404(get_user_model(), pk=user_pk)
        backend = get_used_backend(request)
        user.backend = "%s.%s" % (backend.__module__,
                                  backend.__class__.__name__)
        login(request, user)
    if hijack_history:
        request.session['hijack_history'] = hijack_history
        request.session['is_hijacked_user'] = True
        request.session['display_hijack_warning'] = True
    else:
        try:
            del request.session['hijack_history']
            del request.session['is_hijacked_user']
            del request.session['display_hijack_warning']
        except KeyError:
            pass
    request.session.modified = True
    return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGOUT_REDIRECT_URL)

def is_authorized(hijacker, hijacked):
    """Checks if the user has the correct permission to Hijack another user.

    By default only superusers are allowed to hijack.

    An exception is made to allow staff members to hijack when
    HIJACK_AUTHORIZE_STAFF is enabled in the Django settings.

    By default it prevents staff users from hijacking other staff users.
    This can be disabled by enabling the HIJACK_AUTHORIZE_STAFF_TO_HIJACK_STAFF
    setting in the Django settings.

    Staff users can never hijack superusers. Also, hijacked users must have is_active==True.
    """
    if not hijacked.is_active:
        return False

    if hijacker.is_superuser:
        return True

    if hijacked.is_superuser:
        return False

    if hijacker.is_staff and hijack_settings.HIJACK_AUTHORIZE_STAFF:
        if hijacked.is_staff and not hijack_settings.HIJACK_AUTHORIZE_STAFF_TO_HIJACK_STAFF:
            return False
        return True

    return False

def check_hijack_authorization(request, user):
    check_authorization = import_string(hijack_settings.HIJACK_AUTHORIZATION_CHECK)
    is_authorized = check_authorization(request.user, user)
    if not is_authorized:
        raise PermissionDenied

def login_user(request, user):
    ''' hijack mechanism '''
    hijack_history = [request.user._meta.pk.value_to_string(request.user)]
    if request.session.get('hijack_history'):
        hijack_history = request.session['hijack_history'] + hijack_history

    check_hijack_authorization(request, user)

    backend = get_used_backend(request)
    user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
    last_login = user.last_login  # Save last_login to reset it after hijack login
    login(request, user)
    user.last_login = last_login
    user.save()
    post_superuser_login.send(sender=None, user_id=user.pk)
    request.session['hijack_history'] = hijack_history
    request.session['is_hijacked_user'] = True
    request.session['display_hijack_warning'] = True
    request.session.modified = True
    return redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGIN_REDIRECT_URL)

@receiver(user_logged_out)
def logout_user(sender, **kwargs):
    ''' wraps logout signal '''
    user = kwargs['user']
    if hasattr(user, 'id'):
        post_superuser_logout.send(sender=None, user_id=user.pk)

def redirect_to_next(request, default_url=hijack_settings.HIJACK_LOGIN_REDIRECT_URL):
    redirect_to = request.GET.get('next', '')
    if not is_safe_url(redirect_to):
        redirect_to = default_url
    return HttpResponseRedirect(resolve_url(redirect_to))
<|endoftext|>


<commit_before>"""Views for lutris main app"""

from django.http import Http404, HttpResponse
from django.views.generic import list_detail
from django.template.context import RequestContext
from django.shortcuts import render, redirect, get_object_or_404
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from games.models import Game, Runner, Genre, Platform, Company, Installer
from games.forms import InstallerForm
#pylint: disable=E1101

def home(request):
    """Homepage view"""
    featured = Game.objects.exclude(cover__exact="")[:5]
    return render(request, 'home.html', {'featured': featured})

def game_detail(request, slug):
    """docstring for game_detail"""
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/detail.html', {'game': game})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = InstallerForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/new-installer.html',
                  {'form': form, 'game': game})

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(request, slug):
    """Serve the content of an installer in yaml format"""
    installer = get_object_or_404(Installer, slug=slug)
    content = installer.content
    return HttpResponse(content, content_type="application/yaml")

def games_all(request):
    """View for all games"""
    games = Game.objects.all()
    return render('games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

def games_by_year(request, year):
    """View for games filtered by year"""
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(year=year),
        template_name="games/game_list.html",
        template_object_name="games",
        extra_context={"year": year}
    )

def games_by_genre(request, genre_slug):
    """View for games filtered by genre"""
    genre = get_object_or_404(Genre, slug=genre_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(genre__slug=genre_slug),
        template_name="games/game_list.html",
        template_object_name="games",
        extra_context={'genre': genre}
    )

def games_by_publisher(request, publisher_slug):
    """View for games filtered by publisher"""
    company = get_object_or_404(Company, slug=publisher_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(publisher=company),
        template_name="games/game_list.html",
        template_object_name='games',
        extra_context={'publisher': company}
    )

def games_by_developer(request, developer_slug):
    """View for games filtered by developer"""
    company = get_object_or_404(Company, slug=developer_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(developer=company),
        template_name="games/game_list.html",
        template_object_name='games',
        extra_context={'developer': company}
    )

def games_by_platform(request, platform_slug):
    """View for games filtered by platform"""
    platform = get_object_or_404(Platform, slug=platform_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(platform=platform),
        template_name="games/game_list.html",
        template_object_name='games',
        extra_context={'platform': platform}
    )
<commit_msg>but it's better when it works<commit_after>"""Views for lutris main app"""

from django.http import HttpResponse
from django.views.generic import list_detail
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from games.models import Game, Runner, Genre, Platform, Company, Installer
from games.forms import InstallerForm
#pylint: disable=E1101

def home(request):
    """Homepage view"""
    featured = Game.objects.exclude(cover__exact="")[:5]
    return render(request, 'home.html', {'featured': featured})

def game_detail(request, slug):
    """docstring for game_detail"""
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/detail.html', {'game': game})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = InstallerForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/new-installer.html',
                  {'form': form, 'game': game})

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(request, slug):
    """Serve the content of an installer in yaml format"""
    installer = get_object_or_404(Installer, slug=slug)
    content = installer.content
    return HttpResponse(content, content_type="application/yaml")

def games_all(request):
    """View for all games"""
    games = Game.objects.all()
    return render(request, 'games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

def games_by_year(request, year):
    """View for games filtered by year"""
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(year=year),
        template_name="games/game_list.html",
        template_object_name="games",
        extra_context={"year": year}
    )

def games_by_genre(request, genre_slug):
    """View for games filtered by genre"""
    genre = get_object_or_404(Genre, slug=genre_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(genre__slug=genre_slug),
        template_name="games/game_list.html",
        template_object_name="games",
        extra_context={'genre': genre}
    )

def games_by_publisher(request, publisher_slug):
    """View for games filtered by publisher"""
    company = get_object_or_404(Company, slug=publisher_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(publisher=company),
        template_name="games/game_list.html",
        template_object_name='games',
        extra_context={'publisher': company}
    )

def games_by_developer(request, developer_slug):
    """View for games filtered by developer"""
    company = get_object_or_404(Company, slug=developer_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(developer=company),
        template_name="games/game_list.html",
        template_object_name='games',
        extra_context={'developer': company}
    )

def games_by_platform(request, platform_slug):
    """View for games filtered by platform"""
    platform = get_object_or_404(Platform, slug=platform_slug)
    return list_detail.object_list(
        request,
        queryset=Game.objects.filter(platform=platform),
        template_name="games/game_list.html",
        template_object_name='games',
        extra_context={'platform': platform}
    )
<|endoftext|>


<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

#    Copyright 2011 OpenStack LLC
#
#    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.

NOVA_VERSION = ['2012', '2', '2']
YEAR, COUNT, REVISION = NOVA_VERSION
FINAL = False   # This becomes true at Release Candidate time

def canonical_version_string():
    return '.'.join(filter(None, NOVA_VERSION))

def version_string():
    if FINAL:
        return canonical_version_string()
    else:
        return '%s-dev' % (canonical_version_string(),)

def vcs_version_string():
    return 'LOCALBRANCH:LOCALREVISION'

def version_string_with_vcs():
    return '%s-%s' % (canonical_version_string(), vcs_version_string())
<commit_msg>Final versioning for 2012.2.2<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

#    Copyright 2011 OpenStack LLC
#
#    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.

NOVA_VERSION = ['2012', '2', '2']
YEAR, COUNT, REVISION = NOVA_VERSION
FINAL = True   # This becomes true at Release Candidate time

def canonical_version_string():
    return '.'.join(filter(None, NOVA_VERSION))

def version_string():
    if FINAL:
        return canonical_version_string()
    else:
        return '%s-dev' % (canonical_version_string(),)

def vcs_version_string():
    return 'LOCALBRANCH:LOCALREVISION'

def version_string_with_vcs():
    return '%s-%s' % (canonical_version_string(), vcs_version_string())
<|endoftext|>


<commit_before>from __future__ import absolute_import

import re

import bs4

from six import StringIO

def _visible(elem):
    if isinstance(elem, (bs4.element.ProcessingInstruction,
                         bs4.element.Doctype)):
        return False

    elif re.match('<!--.*-->', str(elem)):
        return False

    return True

def _get_file(f, **kwargs):
    encoding, errors = kwargs['encoding'], kwargs['encoding_errors']
    bdata = f.read()
    tdata = bdata.decode(encoding, errors)
    text, bs = StringIO(), bs4.BeautifulSoup(tdata, 'lxml')

    for elem in filter(_visible, bs.findAll(text=True)):
        text.write(elem)
        text.write(u' ')

    return text.getvalue()
<commit_msg>fix xml backend on py 2<commit_after>from __future__ import absolute_import

import re

import bs4

from six import StringIO
from six import PY3

def _is_visible(elem, encoding, errors):
    if isinstance(elem, (bs4.element.ProcessingInstruction,
                         bs4.element.Doctype)):
        return False

    if not PY3:
        elem = elem.encode(encoding, errors)
    if re.match('<!--.*-->', elem):
        return False

    return True

def _get_file(f, **kwargs):
    encoding, errors = kwargs['encoding'], kwargs['encoding_errors']
    bdata = f.read()
    tdata = bdata.decode(encoding, errors)
    text, bs = StringIO(), bs4.BeautifulSoup(tdata, 'lxml')

    for elem in bs.findAll(text=True):
        if _is_visible(elem, encoding, errors):
            text.write(elem)
            text.write(u' ')

    return text.getvalue()
<|endoftext|>


<commit_before>import numpy as np

import normalization
from signal_type import Signal
import utility

# hard-elbow hiss reduction
def hiss_reduction(signal):
    signal = signal.copy()
    noisewindow = _determine_noise_window(signal)
    signal = Signal(_subtract_noise_from_signal(signal, noisewindow),
                    signal.sampleRate)
    return normalization.normalize(signal)

def _find_lowest_peak_volume_window(windows):
    max_value_per_window = {window.max(): i for i, window
                            in enumerate(windows)}
    min_max_value_key = min(max_value_per_window, key=max_value_per_window.get)
    window_with_lowest_peak = max_value_per_window[min_max_value_key]
    return windows[window_with_lowest_peak][:]

def _split_signal_into_windows(signal):
    samples_per_window = utility.compute_samples_per_window(signal.sampleRate)
    splittable_size = samples_per_window * (len(signal) // samples_per_window)
    window_range = range(0, splittable_size, samples_per_window)
    return np.asarray([signal[i:i+samples_per_window] for i in window_range])

def _determine_noise_window(signal):
    signal_windows = _split_signal_into_windows(signal)
    return _find_lowest_peak_volume_window(signal_windows)

def _subtract_noise_from_signal(signal, noise):
    noise_spectrum = np.fft.rfft(noise)
    noise_spectrum[0] = 0
    return _subtract_noise_frequencies(signal, noise_spectrum)

def _subtract_noise_frequencies(signal, noise_spectrum):
    windows = _split_signal_into_windows(signal)
    windows_no_noise = _remove_noise_from_signal_windows(windows,
                                                         noise_spectrum)
    return _combine_windows_to_signal(windows_no_noise)

def _remove_noise_from_signal_windows(windows, noise_spectrum):
    spectrums = np.asarray([np.fft.rfft(window) for window in windows])
    spectrums_no_noise = np.array([_remove_noise(window, noise_spectrum) for
                                   window in spectrums])
    return np.asarray([np.fft.irfft(window) for window in spectrums_no_noise])

def _remove_noise(spectrum, noise_spectrum):
    window_size = len(noise_spectrum)
    spectrum[0] = 0
    return np.asarray([_remove_noise_frequency(spectrum[i],
                                               noise_spectrum[i])
                       for i in range(window_size)])

def _remove_noise_frequency(signal, noise):
    if abs(signal) < abs(noise):
        return 0
    else:
        return signal

def _combine_windows_to_signal(windows):
    combination = []
    for window in windows:
        for element in window:
            combination.append(element)
    return np.asarray(combination)
<commit_msg>Small performance changes.<commit_after>import numpy as np

import normalization
from signal_type import Signal
import utility

# hard-elbow hiss reduction
def hiss_reduction(signal):
    signal = signal.copy()
    noisewindow = _determine_noise_window(signal)
    signal = Signal(_subtract_noise_from_signal(signal, noisewindow),
                    signal.sampleRate)
    return normalization.normalize(signal)

def _find_lowest_peak_volume_window(windows):
    max_value_per_window = {window.max(): i for i, window
                            in enumerate(windows)}
    min_max_value_key = min(max_value_per_window, key=max_value_per_window.get)
    window_with_lowest_peak = max_value_per_window[min_max_value_key]
    return windows[window_with_lowest_peak][:]

def _split_signal_into_windows(signal):
    samples_per_window = utility.compute_samples_per_window(signal.sampleRate)
    splittable_size = samples_per_window * (len(signal) // samples_per_window)
    window_range = range(0, splittable_size, samples_per_window)
    return np.array([signal[i:i+samples_per_window] for i in window_range])

def _determine_noise_window(signal):
    signal_windows = _split_signal_into_windows(signal)
    return _find_lowest_peak_volume_window(signal_windows)

def _subtract_noise_from_signal(signal, noise):
    noise_spectrum = np.fft.rfft(noise)
    noise_spectrum[0] = 0
    return _subtract_noise_frequencies(signal, noise_spectrum)

def _subtract_noise_frequencies(signal, noise_spectrum):
    windows = _split_signal_into_windows(signal)
    windows_no_noise = _remove_noise_from_signal_windows(windows,
                                                         noise_spectrum)
    return _combine_windows_to_signal(windows_no_noise)

def _remove_noise_from_signal_windows(windows, noise_spectrum):
    spectrums = np.array([np.fft.rfft(window) for window in windows])
    spectrums_no_noise = np.array([_remove_noise(window, noise_spectrum) for
                                   window in spectrums])
    return np.array([np.fft.irfft(window) for window in spectrums_no_noise])

def _remove_noise(spectrum, noise_spectrum):
    window_size = len(noise_spectrum)
    spectrum[0] = 0
    return np.asarray([_remove_noise_frequency(spectrum[i],
                                               noise_spectrum[i])
                       for i in range(window_size)])

def _remove_noise_frequency(signal, noise):
    if abs(signal) < abs(noise):
        return 0
    else:
        return signal

def _combine_windows_to_signal(windows):
    combination = []
    for window in windows:
        for element in window:
            combination.append(element)
    return np.array(combination)
<|endoftext|>


<commit_before>from __future__ import unicode_literals
import frappe

def execute():
	colors = ['red', 'green', 'blue', 'yellow', 'skyblue', 'orange']
	hex = ['#ffc4c4', '#cef6d1', '#d2d2ff', '#fffacd', '#d2f1ff', '#ffd2c2']

	def get_hex_for_color(color):
		index = colors.index(color)
		return hex[index]

	query = '''
		update tabEvent
		set color='{hex}'
		where color='{color}'
	'''

	for color in colors:
		frappe.db.sql(query.format(color=color, hex=get_hex_for_color(color)))

	frappe.db.commit()<commit_msg>codacy fix<commit_after>from __future__ import unicode_literals
import frappe

def execute():
	colors = ['red', 'green', 'blue', 'yellow', 'skyblue', 'orange']
	hex_colors = ['#ffc4c4', '#cef6d1', '#d2d2ff', '#fffacd', '#d2f1ff', '#ffd2c2']

	def get_hex_for_color(color):
		index = colors.index(color)
		return hex_colors[index]

	query = '''
		update tabEvent
		set color='{hex}'
		where color='{color}'
	'''

	for color in colors:
		frappe.db.sql(query.format(color=color, hex=get_hex_for_color(color)))

	frappe.db.commit()
<|endoftext|>


<commit_before>VERSION = (1, 8, 3)

__version__ = '.'.join(map(str, VERSION))
<commit_msg>bump version so users know it is not release<commit_after>VERSION = (1, 8, 4)

__version__ = '.'.join(map(str, VERSION))
<|endoftext|>


<commit_before>import cv2
import numpy as np
import binascii
from bitstring import BitArray

def read_image(image_path):
    """reads image by opencv"""
    return cv2.imread(image_path)

def histogram_matrix(image_path, resize_dim=32, num_bins=16):
    """reads RGB image and returns histogram matrix of BGR bands"""
    img = read_image(image_path)
    resized_image = cv2.resize(img, (resize_dim, resize_dim))
    hist_array = []
    for band in range(3):
        hist = cv2.calcHist([resized_image], [band], None, [num_bins], [0, 256])
        hist_array.append(hist.T[0].astype(int))
    return hist_array

def histogram_hash(hist_matrix, pixel_count):
    """converts histogram matrix into hexidecimal string.
       first divide matrix values by pixel_count in order to find frequency.
       second map values in range [0,1] to values in range [0,15]
       finally join hexidecimal values as string
    """
    result_hash = ""
    for band_hist in hist_matrix:
        freq = band_hist/pixel_count
        hex_values = np.interp(freq, [0, 1], [0, 15])
        hex_values = np.round(hex_values, decimals=0).astype(np.int16)
        hex_string = "".join([hex(val)[2:] for val in hex_values])
        result_hash += hex_string
    return result_hash

def hamming_distance(hash1, hash2):
    bin1 = BitArray('0x' + hash1)
    bin2 = BitArray('0x' + hash2)
    print(bin1.bin)
    print(bin2.bin)
    return sum(c1 != c2 for c1, c2 in zip(bin1.bin, bin2.bin))
<commit_msg>remove additional library dependency<commit_after>import cv2
import numpy as np

def read_image(image_path):
    """reads image by opencv"""
    return cv2.imread(image_path)

def histogram_matrix(image_path, resize_dim=32, num_bins=16):
    """reads RGB image and returns histogram matrix of BGR bands"""
    img = read_image(image_path)
    resized_image = cv2.resize(img, (resize_dim, resize_dim))
    hist_array = []
    for band in range(3):
        hist = cv2.calcHist([resized_image], [band], None, [num_bins], [0, 256])
        hist_array.append(hist.T[0].astype(int))
    return hist_array

def histogram_hash(hist_matrix, pixel_count):
    """converts histogram matrix into hexidecimal string.
       first divide matrix values by pixel_count in order to find frequency.
       second map values in range [0,1] to values in range [0,15]
       finally join hexidecimal values as string
    """
    result_hash = ""
    for band_hist in hist_matrix:
        freq = band_hist/pixel_count
        hex_values = np.interp(freq, [0, 1], [0, 15])
        hex_values = np.round(hex_values, decimals=0).astype(np.int16)
        hex_string = "".join([hex(val)[2:] for val in hex_values])
        result_hash += hex_string
    return result_hash

def hamming_distance(hash1, hash2):
    bin1 = '{0:b}'.format(int(hash1, 16))
    bin2 = '{0:b}'.format(int(hash2, 16))
    return sum(c1 != c2 for c1, c2 in zip(bin1, bin2))
<|endoftext|>