<commit_before>import re
import urllib
import urlparse
import logging

from billy import db

# metadata cache
__metadata = {}

# Adapted from NLTK's english stopwords
stop_words = [
    'i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves',
    'you', 'your', 'yours', 'yourself', 'yourselves',
    'he', 'him', 'his', 'himself', 'she', 'her', 'hers',
    'herself', 'it', 'its', 'itself', 'they',
    'them', 'their', 'theirs', 'themselves', 'what',
    'which',  'who', 'whom', 'this', 'that', 'these', 'those',
    'am', 'is', 'are', 'was', 'were', 'be', 'been',
    'being', 'have', 'has', 'had', 'having', 'do', 'does',
    'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or',
    'because', 'as', 'until', 'while', 'of', 'at', 'by',
    'for', 'with', 'about', 'against', 'between',
    'into', 'through', 'during', 'before', 'after',
    'above', 'below', 'to', 'from', 'up', 'down', 'in',
    'out', 'on', 'off', 'over', 'under', 'again', 'further',
    'then', 'once', 'here', 'there', 'when', 'where', 'why',
    'how', 'all', 'any', 'both', 'each', 'few', 'more',
    'most', 'other', 'some', 'such', 'no', 'nor', 'not',
    'only', 'own', 'same', 'so', 'than', 'too', 'very',
    's', 't', 'can', 'will', 'just', 'don', 'should',
    'now', '']

def tokenize(str):
    return re.split(r"[\s.,!?'\"`()]+", str)

def keywordize(str):
    """
    Splits a string into words, removes common stopwords, stems and removes
    duplicates.
    """
    import jellyfish
    return set([jellyfish.porter_stem(word.lower().encode('ascii',
                                                          'ignore'))
                for word in tokenize(str)
                if (word.isalpha() or word.isdigit()) and
                word.lower() not in stop_words])

def metadata(abbr):
    """
    Grab the metadata for the given two-letter abbreviation.
    """
    # This data should change very rarely and is queried very often so
    # cache it here
    abbr = abbr.lower()
    if abbr in __metadata:
        return __metadata[abbr]
    return db.metadata.find_one({'_id': abbr})

def chamber_name(abbr, chamber):
    if chamber in ('joint', 'other'):
        return 'Joint'

    return metadata(abbr)['%s_chamber_name' % chamber].split()[0]

def term_for_session(abbr, session):
    meta = metadata(abbr)

    for term in meta['terms']:
        if session in term['sessions']:
            return term['name']

    raise ValueError("no such session")

def urlescape(url):
    scheme, netloc, path, qs, anchor = urlparse.urlsplit(url)
    path = urllib.quote(path, '/%')
    qs = urllib.quote_plus(qs, ':&=')
    return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))

def extract_fields(d, fields, delimiter='|'):
    """ get values out of an object ``d`` for saving to a csv """
    rd = {}
    for f in fields:
        v = d.get(f, None)
        if isinstance(v, (str, unicode)):
            v = v.encode('utf8')
        elif isinstance(v, list):
            v = delimiter.join(v)
        rd[f] = v
    return rd

def configure_logging(verbosity_count=0, module=None):
    verbosity = {0: logging.WARNING, 1: logging.INFO}.get(verbosity_count,
                                                          logging.DEBUG)
    if module:
        format = ("%(asctime)s %(name)s %(levelname)s " + module +
                  " %(message)s")
    else:
        format = "%(asctime)s %(name)s %(levelname)s %(message)s"
    logging.basicConfig(level=verbosity, format=format, datefmt="%H:%M:%S")
<commit_msg>fix error from term_for_session<commit_after>import re
import urllib
import urlparse
import logging

from billy import db

# metadata cache
__metadata = {}

# Adapted from NLTK's english stopwords
stop_words = [
    'i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves',
    'you', 'your', 'yours', 'yourself', 'yourselves',
    'he', 'him', 'his', 'himself', 'she', 'her', 'hers',
    'herself', 'it', 'its', 'itself', 'they',
    'them', 'their', 'theirs', 'themselves', 'what',
    'which',  'who', 'whom', 'this', 'that', 'these', 'those',
    'am', 'is', 'are', 'was', 'were', 'be', 'been',
    'being', 'have', 'has', 'had', 'having', 'do', 'does',
    'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or',
    'because', 'as', 'until', 'while', 'of', 'at', 'by',
    'for', 'with', 'about', 'against', 'between',
    'into', 'through', 'during', 'before', 'after',
    'above', 'below', 'to', 'from', 'up', 'down', 'in',
    'out', 'on', 'off', 'over', 'under', 'again', 'further',
    'then', 'once', 'here', 'there', 'when', 'where', 'why',
    'how', 'all', 'any', 'both', 'each', 'few', 'more',
    'most', 'other', 'some', 'such', 'no', 'nor', 'not',
    'only', 'own', 'same', 'so', 'than', 'too', 'very',
    's', 't', 'can', 'will', 'just', 'don', 'should',
    'now', '']

def tokenize(str):
    return re.split(r"[\s.,!?'\"`()]+", str)

def keywordize(str):
    """
    Splits a string into words, removes common stopwords, stems and removes
    duplicates.
    """
    import jellyfish
    return set([jellyfish.porter_stem(word.lower().encode('ascii',
                                                          'ignore'))
                for word in tokenize(str)
                if (word.isalpha() or word.isdigit()) and
                word.lower() not in stop_words])

def metadata(abbr):
    """
    Grab the metadata for the given two-letter abbreviation.
    """
    # This data should change very rarely and is queried very often so
    # cache it here
    abbr = abbr.lower()
    if abbr in __metadata:
        return __metadata[abbr]
    return db.metadata.find_one({'_id': abbr})

def chamber_name(abbr, chamber):
    if chamber in ('joint', 'other'):
        return 'Joint'

    return metadata(abbr)['%s_chamber_name' % chamber].split()[0]

def term_for_session(abbr, session):
    meta = metadata(abbr)

    for term in meta['terms']:
        if session in term['sessions']:
            return term['name']

    raise ValueError("no such session '%s'" % session)

def urlescape(url):
    scheme, netloc, path, qs, anchor = urlparse.urlsplit(url)
    path = urllib.quote(path, '/%')
    qs = urllib.quote_plus(qs, ':&=')
    return urlparse.urlunsplit((scheme, netloc, path, qs, anchor))

def extract_fields(d, fields, delimiter='|'):
    """ get values out of an object ``d`` for saving to a csv """
    rd = {}
    for f in fields:
        v = d.get(f, None)
        if isinstance(v, (str, unicode)):
            v = v.encode('utf8')
        elif isinstance(v, list):
            v = delimiter.join(v)
        rd[f] = v
    return rd

def configure_logging(verbosity_count=0, module=None):
    verbosity = {0: logging.WARNING, 1: logging.INFO}.get(verbosity_count,
                                                          logging.DEBUG)
    if module:
        format = ("%(asctime)s %(name)s %(levelname)s " + module +
                  " %(message)s")
    else:
        format = "%(asctime)s %(name)s %(levelname)s %(message)s"
    logging.basicConfig(level=verbosity, format=format, datefmt="%H:%M:%S")
<|endoftext|>


<commit_before>from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
from utkik.decorators import http_methods

class ViewException(Exception):
    pass

class ContextData(object):
    """This will contain attributes for context. All the attributes are later
    collected by ContextData().__dict__.
    """

class View(object):
    """A minimalist View base class.

    Goals
    -----
    - Building context for rendering should be simple.

    - Source should be easy to follow and encourage this for implementing
      subclasses if possible.

    - Keep methods short and provide useful hooks for sub classing.

    - Embrace the instance and don't pass request nor context around.

    - Narrow the scope to most common use but without limiting less usual
      use-cases.
    """

    methods = ['GET', 'POST'] # allowed HTTP methods
    decorators = [] # a list of decorators
    template = None # template to render to
    ajax_template = None # template to render to for ajax calls

    def __init__(self):
        """All we do here is to instantiate the ContextData class"""
        self.c = ContextData() # c is for context
        self.request = None

    def dispatch(self, request, *args, **kwargs):
        """View entry point. The utkik dispatcher will create a new instance of
        the current class and call this method when the Django handler makes a
        call to the view.
        """
        self.request = request
        return self._decorate(self.get_response)(request, *args, **kwargs)

    def _decorate(self, f):
        """This is meant to decorate ``self.get_response`` with
        ``self.decorators`` much like you would decorate a view function (if you
        remember that era). There is one decorator automatically added here and
        that is the ``http_methods`` computed decorator that uses
        ``self.methods`` attribute and avalable handlers to define what methods
        are allowed.
        """
        for d in reversed(self.decorators):
            f = d(f)
        methods = [m for m in self.methods if hasattr(self, m.lower())]
        return http_methods(*methods)(f)

    def get_response(self, request, *args, **kwargs):
        """Returns the response from a successful request to the view. In it's
        default implementation it will direct to a suitable handler method based
        on the HTTP method call. If this handler does not return a response, we
        will simply call and return ``self.render``. Request is just passed in
        here for decorator compatibilty reasons.
        """
        return self.get_handler()(*args, **kwargs) or self.render()

    def get_handler(self):
        """Return a suitable handler. You can override this for example if you
        want another handler for ajax calls.
        """
        return getattr(self, self.request.method.lower())

    def get_context(self):
        """If you want to add some extra context or modify the current context
        this is a good place. This method is called from ``self.render``.
        """
        return self.c.__dict__

    def get_template(self):
        """Returns a template for ``self.render`` method, this is mostly for
        having an alternative template for ajax calls.
        """
        if self.request.is_ajax() and self.ajax_template:
            return self.ajax_template
        if not self.template:
            raise ViewException(
                _('%s does not define a template to render to.') % self)
        return self.template

    def render(self):
        """
        Renders ``self.get_context()`` to ``self.template``. This is called from
        ``self.get_response`` if the handler does not return a response.
        """
        return render_to_response(self.get_template(), self.get_context(),
            RequestContext(self.request))

<commit_msg>I'm leaving you ajax<commit_after>from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _
from utkik.decorators import http_methods

class ViewException(Exception):
    pass

class ContextData(object):
    """This will contain attributes for context. All the attributes are later
    collected by ContextData().__dict__.
    """

class View(object):
    """A minimalist View base class.

    Goals
    -----
    - Building context for rendering should be simple.

    - Source should be easy to follow and encourage this for implementing
      subclasses if possible.

    - Keep methods short and provide useful hooks for sub classing.

    - Embrace the instance and don't pass request nor context around.

    - Narrow the scope to most common use but without limiting less usual
      use-cases.
    """

    methods = ['GET', 'POST'] # allowed HTTP methods
    decorators = [] # a list of decorators
    template = None # template to render to

    def __init__(self):
        """All we do here is to instantiate the ContextData class"""
        self.c = ContextData() # c is for context
        self.request = None

    def dispatch(self, request, *args, **kwargs):
        """View entry point. The utkik dispatcher will create a new instance of
        the current class and call this method when the Django handler makes a
        call to the view.
        """
        self.request = request
        return self._decorate(self.get_response)(request, *args, **kwargs)

    def _decorate(self, f):
        """This is meant to decorate ``self.get_response`` with
        ``self.decorators`` much like you would decorate a view function (if you
        remember that era). There is one decorator automatically added here and
        that is the ``http_methods`` computed decorator that uses
        ``self.methods`` attribute and avalable handlers to define what methods
        are allowed.
        """
        for d in reversed(self.decorators):
            f = d(f)
        methods = [m for m in self.methods if hasattr(self, m.lower())]
        return http_methods(*methods)(f)

    def get_response(self, request, *args, **kwargs):
        """Returns the response from a successful request to the view. In it's
        default implementation it will direct to a suitable handler method based
        on the HTTP method call. If this handler does not return a response, we
        will simply call and return ``self.render``. Request is just passed in
        here for decorator compatibilty reasons, don't use it, don't get
        confused by it, just use ``self.request``.
        """
        return self.get_handler()(*args, **kwargs) or self.render()

    def get_handler(self):
        """Return a suitable handler. You can override this for example if you
        want another handler for ajax calls.
        """
        return getattr(self, self.request.method.lower())

    def get_context(self):
        """If you want to add some extra context or modify the current context
        this is a good place. This method is called from ``self.render``.
        """
        return self.c.__dict__

    def render(self, template=None):
        """
        Renders ``self.get_context()`` to ``self.template`` or a template
        argument. This is called from ``self.get_response`` if the handler does
        not return a response.
        """
        template = template or self.template
        if not template:
            raise ViewException(_('Missing template to render to.'))
        return render_to_response(
            template, self.get_context(), RequestContext(self.request))

<|endoftext|>


<commit_before>#!/usr/bin/env python
# encoding: utf-8
"""Main application class of vimiv."""

import os
import sys
from gi import require_version
require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, Gio, GLib
from vimiv.configparser import parse_dirs, parse_config
from vimiv.image import Image
from vimiv.fileactions import FileExtras, populate
from vimiv.library import Library
from vimiv.thumbnail import Thumbnail
from vimiv.manipulate import Manipulate
from vimiv.statusbar import Statusbar
from vimiv.commandline import CommandLine
from vimiv.commands import Commands
from vimiv.completions import VimivComplete
from vimiv.slideshow import Slideshow
from vimiv.keyhandler import KeyHandler
from vimiv.tags import TagHandler
from vimiv.mark import Mark
from vimiv.information import Information
from vimiv.window import Window

class Vimiv(Gtk.Application):
    """Main vimiv application class inheriting from Gtk.Application.

    Attributes:
        settings: Settings from configfiles to use.
        paths: List of paths for images.
        index: Current position in paths.
        widgets: Dictionary of vimiv widgets.
            widgets[widget-name] = Gtk.Widget
        directory: Directory in which configfiles and data are stored.
        commands: Dictionary of commands.
            commands[command-name] = [function, *args]
        aliases: Dicionary of aliases to commands.
            aliases[alias-name] = command-name
        functions: Dictionary of functions. Includes all commands and additional
            functions that cannot be called from the commandline.
        screensize: Available screensize.
    """

    def __init__(self, application_id="org.vimiv"):
        """Create the Gtk.Application and connect the activate signal.

        Args:
            application_id: The ID used to register vimiv. Default: org.vimiv.
        """
        # Create directory structure and get settings
        parse_dirs()
        Gtk.Application.__init__(self, application_id=application_id)
        self.set_flags(Gio.ApplicationFlags.HANDLES_OPEN)
        self.connect("activate", self.activate_vimiv)
        self.settings = parse_config()
        self.paths = []
        self.index = 0
        self.widgets = {}
        self.directory = os.path.expanduser("~/.vimiv")
        self.commands = {}
        self.aliases = {}
        self.functions = {}
        # Sceen and window size TODO put somewhere else
        screen = Gdk.Screen()
        self.screensize = [screen.width(), screen.height()]
        # Set up all commandline options
        self.init_commandline_options()

    # Any different number of arguments will fail
    # pylint: disable=arguments-differ
    def do_open(self, files, n_files, hint):
        """Open files by populating self.paths and self.index.

        Args:
            files: List of Gio.Files.
            n_files: Number of files.
            hint: Special string for user, always empty in vimiv.
        """
        filenames = [fil.get_path() for fil in files]
        # Move to the directory of the first argument
        if os.path.isdir(filenames[0]):
            working_directory = filenames[0]
        else:
            working_directory = os.path.dirname(filenames[0])
        if os.path.exists(working_directory):
            os.chdir(working_directory)
        # Populate list of images
        recursive = self.settings["GENERAL"]["recursive"]
        shuffle = self.settings["GENERAL"]["shuffle"]
        self.paths, self.index = populate(filenames, recursive, shuffle)

        # Activate vimiv after opening files
        self.activate_vimiv(self)

    # Any different number of arguments will fail
    # pylint: disable=arguments-differ
    def do_handle_local_options(self, options):
        """Handle commandline arguments.

        Args:
            command_line:
        """
        if options.contains("version"):
            information = Information()
            print(information.get_version())
            return 0  # To exit
        if options.contains("bar"):
            self.settings["GENERAL"]["display_bar"] = True
        elif options.contains("no-bar"):
            self.settings["GENERAL"]["display_bar"] = False
        if options.contains("library"):
            self.settings["LIBRARY"]["show_library"] = True
        elif options.contains("no-library"):
            self.settings["LIBRARY"]["show_library"] = False
        if options.contains("fullscreen"):
            self.settings["GENERAL"]["start_fullscreen"] = True
        elif options.contains("no-fullscreen"):
            self.settings["GENERAL"]["start_fullscreen"] = False
        if options.contains("shuffle"):
            self.settings["GENERAL"]["shuffle"] = True
        elif options.contains("no-shuffle"):
            self.settings["GENERAL"]["shuffle"] = False
        if options.contains("recursive"):
            self.settings["GENERAL"]["recursive"] = True
        elif options.contains("no-recursive"):
            self.settings["GENERAL"]["recursive"] = False
        if options.contains("slideshow"):
            self.settings["GENERAL"]["start_slideshow"] = True
        if options.contains("start-from-desktop"):
            os.chdir(self.settings["LIBRARY"]["desktop_start_dir"])
        elif not sys.stdin.isatty():
            tty_paths = []
            for line in sys.stdin:
                tty_paths.append(line.rstrip("\n"))
            self.paths, self.index = populate(tty_paths)
        if options.contains("slideshow-delay"):
            delay = options.lookup_value("slideshow-delay").unpack()
            self.settings["GENERAL"]["slideshow_delay"] = delay
        if options.contains("geometry"):
            geometry = options.lookup_value("geometry").unpack()
            self.settings["GENERAL"]["geometry"] = geometry
        return -1  # To continue

    def activate_vimiv(self, app):
        """Starting point for the vimiv application.

        Args:
            app: The application itself.
        """
        self.init_widgets()
        self.create_window_structure()
        app.add_window(self["window"])
        # Show everything and then hide whatever needs to be hidden
        self["window"].show_all()
        self["manipulate"].scrolled_win.hide()
        self["commandline"].grid.hide()
        # Statusbar depending on setting
        if self["statusbar"].hidden:
            self["statusbar"].bar.hide()
        # Try to generate imagelist recursively from the current directory if
        # recursive is given and not paths exist
        if self.settings["GENERAL"]["recursive"] and not self.paths:
            shuffle = self.settings["GENERAL"]["shuffle"]
            self.paths, self.index = populate([os.getcwd()], True, shuffle)
        # Show the image if an imagelist exists
        if self.paths:
            self["image"].move_index(True, False, 0)
            # Show library at the beginning?
            if not self["library"].show_at_start:
                self["library"].grid.hide()
            self["image"].scrolled_win.grab_focus()
            # Start in slideshow mode?
            if self["slideshow"].at_start:
                self["slideshow"].toggle()
        else:
            # Slideshow without paths makes no sense
            self["slideshow"].running = False
            self["library"].reload(os.getcwd())
            if self["library"].expand:
                self["image"].scrolled_win.hide()
            self["statusbar"].err_message(
                "No valid paths, opening library viewer")

    def init_widgets(self):
        """Create all the other widgets and add them to the class."""
        self["keyhandler"] = KeyHandler(self, self.settings)
        self["commandline"] = CommandLine(self, self.settings)
        self["tags"] = TagHandler(self)
        self["mark"] = Mark(self, self.settings)
        self["fileextras"] = FileExtras(self)
        self["statusbar"] = Statusbar(self, self.settings)
        self["completions"] = VimivComplete(self)
        self["slideshow"] = Slideshow(self, self.settings)
        self["image"] = Image(self, self.settings)
        self["library"] = Library(self, self.settings)
        self["thumbnail"] = Thumbnail(self, self.settings)
        self["manipulate"] = Manipulate(self, self.settings)
        self["information"] = Information()
        self["window"] = Window(self, self.settings)
        Commands(self, self.settings)

    def create_window_structure(self):
        """Generate the structure of all the widgets and add it to the window.

        There is a large Gtk.Grid() to organize the widgets packed into a
        Gtk.Overlay(). The commandline is added as overlay.
        """
        main_grid = Gtk.Grid()
        main_grid.attach(self["library"].grid, 0, 0, 1, 1)
        main_grid.attach(self["image"].scrolled_win, 1, 0, 1, 1)
        main_grid.attach(self["manipulate"].scrolled_win, 0, 1, 2, 1)
        main_grid.attach(self["statusbar"].bar, 0, 2, 2, 1)

        # Overlay contains grid mainly and adds commandline as floating
        overlay = Gtk.Overlay()
        overlay.add(main_grid)
        overlay.add_overlay(self["commandline"].grid)
        self["window"].add(overlay)

    def quit_wrapper(self, force=False):
        """Quit the applications, print marked files and save history.

        Args:
            force: If True quit even if an image was edited.
        """
        for image in self["mark"].marked:
            print(image)
        # Check if image has been edited
        if self["image"].check_for_edit(force):
            return
        # Save the history
        histfile = os.path.expanduser("~/.vimiv/history")
        histfile = open(histfile, 'w')
        for cmd in self["commandline"].history:
            cmd += "\n"
            histfile.write(cmd)
        histfile.close()
        # Call Gtk.Application.quit()
        self.quit()

    def get_pos(self, get_filename=False, force_widget=""):
        """Get the current position in the focused widget.

        get_filename: If True return filename instead of position.
        force_widget: String to force getting the position of a widget

        Return:
            Current position as Int or filename.
        """
        # Find widget to work on
        if force_widget:
            focused_widget = force_widget
        elif self["image"].scrolled_win.is_focus():
            focused_widget = "im"
        elif self["library"].treeview.is_focus():
            focused_widget = "lib"
        elif self["thumbnail"].iconview.is_focus():
            focused_widget = "thu"

        # Get position and name
        if focused_widget != "im":
            if focused_widget == "lib":
                path = self["library"].treeview.get_cursor()[0]
                filelist = self["library"].files
            elif focused_widget == "thu":
                path = self["thumbnail"].iconview.get_cursor()[1]
                filelist = self.paths
            try:
                position = path.get_indices()[0]
                if get_filename:
                    return filelist[position]
                else:
                    return position
            except:
                if get_filename:
                    return ""
                else:
                    return 0
        else:
            if get_filename:
                return self.paths[self.index]
            else:
                return self.index

    def init_commandline_options(self):
        """Add all possible commandline options."""
        def add_option(name, short, help_str, flags=GLib.OptionFlags.NONE,
                       arg=GLib.OptionArg.NONE, value=None):
            """Add a single option.

            Args:
                name: Long name of the option, called via --name.
                short: Short name of the option, called via -s.
                help_str: Displayed help text when calling --help.
                flags: GLib options.
                arg: Type of the value to give after option.
                value: Name of the value to give after the option.
            """
            if short:
                short = ord(short)
            self.add_main_option(name, short, flags, arg, help_str, value)
        add_option("bar", "b", "Display statusbar")
        add_option("no-bar", "B", "Hide statusbar")
        add_option("library", "l", "Display library")
        add_option("no-library", "L", "Hide library")
        add_option("fullscreen", "f", "Start fullscreen")
        add_option("no-fullscreen", "F", "Do not start fullscreen")
        add_option("shuffle", "s", "Shuffle filelist")
        add_option("no-shuffle", "S", "Do not shuffle filelist")
        add_option("recursive", "r", "Search directory recursively for images")
        add_option("no-recursive", "R",
                   "Do not search directory recursively for images")
        add_option("version", "v", "Print version information and exit")
        add_option("slideshow", 0, "Start slideshow at startup")
        add_option("start-from-desktop", 0,
                   "Start using the desktop_start_dir as path")
        add_option("slideshow-delay", 0, "Set slideshow delay",
                   arg=GLib.OptionArg.DOUBLE, value="delay")
        add_option("geometry", "g", "Set the starting geometry",
                   arg=GLib.OptionArg.STRING, value="GEOMETRY")

    def __getitem__(self, name):
        """Convenience method to access widgets via self[name].

        Args:
            name: Name of the widget to access.
        Return:
            The widget if it exists. None else.
        """
        if name in self.widgets:
            return self.widgets[name]
        else:
            return None

    def __setitem__(self, name, widget):
        """Convenience method to access widgets via self[name].

        Args:
            name: Name of the widget to add.
            item: The actual widget to which name will refer.
        """
        self.widgets[name] = widget
<commit_msg>Clean up get_pos and do_handle_local_options<commit_after>#!/usr/bin/env python
# encoding: utf-8
"""Main application class of vimiv."""

import os
import sys
from gi import require_version
require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, Gio, GLib
from vimiv.configparser import parse_dirs, parse_config
from vimiv.image import Image
from vimiv.fileactions import FileExtras, populate
from vimiv.library import Library
from vimiv.thumbnail import Thumbnail
from vimiv.manipulate import Manipulate
from vimiv.statusbar import Statusbar
from vimiv.commandline import CommandLine
from vimiv.commands import Commands
from vimiv.completions import VimivComplete
from vimiv.slideshow import Slideshow
from vimiv.keyhandler import KeyHandler
from vimiv.tags import TagHandler
from vimiv.mark import Mark
from vimiv.information import Information
from vimiv.window import Window

class Vimiv(Gtk.Application):
    """Main vimiv application class inheriting from Gtk.Application.

    Attributes:
        settings: Settings from configfiles to use.
        paths: List of paths for images.
        index: Current position in paths.
        widgets: Dictionary of vimiv widgets.
            widgets[widget-name] = Gtk.Widget
        directory: Directory in which configfiles and data are stored.
        commands: Dictionary of commands.
            commands[command-name] = [function, *args]
        aliases: Dicionary of aliases to commands.
            aliases[alias-name] = command-name
        functions: Dictionary of functions. Includes all commands and additional
            functions that cannot be called from the commandline.
        screensize: Available screensize.
    """

    def __init__(self, application_id="org.vimiv"):
        """Create the Gtk.Application and connect the activate signal.

        Args:
            application_id: The ID used to register vimiv. Default: org.vimiv.
        """
        # Create directory structure and get settings
        parse_dirs()
        Gtk.Application.__init__(self, application_id=application_id)
        self.set_flags(Gio.ApplicationFlags.HANDLES_OPEN)
        self.connect("activate", self.activate_vimiv)
        self.settings = parse_config()
        self.paths = []
        self.index = 0
        self.widgets = {}
        self.directory = os.path.expanduser("~/.vimiv")
        self.commands = {}
        self.aliases = {}
        self.functions = {}
        # Sceen and window size TODO put somewhere else
        screen = Gdk.Screen()
        self.screensize = [screen.width(), screen.height()]
        # Set up all commandline options
        self.init_commandline_options()

    # Any different number of arguments will fail
    # pylint: disable=arguments-differ
    def do_open(self, files, n_files, hint):
        """Open files by populating self.paths and self.index.

        Args:
            files: List of Gio.Files.
            n_files: Number of files.
            hint: Special string for user, always empty in vimiv.
        """
        filenames = [fil.get_path() for fil in files]
        # Move to the directory of the first argument
        if os.path.isdir(filenames[0]):
            working_directory = filenames[0]
        else:
            working_directory = os.path.dirname(filenames[0])
        if os.path.exists(working_directory):
            os.chdir(working_directory)
        # Populate list of images
        recursive = self.settings["GENERAL"]["recursive"]
        shuffle = self.settings["GENERAL"]["shuffle"]
        self.paths, self.index = populate(filenames, recursive, shuffle)

        # Activate vimiv after opening files
        self.activate_vimiv(self)

    # Any different number of arguments will fail
    # pylint: disable=arguments-differ
    def do_handle_local_options(self, options):
        """Handle commandline arguments.

        Args:
            options: The dictionary containing all options given to the
                commandline.
        Return:
            Exitcode or -1 to continue
        """
        def set_option(name, section, setting, value=0):
            """Set a setting in self.settings according to commandline option.

            Args:
                name: Name of the commandline option
                section: Name of section in self.settings to modify.
                setting: Name of setting in self.settings to modify.
                value: One of 0, 1 or 2.
                    0: Set setting to False.
                    1: Set setting to True.
                    2: Set setting to value given in the commandline.
            """
            if options.contains(name):
                valuedict = {0: False, 1: True}
                if value == 2:
                    valuedict[2] = options.lookup_value(name).unpack()
                self.settings[section][setting] = valuedict[value]

        # If the version option is given, print version and exit 0
        if options.contains("version"):
            information = Information()
            print(information.get_version())
            return 0
        # If we start from desktop, move to the wanted directory
        # Else if the input does not come from a tty, e.g. find sth | vimiv, set
        # paths and index according to the input from the pipe
        if options.contains("start-from-desktop"):
            os.chdir(self.settings["LIBRARY"]["desktop_start_dir"])
        elif not sys.stdin.isatty():
            tty_paths = []
            for line in sys.stdin:
                tty_paths.append(line.rstrip("\n"))
            self.paths, self.index = populate(tty_paths)

        set_option("bar", "GENERAL", "display_bar", 1)
        set_option("no-bar", "GENERAL", "display_bar", 0)
        set_option("library", "LIBRARY", "show_library", 1)
        set_option("no-library", "LIBRARY", "show_library", 0)
        set_option("fullscreen", "GENERAL", "start_fullscreen", 1)
        set_option("no-fullscreen", "GENERAL", "start_fullscreen", 0)
        set_option("shuffle", "GENERAL", "shuffle", 1)
        set_option("no-shuffle", "GENERAL", "shuffle", 0)
        set_option("recursive", "GENERAL", "recursive", 1)
        set_option("no-recursive", "GENERAL", "recursive", 0)
        set_option("slideshow", "GENERAL", "start_slideshow", 1)
        set_option("slideshow-delay", "GENERAL", "slideshow_delay", 2)
        set_option("geometry", "GENERAL", "geometry", 2)
        return -1  # To continue

    def activate_vimiv(self, app):
        """Starting point for the vimiv application.

        Args:
            app: The application itself.
        """
        self.init_widgets()
        self.create_window_structure()
        app.add_window(self["window"])
        # Show everything and then hide whatever needs to be hidden
        self["window"].show_all()
        self["manipulate"].scrolled_win.hide()
        self["commandline"].grid.hide()
        # Statusbar depending on setting
        if self["statusbar"].hidden:
            self["statusbar"].bar.hide()
        # Try to generate imagelist recursively from the current directory if
        # recursive is given and not paths exist
        if self.settings["GENERAL"]["recursive"] and not self.paths:
            shuffle = self.settings["GENERAL"]["shuffle"]
            self.paths, self.index = populate([os.getcwd()], True, shuffle)
        # Show the image if an imagelist exists
        if self.paths:
            self["image"].move_index(True, False, 0)
            # Show library at the beginning?
            if not self["library"].show_at_start:
                self["library"].grid.hide()
            self["image"].scrolled_win.grab_focus()
            # Start in slideshow mode?
            if self["slideshow"].at_start:
                self["slideshow"].toggle()
        else:
            # Slideshow without paths makes no sense
            self["slideshow"].running = False
            self["library"].reload(os.getcwd())
            if self["library"].expand:
                self["image"].scrolled_win.hide()
            self["statusbar"].err_message(
                "No valid paths, opening library viewer")

    def init_widgets(self):
        """Create all the other widgets and add them to the class."""
        self["keyhandler"] = KeyHandler(self, self.settings)
        self["commandline"] = CommandLine(self, self.settings)
        self["tags"] = TagHandler(self)
        self["mark"] = Mark(self, self.settings)
        self["fileextras"] = FileExtras(self)
        self["statusbar"] = Statusbar(self, self.settings)
        self["completions"] = VimivComplete(self)
        self["slideshow"] = Slideshow(self, self.settings)
        self["image"] = Image(self, self.settings)
        self["library"] = Library(self, self.settings)
        self["thumbnail"] = Thumbnail(self, self.settings)
        self["manipulate"] = Manipulate(self, self.settings)
        self["information"] = Information()
        self["window"] = Window(self, self.settings)
        Commands(self, self.settings)

    def create_window_structure(self):
        """Generate the structure of all the widgets and add it to the window.

        There is a large Gtk.Grid() to organize the widgets packed into a
        Gtk.Overlay(). The commandline is added as overlay.
        """
        main_grid = Gtk.Grid()
        main_grid.attach(self["library"].grid, 0, 0, 1, 1)
        main_grid.attach(self["image"].scrolled_win, 1, 0, 1, 1)
        main_grid.attach(self["manipulate"].scrolled_win, 0, 1, 2, 1)
        main_grid.attach(self["statusbar"].bar, 0, 2, 2, 1)

        # Overlay contains grid mainly and adds commandline as floating
        overlay = Gtk.Overlay()
        overlay.add(main_grid)
        overlay.add_overlay(self["commandline"].grid)
        self["window"].add(overlay)

    def quit_wrapper(self, force=False):
        """Quit the applications, print marked files and save history.

        Args:
            force: If True quit even if an image was edited.
        """
        for image in self["mark"].marked:
            print(image)
        # Check if image has been edited
        if self["image"].check_for_edit(force):
            return
        # Save the history
        histfile = os.path.expanduser("~/.vimiv/history")
        histfile = open(histfile, 'w')
        for cmd in self["commandline"].history:
            cmd += "\n"
            histfile.write(cmd)
        histfile.close()
        # Call Gtk.Application.quit()
        self.quit()

    def get_pos(self, get_filename=False, force_widget=""):
        """Get the current position in the focused widget.

        get_filename: If True return filename instead of position.
        force_widget: String to force getting the position of a widget

        Return:
            Current position as number or filename.
        """
        # Find widget to work on
        if force_widget:
            focused_widget = force_widget
        elif self["image"].scrolled_win.is_focus():
            focused_widget = "im"
        elif self["library"].treeview.is_focus():
            focused_widget = "lib"
        elif self["thumbnail"].iconview.is_focus():
            focused_widget = "thu"

        # Get position and name
        if focused_widget != "im":
            if focused_widget == "lib":
                path = self["library"].treeview.get_cursor()[0]
                filelist = self["library"].files
            elif focused_widget == "thu":
                path = self["thumbnail"].iconview.get_cursor()[1]
                filelist = self.paths
            try:
                position = path.get_indices()[0]
            except:
                print("died")
                position = 0
                filelist = [""]
        else:
            filelist = self.paths
            position = self.index

        if get_filename:
            return filelist[position]
        else:
            return position

    def init_commandline_options(self):
        """Add all possible commandline options."""
        def add_option(name, short, help_str, flags=GLib.OptionFlags.NONE,
                       arg=GLib.OptionArg.NONE, value=None):
            """Add a single option.

            Args:
                name: Long name of the option, called via --name.
                short: Short name of the option, called via -s.
                help_str: Displayed help text when calling --help.
                flags: GLib options.
                arg: Type of the value to give after option.
                value: Name of the value to give after the option.
            """
            if short:
                short = ord(short)
            self.add_main_option(name, short, flags, arg, help_str, value)
        add_option("bar", "b", "Display statusbar")
        add_option("no-bar", "B", "Hide statusbar")
        add_option("library", "l", "Display library")
        add_option("no-library", "L", "Hide library")
        add_option("fullscreen", "f", "Start fullscreen")
        add_option("no-fullscreen", "F", "Do not start fullscreen")
        add_option("shuffle", "s", "Shuffle filelist")
        add_option("no-shuffle", "S", "Do not shuffle filelist")
        add_option("recursive", "r", "Search directory recursively for images")
        add_option("no-recursive", "R",
                   "Do not search directory recursively for images")
        add_option("version", "v", "Print version information and exit")
        add_option("slideshow", 0, "Start slideshow at startup")
        add_option("start-from-desktop", 0,
                   "Start using the desktop_start_dir as path")
        add_option("slideshow-delay", 0, "Set slideshow delay",
                   arg=GLib.OptionArg.DOUBLE, value="delay")
        add_option("geometry", "g", "Set the starting geometry",
                   arg=GLib.OptionArg.STRING, value="GEOMETRY")

    def __getitem__(self, name):
        """Convenience method to access widgets via self[name].

        Args:
            name: Name of the widget to access.
        Return:
            The widget if it exists. None else.
        """
        if name in self.widgets:
            return self.widgets[name]
        else:
            return None

    def __setitem__(self, name, widget):
        """Convenience method to access widgets via self[name].

        Args:
            name: Name of the widget to add.
            item: The actual widget to which name will refer.
        """
        self.widgets[name] = widget
<|endoftext|>


<commit_before>import numpy

from chainer import cuda
from chainer import function
from chainer.utils import array
from chainer.utils import type_check

class NormalizeL2(function.Function):

    """L2 normalization"""

    def __init__(self, eps=1e-5):
        self.eps = eps

    def check_type_forward(self, in_types):
        type_check.expect(in_types.size() == 1)
        x_type, = in_types

        type_check.expect(
            x_type.dtype == numpy.float32,
            x_type.ndim == 2,
        )

    def forward_cpu(self, inputs):
        x = array.as_mat(inputs[0])
        norm = numpy.linalg.norm(x, axis=1) + self.eps
        return x / norm[:, numpy.newaxis],

    def forward_gpu(self, inputs):
        x = array.as_mat(inputs[0])
        l2norm_kernel = cuda.cupy.ReductionKernel(
            'T x, float32 eps',
            'T y',
            'x * x',
            'a + b',
            'y = sqrt(a) + eps',
            '0',
            'l2norm'
        )
        norm = cuda.cupy.broadcast_to(
            l2norm_kernel(x, self.eps, axis=1).reshape(-1, 1),
            x.shape
        )

        return x / norm,

    def backward(self, inputs, gy):
        x = inputs[0]
        gy = gy[0]

        xp = cuda.get_array_module(x)

        if xp is numpy:
            norm = numpy.sqrt((x * x).sum(axis=1)) + self.eps
            norm = norm[:, numpy.newaxis]

            gx = gy * norm - (x * gy).sum(axis=1)[:, numpy.newaxis] * x / norm
            gx = gx / norm**2
        else:
            l2norm_kernel = cuda.cupy.ReductionKernel(
                'T x, float32 eps',
                'T y',
                'x * x',
                'a + b',
                'y = sqrt(a) + eps',
                '0',
                'l2norm'
            )
            norm = cuda.cupy.broadcast_to(
                l2norm_kernel(x, self.eps, axis=1).reshape(-1, 1),
                x.shape
            )
            x_gy = cuda.cupy.broadcast_to(
                (x * gy).sum(axis=1, keepdims=True),
                x.shape
            )
            gx = cuda.elementwise(
                'T gy, T x, T x_gy, T norm',
                'T gx',
                'gx = (gy * norm - x_gy * x / norm) / (norm * norm)',
                'l2_bwd')(gy, x, x_gy, norm)

        return gx,

def normalize(x, eps=1e-5):
    """L2 norm (a.k.a. Euclidean norm) squared.

    This function implements L2 normalization on a 1D vector. No reduction
    along batch axis is done.  Let :math:`x` be an input vector of dimension
    :math:`(N,D)`, where :math:`N` and :math:`K` denote mini-batchsize and the
    dimension of the input variable. Then, this function computes an output
    vector :math:`y` by following formula:

    .. math::
       y_i = {x_i \\over \\| x_i \\|_2}

    :math:`eps` is used to avoid division by zero when :math:`x_i=0`

    Args:
        x (~chainer.Variable): Two dimensional output variable. The first
            dimension is assumed to be the *minibatch dimension*.
        eps (float): Epsilon value for numerical stability.

    Returns:
        ~chainer.Variable: Two dimensional output variable.

    """
    return NormalizeL2(eps)(x)
<commit_msg>Fixes according to code review.<commit_after>import numpy

from chainer import cuda
from chainer import function
from chainer.utils import array
from chainer.utils import type_check

class NormalizeL2(function.Function):

    """L2 normalization"""

    def __init__(self, eps=1e-5):
        self.eps = eps

    def check_type_forward(self, in_types):
        type_check.expect(in_types.size() == 1)
        x_type, = in_types

        type_check.expect(
            x_type.dtype == numpy.float32,
            x_type.ndim == 2,
        )

    def forward_cpu(self, inputs):
        x = array.as_mat(inputs[0])
        norm = numpy.linalg.norm(x, axis=1) + self.eps
        return x / norm[:, numpy.newaxis],

    def forward_gpu(self, inputs):
        x = array.as_mat(inputs[0])
        l2norm_kernel = cuda.cupy.ReductionKernel(
            'T x, float32 eps',
            'T y',
            'x * x',
            'a + b',
            'y = sqrt(a) + eps',
            '0',
            'l2norm'
        )
        norm = cuda.cupy.broadcast_to(
            l2norm_kernel(x, self.eps, axis=1).reshape(-1, 1),
            x.shape
        )

        return x / norm,

    def backward(self, inputs, gy):
        x = inputs[0]
        gy = gy[0]

        xp = cuda.get_array_module(x)

        if xp is numpy:
            norm = numpy.linalg.norm(x, axis=1) + self.eps
            norm = norm[:, numpy.newaxis]

            gx = gy * norm - (x * gy).sum(axis=1)[:, numpy.newaxis] * x / norm
            gx = gx / norm**2
        else:
            l2norm_kernel = cuda.cupy.ReductionKernel(
                'T x, float32 eps',
                'T y',
                'x * x',
                'a + b',
                'y = sqrt(a) + eps',
                '0',
                'l2norm'
            )
            norm = cuda.cupy.broadcast_to(
                l2norm_kernel(x, self.eps, axis=1).reshape(-1, 1),
                x.shape
            )
            x_gy = cuda.cupy.broadcast_to(
                (x * gy).sum(axis=1, keepdims=True),
                x.shape
            )
            gx = cuda.elementwise(
                'T gy, T x, T x_gy, T norm',
                'T gx',
                'gx = (gy * norm - x_gy * x / norm) / (norm * norm)',
                'l2_bwd')(gy, x, x_gy, norm)

        return gx,

def normalize(x, eps=1e-5):
    """L2 norm (a.k.a. Euclidean norm) squared.

    This function implements L2 normalization on a 1D vector. No reduction
    along batch axis is done.  Let :math:`x` be an input vector of dimension
    :math:`(N, K)`, where :math:`N` and :math:`K` denote mini-batchsize and the
    dimension of the input variable. Then, this function computes an output
    vector :math:`y` by following formula:

    .. math::
       y_i = {x_i \\over \\| x_i \\|_2}

    :math:`eps` is used to avoid division by zero when :math:`x_i=0`

    Args:
        x (~chainer.Variable): Two dimensional output variable. The first
            dimension is assumed to be the *minibatch dimension*.
        eps (float): Epsilon value for numerical stability.

    Returns:
        ~chainer.Variable: Two dimensional output variable.

    """
    return NormalizeL2(eps)(x)
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import argparse
import re

def get_next_go(go_slim):
    read_file = True
    while read_file:
        line = go_slim.readline()
        if not line:
            read_file = False
        if line.startswith("[Term]"):
            read_file = False

    if not line:
        return None

    go = {}
    go["id"] = ""
    go["name"] = ""
    go["namespace"] = ""

    for i in range(3):
        line = go_slim.readline()
        if line.startswith("id:"):
            go["id"] = line[:-1].split(": ")[1]
        elif line.startswith("name:"):
            go["name"] = line[:-1].split(": ")[1]
        elif line.startswith("namespace:"):
            go["namespace"] = line[:-1].split(": ")[1]
        else:
            raise ValueError("wrong descriptor: " + line )
    return go

def extract_go_slim_annotations(args):
    go_annotations = {}
    with open(args.go_slim, "r") as go_slim:
        go = get_next_go(go_slim)
        while go != None:
            go_annotations.setdefault(go["id"],{})
            go_annotations[go["id"]]["name"] = go["name"]
            go_annotations[go["id"]]["namespace"] = go["namespace"]
            go = get_next_go(go_slim)
    return go_annotations

def format_humann2_output(args, go_annotations):
    with open(args.humann2_output, "r") as humann2_output:
        output_files = {}

        # Check if any tax IDs are present then set up the appropriate header extension
        tax_header = ''
        if any(re.match('.+\|g__.+\.s__.+', line) for line in humann2_output):
            tax_header = '\tGenus\tSpecies'

        output_files['molecular_function'] = open(args.molecular_function_output_file,"w")
        output_files['molecular_function'].write("GO id\tGO name\tAbundance" + tax_header + "\n")

        output_files['biological_process'] = open(args.biological_processes_output_file,"w")
        output_files['biological_process'].write("GO id\tGO name\tAbundance" + tax_header + "\n")

        output_files['cellular_component'] = open(args.cellular_component_output_file,"w")
        output_files['cellular_component'].write("GO id\tGO name\tAbundance" + tax_header + "\n")

        # Reset to beginning of file and skip header
        humann2_output.seek(0)
        next(humann2_output)

        for line in humann2_output:
            split_line = line[:-1].split('\t')
            go_id = split_line[0]
            abundance = split_line[1]

            genus = species = ''
            if '|' in go_id:
                go_id, extra_id = go_id.split('|')
                if re.match('g__.+\.s__.+', extra_id):
                    genus, species = re.match('g__(.+)\.s__(.+)', extra_id).groups()

            if go_id == "UNGROUPED" or go_id == "UNMAPPED":
                continue

            namespace = go_annotations[go_id]["namespace"]
            if not go_id in go_annotations:
                string = go_id + " has not found annotations"
                raise ValueError(string)

            output_files[namespace].write(go_id + '\t')
            output_files[namespace].write(go_annotations[go_id]["name"] + '\t')
            if tax_header == '':
                output_files[namespace].write(abundance + '\n')
            else:
                output_files[namespace].write(abundance + '\t')
                output_files[namespace].write(genus.replace('_',' ') + '\t')
                output_files[namespace].write(species.replace('_',' ') + '\n')

        output_files['molecular_function'].close()
        output_files['biological_process'].close()
        output_files['cellular_component'].close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--go_slim', required=True)
    parser.add_argument('--humann2_output', required=True)
    parser.add_argument('--molecular_function_output_file', required=True)
    parser.add_argument('--biological_processes_output_file', required=True)
    parser.add_argument('--cellular_component_output_file', required=True)
    args = parser.parse_args()

    go_annotations = extract_go_slim_annotations(args)
    format_humann2_output(args, go_annotations)<commit_msg>transfer |species.genus IDs to GO and namespace columns<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import argparse
import re

def get_next_go(go_slim):
    read_file = True
    while read_file:
        line = go_slim.readline()
        if not line:
            read_file = False
        if line.startswith("[Term]"):
            read_file = False

    if not line:
        return None

    go = {}
    go["id"] = ""
    go["name"] = ""
    go["namespace"] = ""

    for i in range(3):
        line = go_slim.readline()
        if line.startswith("id:"):
            go["id"] = line[:-1].split(": ")[1]
        elif line.startswith("name:"):
            go["name"] = line[:-1].split(": ")[1]
        elif line.startswith("namespace:"):
            go["namespace"] = line[:-1].split(": ")[1]
        else:
            raise ValueError("wrong descriptor: " + line )
    return go

def extract_go_slim_annotations(args):
    go_annotations = {}
    with open(args.go_slim, "r") as go_slim:
        go = get_next_go(go_slim)
        while go != None:
            go_annotations.setdefault(go["id"],{})
            go_annotations[go["id"]]["name"] = go["name"]
            go_annotations[go["id"]]["namespace"] = go["namespace"]
            go = get_next_go(go_slim)
    return go_annotations

def format_humann2_output(args, go_annotations):
    with open(args.humann2_output, "r") as humann2_output:
        output_files = {}

        output_files['molecular_function'] = open(args.molecular_function_output_file,"w")
        output_files['molecular_function'].write("GO id\tGO name\tAbundance\n")

        output_files['biological_process'] = open(args.biological_processes_output_file,"w")
        output_files['biological_process'].write("GO id\tGO name\tAbundance\n")

        output_files['cellular_component'] = open(args.cellular_component_output_file,"w")
        output_files['cellular_component'].write("GO id\tGO name\tAbundance\n")

        # skip header
        next(humann2_output)
        for line in humann2_output:
            split_line = line[:-1].split('\t')
            go_id = split_line[0]
            abundance = split_line[1]

            extra_id = ''
            if '|' in go_id:
                go_id, extra_id = go_id.split('|')
                extra_id = '|' + extra_id

            if go_id == "UNGROUPED" or go_id == "UNMAPPED":
                continue

            namespace = go_annotations[go_id]["namespace"]
            if not go_id in go_annotations:
                string = go_id + " has not found annotations"
                raise ValueError(string)

            output_files[namespace].write(go_id + extra_id + '\t')
            output_files[namespace].write(go_annotations[go_id]["name"] + extra_id + '\t')
            output_files[namespace].write(abundance + '\n')

        output_files['molecular_function'].close()
        output_files['biological_process'].close()
        output_files['cellular_component'].close()

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--go_slim', required=True)
    parser.add_argument('--humann2_output', required=True)
    parser.add_argument('--molecular_function_output_file', required=True)
    parser.add_argument('--biological_processes_output_file', required=True)
    parser.add_argument('--cellular_component_output_file', required=True)
    args = parser.parse_args()

    go_annotations = extract_go_slim_annotations(args)
    format_humann2_output(args, go_annotations)<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

# region Description
"""
examples.py: Raw-packet examples
Author: Vladimir Ivanov
License: MIT
Copyright 2019, Raw-packet Project
"""
# endregion

# region Import

# region Add project root path
from sys import path
from os.path import dirname, abspath
path.append(dirname(dirname(dirname(abspath(__file__)))))
# endregion

# region Raw-packet modules
from raw_packet.Utils.base import Base
from raw_packet.Utils.network import RawEthernet, RawARP, RawIPv4, RawIPv6, RawUDP, RawDNS
# endregion

# region Import libraries
from os.path import dirname, abspath
project_root_path = dirname(dirname(dirname(abspath(__file__))))
# endregion

# endregion

# region Authorship information
__author__ = 'Vladimir Ivanov'
__copyright__ = 'Copyright 2019, Raw-packet Project'
__credits__ = ['']
__license__ = 'MIT'
__version__ = '0.2.1'
__maintainer__ = 'Vladimir Ivanov'
__email__ = 'ivanov.vladimir.mail@gmail.com'
__status__ = 'Development'
# endregion

# region Main function
if __name__ == "__main__":

    # region Check user, platform and print banner
    Base = Base()
    Base.check_user()
    Base.check_platform()
    Base.print_banner()
    # endregion

    # region Init Raw-packet classes
    eth = RawEthernet()
    arp = RawARP()
    ipv4 = RawIPv4()
    ipv6 = RawIPv6()
    udp = RawUDP()
    dns = RawDNS()
    # endregion

    try:
        # region Base functions
        print('\n')
        Base.print_info('Network functions:')

        print('\nNetwork interface settings:')
        print(Base.get_interface_settings('eth0'))

        print('\nMac address:')
        print(Base.get_interface_mac_address('eth0', False))

        print('\nipv4 address:')
        print(Base.get_interface_ip_address('eth0', False))

        print('\nipv6 link local address:')
        print(Base.get_interface_ipv6_link_address('eth0', False))

        print('\nipv6 link local address by mac address:')
        print(Base.make_ipv6_link_address('12:34:56:78:90:ab'))

        print('\nipv6 link global address:')
        print(Base.get_interface_ipv6_glob_address('eth0'))

        print('\nipv6 global addresses:')
        print(Base.get_interface_ipv6_glob_addresses('eth0'))

        print('\nNetwork mask:')
        print(Base.get_interface_netmask('eth0', False))

        print('\nFirst ipv4:')
        print(Base.get_first_ip_on_interface('eth0', False))

        print('\nSecond ipv4:')
        print(Base.get_second_ip_on_interface('eth0', False))

        print('\nPenultimate ipv4:')
        print(Base.get_penultimate_ip_on_interface('eth0', False))

        print('\nLast ipv4:')
        print(Base.get_last_ip_on_interface('eth0', False))

        print('\nRandom ipv4:')
        print(Base.get_random_ip_on_interface('eth0', False))

        print('\nipv4 network:')
        print(Base.get_interface_network('eth0', False))

        print('\nipv4 broadcast:')
        print(Base.get_interface_broadcast('eth0', False))

        print('\nipv4 gateway:')
        print(Base.get_interface_ipv4_gateway('eth0', False))

        print('\nipv6 gateway:')
        print(Base.get_interface_ipv6_gateway('eth0', False))

        print('\n')
        Base.print_info('Software functions:')

        print('\nApt list installed software:')
        print(Base.apt_list_installed_packages())

        print('\nCheck installed software: apache2')
        print(Base.check_installed_software('apache2', False))

        print('\n')
        Base.print_info('Process functions:')

        print('\nProcess apache2 pid:')
        print(Base.get_process_pid('apache2'))

        print('\nProcess pid by listen port 80:')
        print(Base.get_process_pid_by_listen_port(80))
        # endregion

        # region RawEthernet functions
        print('\n')
        Base.print_info('Test network Ethernet functions:')

        print('\nConvert MAC address string to bytes:')
        print(eth.convert_mac('30:31:32:33:34:35', True))

        print('\nConvert bad MAC address string to bytes:')
        print(eth.convert_mac('01123:45:67:89:0a', False))

        print('\nConvert MAC address bytes to string:')
        print(eth.convert_mac(b'\x01#Eg\x89\n', True))

        print('\nConvert bad MAC address bytes to string:')
        print(eth.convert_mac(b'\x01#Eg\x89', False))

        print('\nGet MAC address prefix string:')
        print(eth.get_mac_prefix('ab:c3:45:67:89:0a', 3, True))

        print('\nGet MAC address prefix bytes:')
        print(eth.get_mac_prefix(b'\x01#Eg\x89\n', 3, True))

        print('\nMake Ethernet header:')
        print(eth.make_header('30:31:32:33:34:35', '36:37:38:39:40:41', 2048))

        print('\nMake Ethernet header bad input:')
        print(eth.make_header('01:23:45:67:89:0', '01:23:45:67:89:0a', 2048))

        print('\nParse Ethernet header:')
        print(eth.parse_header(b'6789@A012345\x08\x00'))
        # endregion

        # region RawARP functions
        print('\n')
        Base.print_info('Test network ARP functions:')

        print('\nMake ARP packet')
        print(arp.make_packet())

        print('\nMake ARP packet bad input')
        print(arp.make_packet('01:23:45:67:89:0a', '01:23:45:67:89:0b',
                              '01:23:45:67:89:0aa', '1111', '01:23:45:67:89:b', '2222'))

        print('\nParse ARP packet')
        print(arp.parse_packet(b'\x00\x01\x08\x00\x06\x04\x00\x01\x01#Eg\x89\n' +
                               b'\xc0\xa8\x01\x01\x01#Eg\x89\x0b\xc0\xa8\x01\x02'))

        print('\nMake ARP request')
        print(arp.make_request())

        print('\nParse ARP request')
        print(arp.parse_packet(b'\x00\x01\x08\x00\x06\x04\x00\x01\x01#Eg\x89\n' +
                               b'\xc0\xa8\x01\x01\x01#Eg\x89\x0b\xc0\xa8\x01\x02'))

        print('\nMake ARP response')
        print(arp.make_response())

        print('\nParse ARP response')
        print(arp.parse_packet(b'\x00\x01\x08\x00\x06\x04\x00\x02\x01#Eg\x89\n' +
                               b'\xc0\xa8\x01\x01\x01#Eg\x89\x0b\xc0\xa8\x01\x02'))
        # endregion

        # region RawIPv4 functions
        print('\n')
        Base.print_info('Test network IPv4 functions:')

        print('\nGet random IPv4 address:')
        print(ipv4.make_random_ip())

        print('\nMake IPv4 header:')
        print(ipv4.make_header('192.168.1.1', '192.168.1.2', 1, 0, 8, 17, 64))

        print('\nMake IPv4 header bad input:')
        print(ipv4.make_header('1234', '1234', 65537))

        print('\nParse IPv4 header:')
        print(ipv4.parse_header(b'E\x00\x00\x1c\x8d/\x00\x00@\x11jN\xc0\xa8\x01\x01\xc0\xa8\x01\x02'))

        print('\nParse IPv4 header bad input:')
        print(ipv4.parse_header(b'\x61\x00\x00\x1c\x8d/\x00\x00@\x11jN\xc0\xa8\x01\x01\xc0\xa8\x01\x02'))
        # endregion

        # region RawIPv6 functions
        print('\n')
        Base.print_info('Test network ipv6 functions:')

        print('\nGet random ipv6 address:')
        print(ipv6.make_random_ip())

        print('\nPack ipv6 address:')
        print(ipv6.pack_addr('3132:3334::1'))

        print('\nPack ipv6 address bad input:')
        print(ipv6.pack_addr('fd12:::1', False))

        print('\nMake ipv6 header:')
        print(ipv6.make_header())

        print('\nMake ipv6 header bad input:')
        print(ipv6.make_header('fd00:::1', 'fd00:2', 1, 1, 1, 1))

        print('\nParse ipv6 header:')
        print(ipv6.parse_header(b'`\x00\x00\x00\x00\x08\x11@\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +
                                b'\x00\x01\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02'))
        # endregion

        # region RawUDP functions
        print('\n')
        Base.print_info('Test network UDP functions:')

        print('\nMake UDP header:')
        print(udp.make_header())

        print('\nMake UDP header bad input:')
        print(udp.make_header(123123, 123123))

        print('\nMake UDP header with checksum for ipv6:')
        print(udp.make_header_with_ipv6_checksum())

        print('\nMake UDP header with checksum for ipv6 bad input:')
        print(udp.make_header_with_ipv6_checksum('fd00:::1', 'fd00:2'))

        print('\nParse UDP header')
        print(udp.parse_header(b'\x14\xe9\x14\xe9\x00\x08\xdc\x07'))
        # endregion

        # region RawDNS functions
        print('\n')
        Base.print_info('Test network DNS functions:')

        print('\nMake DNS name:')
        print(dns.make_dns_name())

        print('\nMake IPv4 DNS request packet:')
        print(dns.make_ipv4_request_packet(src_mac='01:23:45:67:89:0a', dst_mac='01:23:45:67:89:0b',
                                           src_ip='192.168.1.1', dst_ip='192.168.1.2', ip_ident=1,
                                           src_port=5353, dst_port=53, transaction_id=1,
                                           queries=[{'type': 1, 'class': 1, 'name': 'test.com'}],
                                           flags=0))

        print('\nMake IPv6 DNS request packet:')
        print(dns.make_ipv6_request_packet(src_mac='01:23:45:67:89:0a', dst_mac='01:23:45:67:89:0b',
                                           src_ip='fd00::1', dst_ip='fd00::2', ip_ttl=64,
                                           src_port=5353, dst_port=53, transaction_id=1,
                                           queries=[{'type': 1, 'class': 1, 'name': 'test.com'}],
                                           flags=0))

        print('\nMake DNS response packet:')
        print(dns.make_response_packet(src_mac='01:23:45:67:89:0a', dst_mac='01:23:45:67:89:0b',
                                       src_ip='192.168.1.1', dst_ip='192.168.1.2', ip_ttl=64, ip_ident=1,
                                       src_port=53, dst_port=5353, transaction_id=1, flags=0,
                                       queries=[{'type': 1, 'class': 1, 'name': 'test.com'}],
                                       answers_address=[{'name': 'test.com', 'type': 1, 'class': 1, 'ttl': 65535,
                                                         'address': '192.168.1.1'}], name_servers={},
                                       exit_on_failure=True))
        # endregion

    except KeyboardInterrupt:
        Base.print_info("Exit")
        exit(0)

# endregion
<commit_msg>Update RawDNS functions<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

# region Description
"""
examples.py: Raw-packet examples
Author: Vladimir Ivanov
License: MIT
Copyright 2019, Raw-packet Project
"""
# endregion

# region Import

# region Add project root path
from sys import path
from os.path import dirname, abspath
path.append(dirname(dirname(dirname(abspath(__file__)))))
# endregion

# region Raw-packet modules
from raw_packet.Utils.base import Base
from raw_packet.Utils.network import RawEthernet, RawARP, RawIPv4, RawIPv6, RawUDP, RawDNS
# endregion

# region Import libraries
from os.path import dirname, abspath
project_root_path = dirname(dirname(dirname(abspath(__file__))))
# endregion

# endregion

# region Authorship information
__author__ = 'Vladimir Ivanov'
__copyright__ = 'Copyright 2019, Raw-packet Project'
__credits__ = ['']
__license__ = 'MIT'
__version__ = '0.2.1'
__maintainer__ = 'Vladimir Ivanov'
__email__ = 'ivanov.vladimir.mail@gmail.com'
__status__ = 'Development'
# endregion

# region Main function
if __name__ == "__main__":

    # region Check user, platform and print banner
    Base = Base()
    Base.check_user()
    Base.check_platform()
    Base.print_banner()
    # endregion

    # region Init Raw-packet classes
    eth = RawEthernet()
    arp = RawARP()
    ipv4 = RawIPv4()
    ipv6 = RawIPv6()
    udp = RawUDP()
    dns = RawDNS()
    # endregion

    try:
        # region Base functions
        print('\n')
        Base.print_info('Network functions:')

        print('\nNetwork interface settings:')
        print(Base.get_interface_settings('eth0'))

        print('\nMac address:')
        print(Base.get_interface_mac_address('eth0', False))

        print('\nipv4 address:')
        print(Base.get_interface_ip_address('eth0', False))

        print('\nipv6 link local address:')
        print(Base.get_interface_ipv6_link_address('eth0', False))

        print('\nipv6 link local address by mac address:')
        print(Base.make_ipv6_link_address('12:34:56:78:90:ab'))

        print('\nipv6 link global address:')
        print(Base.get_interface_ipv6_glob_address('eth0'))

        print('\nipv6 global addresses:')
        print(Base.get_interface_ipv6_glob_addresses('eth0'))

        print('\nNetwork mask:')
        print(Base.get_interface_netmask('eth0', False))

        print('\nFirst ipv4:')
        print(Base.get_first_ip_on_interface('eth0', False))

        print('\nSecond ipv4:')
        print(Base.get_second_ip_on_interface('eth0', False))

        print('\nPenultimate ipv4:')
        print(Base.get_penultimate_ip_on_interface('eth0', False))

        print('\nLast ipv4:')
        print(Base.get_last_ip_on_interface('eth0', False))

        print('\nRandom ipv4:')
        print(Base.get_random_ip_on_interface('eth0', False))

        print('\nipv4 network:')
        print(Base.get_interface_network('eth0', False))

        print('\nipv4 broadcast:')
        print(Base.get_interface_broadcast('eth0', False))

        print('\nipv4 gateway:')
        print(Base.get_interface_ipv4_gateway('eth0', False))

        print('\nipv6 gateway:')
        print(Base.get_interface_ipv6_gateway('eth0', False))

        print('\n')
        Base.print_info('Software functions:')

        print('\nApt list installed software:')
        print(Base.apt_list_installed_packages())

        print('\nCheck installed software: apache2')
        print(Base.check_installed_software('apache2', False))

        print('\n')
        Base.print_info('Process functions:')

        print('\nProcess apache2 pid:')
        print(Base.get_process_pid('apache2'))

        print('\nProcess pid by listen port 80:')
        print(Base.get_process_pid_by_listen_port(80))
        # endregion

        # region RawEthernet functions
        print('\n')
        Base.print_info('Test network Ethernet functions:')

        print('\nConvert MAC address string to bytes:')
        print(eth.convert_mac('30:31:32:33:34:35', True))

        print('\nConvert bad MAC address string to bytes:')
        print(eth.convert_mac('01123:45:67:89:0a', False))

        print('\nConvert MAC address bytes to string:')
        print(eth.convert_mac(b'\x01#Eg\x89\n', True))

        print('\nConvert bad MAC address bytes to string:')
        print(eth.convert_mac(b'\x01#Eg\x89', False))

        print('\nGet MAC address prefix string:')
        print(eth.get_mac_prefix('ab:c3:45:67:89:0a', 3, True))

        print('\nGet MAC address prefix bytes:')
        print(eth.get_mac_prefix(b'\x01#Eg\x89\n', 3, True))

        print('\nMake Ethernet header:')
        print(eth.make_header('30:31:32:33:34:35', '36:37:38:39:40:41', 2048))

        print('\nMake Ethernet header bad input:')
        print(eth.make_header('01:23:45:67:89:0', '01:23:45:67:89:0a', 2048))

        print('\nParse Ethernet header:')
        print(eth.parse_header(b'6789@A012345\x08\x00'))
        # endregion

        # region RawARP functions
        print('\n')
        Base.print_info('Test network ARP functions:')

        print('\nMake ARP packet')
        print(arp.make_packet())

        print('\nMake ARP packet bad input')
        print(arp.make_packet('01:23:45:67:89:0a', '01:23:45:67:89:0b',
                              '01:23:45:67:89:0aa', '1111', '01:23:45:67:89:b', '2222'))

        print('\nParse ARP packet')
        print(arp.parse_packet(b'\x00\x01\x08\x00\x06\x04\x00\x01\x01#Eg\x89\n' +
                               b'\xc0\xa8\x01\x01\x01#Eg\x89\x0b\xc0\xa8\x01\x02'))

        print('\nMake ARP request')
        print(arp.make_request())

        print('\nParse ARP request')
        print(arp.parse_packet(b'\x00\x01\x08\x00\x06\x04\x00\x01\x01#Eg\x89\n' +
                               b'\xc0\xa8\x01\x01\x01#Eg\x89\x0b\xc0\xa8\x01\x02'))

        print('\nMake ARP response')
        print(arp.make_response())

        print('\nParse ARP response')
        print(arp.parse_packet(b'\x00\x01\x08\x00\x06\x04\x00\x02\x01#Eg\x89\n' +
                               b'\xc0\xa8\x01\x01\x01#Eg\x89\x0b\xc0\xa8\x01\x02'))
        # endregion

        # region RawIPv4 functions
        print('\n')
        Base.print_info('Test network IPv4 functions:')

        print('\nGet random IPv4 address:')
        print(ipv4.make_random_ip())

        print('\nMake IPv4 header:')
        print(ipv4.make_header('192.168.1.1', '192.168.1.2', 1, 0, 8, 17, 64))

        print('\nMake IPv4 header bad input:')
        print(ipv4.make_header('1234', '1234', 65537))

        print('\nParse IPv4 header:')
        print(ipv4.parse_header(b'E\x00\x00\x1c\x8d/\x00\x00@\x11jN\xc0\xa8\x01\x01\xc0\xa8\x01\x02'))

        print('\nParse IPv4 header bad input:')
        print(ipv4.parse_header(b'\x61\x00\x00\x1c\x8d/\x00\x00@\x11jN\xc0\xa8\x01\x01\xc0\xa8\x01\x02'))
        # endregion

        # region RawIPv6 functions
        print('\n')
        Base.print_info('Test network ipv6 functions:')

        print('\nGet random ipv6 address:')
        print(ipv6.make_random_ip())

        print('\nPack ipv6 address:')
        print(ipv6.pack_addr('3132:3334::1'))

        print('\nPack ipv6 address bad input:')
        print(ipv6.pack_addr('fd12:::1', False))

        print('\nMake ipv6 header:')
        print(ipv6.make_header())

        print('\nMake ipv6 header bad input:')
        print(ipv6.make_header('fd00:::1', 'fd00:2', 1, 1, 1, 1))

        print('\nParse ipv6 header:')
        print(ipv6.parse_header(b'`\x00\x00\x00\x00\x08\x11@\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +
                                b'\x00\x01\xfd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02'))
        # endregion

        # region RawUDP functions
        print('\n')
        Base.print_info('Test network UDP functions:')

        print('\nMake UDP header:')
        print(udp.make_header())

        print('\nMake UDP header bad input:')
        print(udp.make_header(123123, 123123))

        print('\nMake UDP header with checksum for ipv6:')
        print(udp.make_header_with_ipv6_checksum())

        print('\nMake UDP header with checksum for ipv6 bad input:')
        print(udp.make_header_with_ipv6_checksum('fd00:::1', 'fd00:2'))

        print('\nParse UDP header')
        print(udp.parse_header(b'\x14\xe9\x14\xe9\x00\x08\xdc\x07'))
        # endregion

        # region RawDNS functions
        print('\n')
        Base.print_info('Test network DNS functions:')

        print('\nMake DNS name:')
        print(dns.make_dns_name())

        print('\nMake IPv4 DNS request packet:')
        print(dns.make_ipv4_request_packet(src_mac='01:23:45:67:89:0a', dst_mac='01:23:45:67:89:0b',
                                           src_ip='192.168.1.1', dst_ip='192.168.1.2', ip_ident=1,
                                           src_port=5353, dst_port=53, transaction_id=1,
                                           queries=[{'type': 1, 'class': 1, 'name': 'test.com'}],
                                           flags=0))

        print('\nMake IPv6 DNS request packet:')
        print(dns.make_ipv6_request_packet(src_mac='01:23:45:67:89:0a', dst_mac='01:23:45:67:89:0b',
                                           src_ip='fd00::1', dst_ip='fd00::2', ip_ttl=64,
                                           src_port=5353, dst_port=53, transaction_id=1,
                                           queries=[{'type': 1, 'class': 1, 'name': 'test.com'}],
                                           flags=0))

        print('\nMake IPv4 DNS response packet:')
        print(dns.make_response_packet(src_mac='01:23:45:67:89:0a', dst_mac='01:23:45:67:89:0b',
                                       src_ip='192.168.1.1', dst_ip='192.168.1.2', ip_ttl=64, ip_ident=1,
                                       src_port=53, dst_port=5353, transaction_id=1, flags=0,
                                       queries=[{'type': 1, 'class': 1, 'name': 'test.com'}],
                                       answers_address=[{'name': 'test.com', 'type': 1, 'class': 1, 'ttl': 65535,
                                                         'address': '192.168.1.1'}], name_servers={},
                                       exit_on_failure=True))

        print('\nMake IPv6 DNS response packet:')
        print(dns.make_response_packet(src_mac='01:23:45:67:89:0a', dst_mac='01:23:45:67:89:0b',
                                       src_ip='fd00::1', dst_ip='fd00::2', ip_ttl=64, ip_ident=1,
                                       src_port=53, dst_port=5353, transaction_id=1, flags=0,
                                       queries=[{'type': 1, 'class': 1, 'name': 'test.com'}],
                                       answers_address=[{'name': 'test.com', 'type': 28, 'class': 1, 'ttl': 65535,
                                                         'address': 'fd00::1'}], name_servers={},
                                       exit_on_failure=True))

        print('\nParse IPv4 DNS packet:')
        print(dns.parse_packet(
            b'\x00\x01\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04test\x03com\x00\x00\x01\x00\x01\x04test\x03com\x00' +
            b'\x00\x01\x00\x01\x00\x00\xff\xff\x00\x04\xc0\xa8\x01\x01'))
        # endregion

    except KeyboardInterrupt:
        Base.print_info("Exit")
        exit(0)

# endregion
<|endoftext|>


<commit_before>import json
from corehq import Domain
from corehq.apps.accounting.models import Feature, SoftwareProduct
from corehq.apps.accounting.utils import fmt_feature_rate_dict, fmt_product_rate_dict, LazyEncoder
from corehq.apps.hqwebapp.async_handler import BaseAsyncHandler, AsyncHandlerError
from corehq.apps.users.models import WebUser

class BaseRateAsyncHandler(BaseAsyncHandler):
    """
    Subclass this for interacting with RatesManager.
    """
    allowed_actions = [
        'apply',
        'create',
    ]

    @property
    def name(self):
        return self.data.get('name')

    @property
    def rate_type(self):
        return self.data.get('rate_type')

    @property
    def rate_id(self):
        return self.data.get('rate_id')

    @property
    def create_response(self):
        raise NotImplementedError("create_response is required")

    @property
    def apply_response(self):
        raise NotImplementedError("apply_response is required")

class FeatureRateAsyncHandler(BaseRateAsyncHandler):
    slug = 'features_handler'

    @property
    def create_response(self):
        new_feature, is_new = Feature.objects.get_or_create(
            name=self.name,
            feature_type=self.rate_type,
        )
        if not is_new:
            raise AsyncHandlerError("Feature '%s' already exists, and likely already "
                                    "in this Software Plan Version." % new_feature.name)
        return fmt_feature_rate_dict(new_feature)

    @property
    def apply_response(self):
        try:
            feature = Feature.objects.get(id=self.rate_id)
            return fmt_feature_rate_dict(feature)
        except Feature.DoesNotExist:
            raise AsyncHandlerError("could not find an existing feature")

class SoftwareProductRateAsyncHandler(BaseRateAsyncHandler):
    slug = 'products_handler'

    @property
    def create_response(self):
        new_product, is_new = SoftwareProduct.objects.get_or_create(
            name=self.name,
            product_type=self.rate_type
        )
        if not is_new:
            raise AsyncHandlerError("Product '%s' already exists, and likely already "
                                    "in this Software Plan Version." % new_product.name)
        return fmt_product_rate_dict(new_product)

    @property
    def apply_response(self):
        try:
            product = SoftwareProduct.objects.get(id=self.rate_id)
            return fmt_product_rate_dict(product)
        except SoftwareProduct.DoesNotExist:
            raise AsyncHandlerError("could not find an existing product")

class BaseSelect2AsyncHandler(BaseAsyncHandler):
    @property
    def search_string(self):
        return self.data.get('searchString')

    @property
    def existing(self):
        return self.data.getlist('existing[]')

    def _fmt_success(self, response):
        success = json.dumps({
            'results': [{
                'id': r[0],
                'text': r[1],
            } for r in response]
        }, cls=LazyEncoder)
        return success

class Select2RateAsyncHandler(BaseSelect2AsyncHandler):
    """
    Handles the async responses for the select2 widget in the Features & Rates portion
    of the SoftwarePlanVersion form.
    """
    slug = 'select2_rate'
    allowed_actions = [
        'feature_id',
        'product_id',
    ]

    @property
    def feature_id_response(self):
        features = Feature.objects
        if self.existing:
            features = features.exclude(name__in=self.existing)
        if self.search_string:
            features = features.filter(name__startswith=self.search_string)
        return [(f.id, f.name, f.feature_type) for f in features.all()]

    @property
    def product_id_response(self):
        products = SoftwareProduct.objects
        if self.existing:
            products = products.exclude(name__in=self.existing)
        if self.search_string:
            products = products.filter(name__startswith=self.search_string)
        return [(p.id, p.name, p.product_type) for p in products.all()]

    def _fmt_success(self, response):
        return json.dumps({
            'results': [
            {
                'id': r[0],
                'name': r[1],
                'rate_type': r[2],
                'text': '%s (%s)' % (r[1], r[2]),
                'isExisting': True,
            } for r in response]
        })

class Select2BillingInfoHandler(BaseSelect2AsyncHandler):
    slug = 'select2_billing'
    allowed_actions = [
        'country',
        'billing_admins',
    ]

    @property
    def country_response(self):
        from django_countries.countries import COUNTRIES
        if self.search_string:
            return filter(lambda x: x[1].lower().startswith(self.search_string.lower()), COUNTRIES)
        return COUNTRIES

    @property
    def billing_admins_response(self):
        all_web_users = WebUser.by_domain(domain=self.request.domain)
        admins = filter(lambda x: x.is_domain_admin and x.username != self.request.couch_user.username,
                        all_web_users)
        admins = filter(lambda x: x.username not in self.existing, admins)
        return [(a.username, "%s (%s)" % (a.full_name, a.username)) for a in admins]

class Select2SubscriptionInfoHandler(BaseSelect2AsyncHandler):
    slug = 'select2_billing'
    allowed_actions = [
        'domain'
    ]

    @property
    def domain_response(self):
        domain_names = [domain['key'] for domain in Domain.get_all(include_docs=False)]
        if self.search_string:
            domain_names = filter(lambda x: x.lower().startswith(self.search_string.lower()), domain_names)
        return [(name, name) for name in domain_names]
<commit_msg>prevent internal error from creating a feature/product with an existing name but different type<commit_after>import json
from corehq import Domain
from corehq.apps.accounting.models import Feature, SoftwareProduct
from corehq.apps.accounting.utils import fmt_feature_rate_dict, fmt_product_rate_dict, LazyEncoder
from corehq.apps.hqwebapp.async_handler import BaseAsyncHandler, AsyncHandlerError
from corehq.apps.users.models import WebUser

class BaseRateAsyncHandler(BaseAsyncHandler):
    """
    Subclass this for interacting with RatesManager.
    """
    allowed_actions = [
        'apply',
        'create',
    ]

    @property
    def name(self):
        return self.data.get('name')

    @property
    def rate_type(self):
        return self.data.get('rate_type')

    @property
    def rate_id(self):
        return self.data.get('rate_id')

    @property
    def create_response(self):
        raise NotImplementedError("create_response is required")

    @property
    def apply_response(self):
        raise NotImplementedError("apply_response is required")

class FeatureRateAsyncHandler(BaseRateAsyncHandler):
    slug = 'features_handler'

    @property
    def create_response(self):
        if len(Feature.objects.filter(name=self.name)) > 0:
            raise AsyncHandlerError("Feature '%s' already exists, and likely already "
                                    "in this Software Plan Version." % self.name)
        new_feature, _ = Feature.objects.get_or_create(
            name=self.name,
            feature_type=self.rate_type,
        )
        return fmt_feature_rate_dict(new_feature)

    @property
    def apply_response(self):
        try:
            feature = Feature.objects.get(id=self.rate_id)
            return fmt_feature_rate_dict(feature)
        except Feature.DoesNotExist:
            raise AsyncHandlerError("could not find an existing feature")

class SoftwareProductRateAsyncHandler(BaseRateAsyncHandler):
    slug = 'products_handler'

    @property
    def create_response(self):
        if len(SoftwareProduct.objects.filter(name=self.name)) > 0:
            raise AsyncHandlerError("Product '%s' already exists, and likely already "
                                    "in this Software Plan Version." % self.name)
        new_product, _ = SoftwareProduct.objects.get_or_create(
            name=self.name,
            product_type=self.rate_type
        )
        return fmt_product_rate_dict(new_product)

    @property
    def apply_response(self):
        try:
            product = SoftwareProduct.objects.get(id=self.rate_id)
            return fmt_product_rate_dict(product)
        except SoftwareProduct.DoesNotExist:
            raise AsyncHandlerError("could not find an existing product")

class BaseSelect2AsyncHandler(BaseAsyncHandler):
    @property
    def search_string(self):
        return self.data.get('searchString')

    @property
    def existing(self):
        return self.data.getlist('existing[]')

    def _fmt_success(self, response):
        success = json.dumps({
            'results': [{
                'id': r[0],
                'text': r[1],
            } for r in response]
        }, cls=LazyEncoder)
        return success

class Select2RateAsyncHandler(BaseSelect2AsyncHandler):
    """
    Handles the async responses for the select2 widget in the Features & Rates portion
    of the SoftwarePlanVersion form.
    """
    slug = 'select2_rate'
    allowed_actions = [
        'feature_id',
        'product_id',
    ]

    @property
    def feature_id_response(self):
        features = Feature.objects
        if self.existing:
            features = features.exclude(name__in=self.existing)
        if self.search_string:
            features = features.filter(name__startswith=self.search_string)
        return [(f.id, f.name, f.feature_type) for f in features.all()]

    @property
    def product_id_response(self):
        products = SoftwareProduct.objects
        if self.existing:
            products = products.exclude(name__in=self.existing)
        if self.search_string:
            products = products.filter(name__startswith=self.search_string)
        return [(p.id, p.name, p.product_type) for p in products.all()]

    def _fmt_success(self, response):
        return json.dumps({
            'results': [
            {
                'id': r[0],
                'name': r[1],
                'rate_type': r[2],
                'text': '%s (%s)' % (r[1], r[2]),
                'isExisting': True,
            } for r in response]
        })

class Select2BillingInfoHandler(BaseSelect2AsyncHandler):
    slug = 'select2_billing'
    allowed_actions = [
        'country',
        'billing_admins',
    ]

    @property
    def country_response(self):
        from django_countries.countries import COUNTRIES
        if self.search_string:
            return filter(lambda x: x[1].lower().startswith(self.search_string.lower()), COUNTRIES)
        return COUNTRIES

    @property
    def billing_admins_response(self):
        all_web_users = WebUser.by_domain(domain=self.request.domain)
        admins = filter(lambda x: x.is_domain_admin and x.username != self.request.couch_user.username,
                        all_web_users)
        admins = filter(lambda x: x.username not in self.existing, admins)
        return [(a.username, "%s (%s)" % (a.full_name, a.username)) for a in admins]

class Select2SubscriptionInfoHandler(BaseSelect2AsyncHandler):
    slug = 'select2_billing'
    allowed_actions = [
        'domain'
    ]

    @property
    def domain_response(self):
        domain_names = [domain['key'] for domain in Domain.get_all(include_docs=False)]
        if self.search_string:
            domain_names = filter(lambda x: x.lower().startswith(self.search_string.lower()), domain_names)
        return [(name, name) for name in domain_names]
<|endoftext|>