<commit_before># This code is part of Qiskit.
#
# (C) Copyright IBM 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Gate equivalence library."""

import io
from collections import namedtuple

import retworkx as rx

from .exceptions import CircuitError
from .parameterexpression import ParameterExpression

try:
    import pydot  # pylint: disable=unused-import
    HAS_PYDOT = True
except ImportError:
    HAS_PYDOT = False
try:
    from PIL import Image
    HAS_PIL = True
except ImportError:
    HAS_PIL = False

Key = namedtuple('Key', ['name',
                         'num_qubits'])

Entry = namedtuple('Entry', ['search_base',
                             'equivalences'])

Equivalence = namedtuple('Equivalence', ['params',  # Ordered to match Gate.params
                                         'circuit'])

class EquivalenceLibrary():
    """A library providing a one-way mapping of Gates to their equivalent
    implementations as QuantumCircuits."""

    def __init__(self, *, base=None):
        """Create a new equivalence library.

        Args:
            base (Optional[EquivalenceLibrary]):  Base equivalence library to
                will be referenced if an entry is not found in this library.
        """
        self._base = base

        self._map = {}

    def add_equivalence(self, gate, equivalent_circuit):
        """Add a new equivalence to the library. Future queries for the Gate
        will include the given circuit, in addition to all existing equivalences
        (including those from base).

        Parameterized Gates (those including `qiskit.circuit.Parameters` in their
        `Gate.params`) can be marked equivalent to parameterized circuits,
        provided the parameters match.

        Args:
            gate (Gate): A Gate instance.
            equivalent_circuit (QuantumCircuit): A circuit equivalently
                implementing the given Gate.
        """

        _raise_if_shape_mismatch(gate, equivalent_circuit)
        _raise_if_param_mismatch(gate.params, equivalent_circuit.parameters)

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        equiv = Equivalence(params=gate.params.copy(),
                            circuit=equivalent_circuit.copy())

        if key not in self._map:
            self._map[key] = Entry(search_base=True, equivalences=[])

        self._map[key].equivalences.append(equiv)

    def has_entry(self, gate):
        """Check if a library contains any decompositions for gate.

        Args:
            gate (Gate): A Gate instance.

        Returns:
            Bool: True if gate has a known decomposition in the library.
                False otherwise.
        """

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        return (key in self._map or
                (self._base.has_entry(gate) if self._base is not None else False))

    def set_entry(self, gate, entry):
        """Set the equivalence record for a Gate. Future queries for the Gate
        will return only the circuits provided.

        Parameterized Gates (those including `qiskit.circuit.Parameters` in their
        `Gate.params`) can be marked equivalent to parameterized circuits,
        provided the parameters match.

        Args:
            gate (Gate): A Gate instance.
            entry (List['QuantumCircuit']) : A list of QuantumCircuits, each
                equivalently implementing the given Gate.
        """

        for equiv in entry:
            _raise_if_shape_mismatch(gate, equiv)
            _raise_if_param_mismatch(gate.params, equiv.parameters)

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        equivs = [Equivalence(params=gate.params.copy(),
                              circuit=equiv.copy())
                  for equiv in entry]

        self._map[key] = Entry(search_base=False,
                               equivalences=equivs)

    def get_entry(self, gate):
        """Gets the set of QuantumCircuits circuits from the library which
        equivalently implement the given Gate.

        Parameterized circuits will have their parameters replaced with the
        corresponding entries from Gate.params.

        Args:
            gate (Gate) - Gate: A Gate instance.

        Returns:
            List[QuantumCircuit]: A list of equivalent QuantumCircuits. If empty,
                library contains no known decompositions of Gate.

                Returned circuits will be ordered according to their insertion in
                the library, from earliest to latest, from top to base. The
                ordering of the StandardEquivalenceLibrary will not generally be
                consistent across Qiskit versions.
        """

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        query_params = gate.params

        return [_rebind_equiv(equiv, query_params)
                for equiv in self._get_equivalences(key)]

    def draw(self, filename=None):
        """Draws the equivalence relations available in the library.

        Args:
            filename (str): An optional path to write the output image to
                if specified this method will return None.

        Returns:
            PIL.Image: Drawn equivalence library.

        Raises:
            ImportError: when pydot or pillow are not installed.
        """
        if not HAS_PYDOT:
            raise ImportError('EquivalenceLibrary.draw requires pydot. '
                              "You can use 'pip install pydot' to install")
        if not HAS_PIL and not filename:
            raise ImportError('EquivalenceLibrary.draw requires pillow. '
                              "You can use 'pip install pillow' to install")

        dot_str = self._build_basis_graph().to_dot(
            lambda node: {'label': node['label']}, lambda edge: edge)
        dot = pydot.graph_from_dot_data(dot_str)[0]
        if filename:
            extension = filename.split('.')[-1]
            dot.write(filename, format=extension)
            return None
        png = dot.create_png(prog='dot')
        return Image.open(io.BytesIO(png))

    def _build_basis_graph(self):
        graph = rx.PyDiGraph()

        node_map = {}
        for key in self._get_all_keys():
            name, num_qubits = key
            equivalences = self._get_equivalences(key)

            basis = frozenset(['{}/{}'.format(name, num_qubits)])
            for params, decomp in equivalences:
                decomp_basis = frozenset('{}/{}'.format(name, num_qubits)
                                         for name, num_qubits in
                                         {(inst.name, inst.num_qubits)
                                          for inst, _, __ in decomp.data})
                if basis not in node_map:
                    basis_node = graph.add_node({'basis': basis,
                                                 'label': str(set(basis))})
                    node_map[basis] = basis_node
                if decomp_basis not in node_map:
                    decomp_basis_node = graph.add_node({'basis': decomp_basis,
                                                        'label': str(set(decomp_basis))})
                    node_map[decomp_basis] = decomp_basis_node

                label = "%s\n%s" % (
                    str(params), str(decomp) if num_qubits <= 5 else '...')
                graph.add_edge(node_map[basis],
                               node_map[decomp_basis],
                               dict(label=label, fontname='Courier', fontsize=str(8)))

        return graph

    def _get_all_keys(self):
        base_keys = self._base._get_all_keys() if self._base is not None else set()

        self_keys = set(self._map.keys())

        return self_keys | {base_key
                            for base_key in base_keys
                            if base_key not in self._map
                            or self._map[base_key].search_base}

    def _get_equivalences(self, key):
        search_base, equivalences = self._map.get(key, (True, []))

        if search_base and self._base is not None:
            return equivalences + self._base._get_equivalences(key)
        return equivalences

def _raise_if_param_mismatch(gate_params, circuit_parameters):
    gate_parameters = [p for p in gate_params
                       if isinstance(p, ParameterExpression)]

    if set(gate_parameters) != circuit_parameters:
        raise CircuitError('Cannot add equivalence between circuit and gate '
                           'of different parameters. Gate params: {}. '
                           'Circuit params: {}.'.format(
                               gate_parameters,
                               circuit_parameters))

def _raise_if_shape_mismatch(gate, circuit):
    if (gate.num_qubits != circuit.num_qubits
            or gate.num_clbits != circuit.num_clbits):
        raise CircuitError('Cannot add equivalence between circuit and gate '
                           'of different shapes. Gate: {} qubits and {} clbits. '
                           'Circuit: {} qubits and {} clbits.'.format(
                               gate.num_qubits, gate.num_clbits,
                               circuit.num_qubits, circuit.num_clbits))

def _rebind_equiv(equiv, query_params):
    equiv_params, equiv_circuit = equiv
    param_map = dict(zip(equiv_params, query_params))
    equiv = equiv_circuit.assign_parameters(param_map, inplace=False)

    return equiv
<commit_msg>Move equivalence drawer visualization imports to runtime (#5488)<commit_after># This code is part of Qiskit.
#
# (C) Copyright IBM 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Gate equivalence library."""

import io
from collections import namedtuple

import retworkx as rx

from .exceptions import CircuitError
from .parameterexpression import ParameterExpression

Key = namedtuple('Key', ['name',
                         'num_qubits'])

Entry = namedtuple('Entry', ['search_base',
                             'equivalences'])

Equivalence = namedtuple('Equivalence', ['params',  # Ordered to match Gate.params
                                         'circuit'])

class EquivalenceLibrary():
    """A library providing a one-way mapping of Gates to their equivalent
    implementations as QuantumCircuits."""

    def __init__(self, *, base=None):
        """Create a new equivalence library.

        Args:
            base (Optional[EquivalenceLibrary]):  Base equivalence library to
                will be referenced if an entry is not found in this library.
        """
        self._base = base

        self._map = {}

    def add_equivalence(self, gate, equivalent_circuit):
        """Add a new equivalence to the library. Future queries for the Gate
        will include the given circuit, in addition to all existing equivalences
        (including those from base).

        Parameterized Gates (those including `qiskit.circuit.Parameters` in their
        `Gate.params`) can be marked equivalent to parameterized circuits,
        provided the parameters match.

        Args:
            gate (Gate): A Gate instance.
            equivalent_circuit (QuantumCircuit): A circuit equivalently
                implementing the given Gate.
        """

        _raise_if_shape_mismatch(gate, equivalent_circuit)
        _raise_if_param_mismatch(gate.params, equivalent_circuit.parameters)

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        equiv = Equivalence(params=gate.params.copy(),
                            circuit=equivalent_circuit.copy())

        if key not in self._map:
            self._map[key] = Entry(search_base=True, equivalences=[])

        self._map[key].equivalences.append(equiv)

    def has_entry(self, gate):
        """Check if a library contains any decompositions for gate.

        Args:
            gate (Gate): A Gate instance.

        Returns:
            Bool: True if gate has a known decomposition in the library.
                False otherwise.
        """

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        return (key in self._map or
                (self._base.has_entry(gate) if self._base is not None else False))

    def set_entry(self, gate, entry):
        """Set the equivalence record for a Gate. Future queries for the Gate
        will return only the circuits provided.

        Parameterized Gates (those including `qiskit.circuit.Parameters` in their
        `Gate.params`) can be marked equivalent to parameterized circuits,
        provided the parameters match.

        Args:
            gate (Gate): A Gate instance.
            entry (List['QuantumCircuit']) : A list of QuantumCircuits, each
                equivalently implementing the given Gate.
        """

        for equiv in entry:
            _raise_if_shape_mismatch(gate, equiv)
            _raise_if_param_mismatch(gate.params, equiv.parameters)

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        equivs = [Equivalence(params=gate.params.copy(),
                              circuit=equiv.copy())
                  for equiv in entry]

        self._map[key] = Entry(search_base=False,
                               equivalences=equivs)

    def get_entry(self, gate):
        """Gets the set of QuantumCircuits circuits from the library which
        equivalently implement the given Gate.

        Parameterized circuits will have their parameters replaced with the
        corresponding entries from Gate.params.

        Args:
            gate (Gate) - Gate: A Gate instance.

        Returns:
            List[QuantumCircuit]: A list of equivalent QuantumCircuits. If empty,
                library contains no known decompositions of Gate.

                Returned circuits will be ordered according to their insertion in
                the library, from earliest to latest, from top to base. The
                ordering of the StandardEquivalenceLibrary will not generally be
                consistent across Qiskit versions.
        """

        key = Key(name=gate.name,
                  num_qubits=gate.num_qubits)

        query_params = gate.params

        return [_rebind_equiv(equiv, query_params)
                for equiv in self._get_equivalences(key)]

    def draw(self, filename=None):
        """Draws the equivalence relations available in the library.

        Args:
            filename (str): An optional path to write the output image to
                if specified this method will return None.

        Returns:
            PIL.Image: Drawn equivalence library.

        Raises:
            ImportError: when pydot or pillow are not installed.
        """
        try:
            import pydot  # pylint: disable=unused-import
            has_pydot = True
        except ImportError:
            has_pydot = False
        try:
            from PIL import Image
            has_pil = True
        except ImportError:
            has_pil = False

        if not has_pydot:
            raise ImportError('EquivalenceLibrary.draw requires pydot. '
                              "You can use 'pip install pydot' to install")
        if not has_pil and not filename:
            raise ImportError('EquivalenceLibrary.draw requires pillow. '
                              "You can use 'pip install pillow' to install")

        dot_str = self._build_basis_graph().to_dot(
            lambda node: {'label': node['label']}, lambda edge: edge)
        dot = pydot.graph_from_dot_data(dot_str)[0]
        if filename:
            extension = filename.split('.')[-1]
            dot.write(filename, format=extension)
            return None
        png = dot.create_png(prog='dot')
        return Image.open(io.BytesIO(png))

    def _build_basis_graph(self):
        graph = rx.PyDiGraph()

        node_map = {}
        for key in self._get_all_keys():
            name, num_qubits = key
            equivalences = self._get_equivalences(key)

            basis = frozenset(['{}/{}'.format(name, num_qubits)])
            for params, decomp in equivalences:
                decomp_basis = frozenset('{}/{}'.format(name, num_qubits)
                                         for name, num_qubits in
                                         {(inst.name, inst.num_qubits)
                                          for inst, _, __ in decomp.data})
                if basis not in node_map:
                    basis_node = graph.add_node({'basis': basis,
                                                 'label': str(set(basis))})
                    node_map[basis] = basis_node
                if decomp_basis not in node_map:
                    decomp_basis_node = graph.add_node({'basis': decomp_basis,
                                                        'label': str(set(decomp_basis))})
                    node_map[decomp_basis] = decomp_basis_node

                label = "%s\n%s" % (
                    str(params), str(decomp) if num_qubits <= 5 else '...')
                graph.add_edge(node_map[basis],
                               node_map[decomp_basis],
                               dict(label=label, fontname='Courier', fontsize=str(8)))

        return graph

    def _get_all_keys(self):
        base_keys = self._base._get_all_keys() if self._base is not None else set()

        self_keys = set(self._map.keys())

        return self_keys | {base_key
                            for base_key in base_keys
                            if base_key not in self._map
                            or self._map[base_key].search_base}

    def _get_equivalences(self, key):
        search_base, equivalences = self._map.get(key, (True, []))

        if search_base and self._base is not None:
            return equivalences + self._base._get_equivalences(key)
        return equivalences

def _raise_if_param_mismatch(gate_params, circuit_parameters):
    gate_parameters = [p for p in gate_params
                       if isinstance(p, ParameterExpression)]

    if set(gate_parameters) != circuit_parameters:
        raise CircuitError('Cannot add equivalence between circuit and gate '
                           'of different parameters. Gate params: {}. '
                           'Circuit params: {}.'.format(
                               gate_parameters,
                               circuit_parameters))

def _raise_if_shape_mismatch(gate, circuit):
    if (gate.num_qubits != circuit.num_qubits
            or gate.num_clbits != circuit.num_clbits):
        raise CircuitError('Cannot add equivalence between circuit and gate '
                           'of different shapes. Gate: {} qubits and {} clbits. '
                           'Circuit: {} qubits and {} clbits.'.format(
                               gate.num_qubits, gate.num_clbits,
                               circuit.num_qubits, circuit.num_clbits))

def _rebind_equiv(equiv, query_params):
    equiv_params, equiv_circuit = equiv
    param_map = dict(zip(equiv_params, query_params))
    equiv = equiv_circuit.assign_parameters(param_map, inplace=False)

    return equiv
<|endoftext|>


<commit_before># Copyright (c) 2010 Aldo Cortesi
# Copyright (c) 2010, 2014 dequis
# Copyright (c) 2012 Randall Ma
# Copyright (c) 2012-2014 Tycho Andersen
# Copyright (c) 2012 Craig Barnes
# Copyright (c) 2013 horsik
# Copyright (c) 2013 Tao Sauvage
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from libqtile.config import Key, Screen, Group, Drag, Click
from libqtile.command import lazy
from libqtile import layout, bar, widget, hook
import os

def to_urgent(qtile):
    cg = qtile.currentGroup
    for group in qtile.groupMap.values():
        if group == cg:
            continue
        if len([w for w in group.windows if w.urgent]) > 0:
            qtile.currentScreen.setGroup(group)
            return

def get_interface():
    def filter_ethernet(iface):
        with open("/sys/class/net/" + iface + "/type") as f:
            return f.readline() == "1\n"

    def filter_up(iface):
        with open("/sys/class/net/" + iface + "/carrier") as f:
            return f.readline() == "1\n"

    return next(filter(filter_up,
                       filter(filter_ethernet,
                              os.listdir("/sys/class/net"))), "wlp2s0")

mod = "mod4"
alt = "mod1"
homedir = os.getenv("HOME")
terminal = os.getenv("TERMCMD")
dgroups_key_binder = None
dgroups_app_rules = []
main = None
follow_mouse_focus = True
bring_front_click = True
cursor_warp = False
auto_fullscreen = True
focus_on_window_activation = "smart"
wmname = "LG3D"

colorscheme = {
    "blue": "#5294E2",
    "black": "#000000",
    "white": "#FFFFFF",
    "red": "#F46067",
    "green": "#00C43E",
    "gray": "#858C98",
    "arc_darker": "#2F343F",
    "arc_dark": "#3E424D",
}

screenlock = "i3lock -S 0 -f -c '" + colorscheme["arc_dark"] + "'" \
    " --insidevercolor=00000000" \
    " --insidewrongcolor=00000000" \
    " --insidecolor=00000000" \
    " --ringvercolor='" + colorscheme["blue"] + "ff'" \
    " --ringwrongcolor='" + colorscheme["red"] + "ff'" \
    " --ringcolor='" + colorscheme["arc_darker"] + "ff'" \
    " --linecolor=00000000" \
    " --separatorcolor=00000000" \
    " --textcolor='" + colorscheme["white"] + "ff'" \
    " --keyhlcolor='" + colorscheme["blue"] + "ff'" \
    " --bshlcolor='" + colorscheme["blue"] + "ff'" \

rofi = "rofi -show %%s -terminal %s -ssh-command '{terminal} -e \"{ssh-client} {host}\"'" % terminal

keys = [
    Key([mod], "j", lazy.layout.down()),
    Key([mod], "k", lazy.layout.up()),
    Key([mod], "h", lazy.layout.left()),
    Key([mod], "l", lazy.layout.right()),
    Key([mod, "shift"], "j", lazy.layout.shuffle_down()),
    Key([mod, "shift"], "k", lazy.layout.shuffle_up()),
    Key([mod, "shift"], "h", lazy.layout.shuffle_left()),
    Key([mod, "shift"], "l", lazy.layout.shuffle_right()),
    Key([mod, "control"], "j", lazy.layout.grow_down()),
    Key([mod, "control"], "k", lazy.layout.grow_up()),
    Key([mod, "control"], "h", lazy.layout.grow_left()),
    Key([mod, "control"], "l", lazy.layout.grow_right()),
    Key([mod], "s", lazy.layout.toggle_split()),
    Key([mod], "n", lazy.layout.normalize()),
    Key([mod], "Escape", lazy.screen.toggle_group()),
    Key([mod], "Right", lazy.screen.next_group()),
    Key([mod], "Left", lazy.screen.prev_group()),
    Key([mod], "f", lazy.window.toggle_fullscreen()),
    Key([mod], "m", lazy.layout.maximize()),
    Key([mod, "control"], "space", lazy.window.toggle_floating()),
    Key([mod], "space", lazy.next_layout()),
    Key([mod], "c", lazy.window.kill()),
    Key([mod], "Tab", lazy.layout.next()),
    Key([mod, "shift"], "Tab", lazy.layout.previous()),
    Key([mod], "1", lazy.to_screen(0)),
    Key([mod], "2", lazy.to_screen(1)),
    Key([mod], "3", lazy.to_screen(2)),
    Key([mod], "space", lazy.next_layout()),
    Key([mod, "shift"], "space", lazy.prev_layout()),
    Key([mod], "c", lazy.window.kill()),
    Key([mod, "control"], "r", lazy.restart()),
    Key([mod, "control"], "q", lazy.shutdown()),
    Key([mod, "shift"], "period", lazy.spawncmd()),
    Key([mod], "udiaeresis", lazy.function(to_urgent)),

    # Multimedia/Function keys
    Key([], "XF86MonBrightnessDown", lazy.spawn("xbacklight -dec 1 -steps 1")),
    Key([], "XF86MonBrightnessUp", lazy.spawn("xbacklight -inc 1 -steps 1")),
    Key([], "XF86AudioRaiseVolume", lazy.spawn("amixer sset Master 2%+")),
    Key([], "XF86AudioLowerVolume", lazy.spawn("amixer sset Master 2%-")),
    Key([], "XF86AudioMute", lazy.spawn("amixer sset Master toggle")),
    Key([], "XF86Display", lazy.spawn("arandr")),
    Key([], "XF86WebCam", lazy.spawn("guvcview")),
    Key([], "XF86AudioNext", lazy.spawn("mocp --next")),
    Key([], "XF86AudioPrev", lazy.spawn("mocp --previous")),
    Key([], "XF86AudioPlay", lazy.spawn(homedir + "/.moc/mocp_toggle")),
    Key([], "KP_Right", lazy.spawn("mocp --next")),
    Key([], "KP_Left", lazy.spawn("mocp --previous")),
    Key([], "KP_Begin", lazy.spawn(homedir + "/.moc/mocp_toggle")),

    # Programs
    Key([mod], "Return", lazy.spawn(terminal)),
    Key([mod, alt], "Return", lazy.spawn("termite --class drop  -e 'tmux new-session -A -s drop'")),
    Key([], "Print", lazy.spawn("xfce4-screenshooter")),
    Key([mod, "control"], "n", lazy.spawn("xrandr --output LVDS1 --mode 1366x768 --output HDMI1 --off --output VGA1 --off")),
    Key([mod, alt], "f", lazy.spawn("nautilus --no-desktop")),
    Key([mod, alt], "r", lazy.spawn([terminal, "-e", "ranger"])),
    Key([mod, alt], "m", lazy.spawn([terminal, "-e", "mocp"])),
    Key([mod, alt], "n", lazy.spawn('gvim note:Notes')),
    Key([mod, alt], "b", lazy.spawn("firefox")),
    Key([mod, alt], "c", lazy.spawn("chromium --incognito")),
    Key([mod, alt], "p", lazy.spawn(["keepassx2", homedir + "/sync/passwords.kdbx"])),
    Key([mod, "control"], "s", lazy.spawn(screenlock)),

    # rofi launcher
    Key([mod], "x", lazy.spawn(rofi % "run")),
    Key([mod], "d", lazy.spawn(rofi % "drun")),
    Key([mod], "a", lazy.spawn(rofi % "window")),
    Key([mod], "y", lazy.spawn(rofi % "ssh")),
]

groups = [Group(i) for i in "qwertzuiop"]

for i in groups:
    # mod1 + letter of group = switch to group
    keys.append(
        Key([mod], i.name, lazy.group[i.name].toscreen())
    )

    # mod1 + shift + letter of group = switch to & move focused window to group
    keys.append(
        Key([mod, "shift"], i.name, lazy.window.togroup(i.name))
    )

border = {
    "border_focus": colorscheme["blue"],
    "border_normal": colorscheme["black"],
    "border_width": 4
}

layouts = [
    # TODO bordercolor, width
    layout.Columns(name="col", num_columns=2, **border),
    layout.VerticalTile(name="vert", **border),
    layout.Max(),
]

floating_layout = layout.Floating(**border)

widget_defaults = dict(
    font='Arial',
    fontsize=12,
    padding=1,
)

graph_config = {
    "width": 70,
    "background": None,
    "border_color": colorscheme["blue"],
    "border_width": 0,
    "fill_color": colorscheme["white"],
    "frequency": 2,
    "graph_color": colorscheme["white"],
    "line_width": 1,
    "margin_x": 3,
    "margin_y": 3,
    "samples": 50,
    "start_pos": 'bottom',
    "type": 'linefill'
}

sep_config = {
    "linewidth": 4,
    "padding": 10,
    "foreground": colorscheme["blue"],
}

group_box_config = {
    "highlight_method": "border",
    "inactive": colorscheme["gray"],
    "rounded": False,
    "borderwidth": 4,
    "active": colorscheme["white"],
    "this_current_screen_border": colorscheme["blue"],
    "this_screen_border": colorscheme["blue"],
    "other_screen_border": colorscheme["gray"],
    "urgent_border": colorscheme["red"],
    "urgent_text": colorscheme["red"],
}

task_list_config = {
    "highlight_method": "border",
    "border": colorscheme["blue"],
    "borderwidth": 4,
    "rounded": False,
    "max_title_width": 200,
    "urgent_border": colorscheme["red"],
}

widgets = [
    widget.GroupBox(**group_box_config),
    widget.Prompt(),
    widget.TaskList(**task_list_config),
    # widget.TextBox("default config", name="default"),
    widget.Sep(**sep_config),
    widget.Systray(),
    widget.Sep(**sep_config),
    widget.Net(interface=get_interface(), update_interval=2),
    widget.NetGraph(bandwidth_type="down", interface=get_interface(), **graph_config),
    widget.Sep(**sep_config),
    widget.TextBox("CPU:"),
    widget.CPUGraph(core='all', **graph_config),
    widget.Sep(**sep_config),
    widget.TextBox("🔊"),
    widget.Volume(update_interval=1),
]

if os.path.exists("/sys/class/power_supply/BAT0/present"):
    widgets.extend([
        widget.Sep(**sep_config),
        widget.Battery(low_foreground=colorscheme["red"],
                       discharge_char="🗲",
                       charge_char="🔌")
    ])

widgets.extend([
    widget.Sep(**sep_config),
    widget.Clock(format='%H:%M %a %d', update_interval=5),
    widget.Sep(**sep_config),
    widget.CurrentLayout(),
    widget.Sep(**sep_config),
])

screens = [
    Screen(
        top=bar.Bar(
            widgets,
            22,
            background=colorscheme["arc_darker"]
        ),
    ),
    Screen(
        top=bar.Bar(
            [
                widget.GroupBox(**group_box_config),
                widget.Prompt(),
                widget.TaskList(**task_list_config),
                widget.Sep(**sep_config),
                widget.Clock(format='%H:%M %a %d', update_interval=5),
                widget.Sep(**sep_config),
                widget.CurrentLayout(),
                widget.Sep(**sep_config),
            ],
            22,
            background=colorscheme["arc_darker"]
        ),
    ),
]

# Drag floating layouts.
mouse = [
    Drag([mod], "Button1", lazy.window.set_position_floating(),
         start=lazy.window.get_position()),
    Drag([mod], "Button3", lazy.window.set_size_floating(),
         start=lazy.window.get_size()),
    Click([mod], "Button2", lazy.window.bring_to_front())
]

@hook.subscribe.client_new
def floating_windows(window):
    floaters = ["mpv", "quake", "Gcr-prompter", "Keepassx"]
    if window.window.get_wm_class()[1] in floaters:
        window.floating = True

@hook.subscribe.client_managed
def drop(window):
    if window.window.get_wm_class()[1] == "drop":
        window.fullscreen = True
        #window.place(100, 200, 400, 200, 3, None, above=True, force=True, margin=None)

@hook.subscribe.startup
def set_wallpaper():
    import subprocess
    subprocess.run(["feh", "--bg-fill",  homedir + "/.wallpaper"])

<commit_msg>qtile: fix nic detection<commit_after># Copyright (c) 2010 Aldo Cortesi
# Copyright (c) 2010, 2014 dequis
# Copyright (c) 2012 Randall Ma
# Copyright (c) 2012-2014 Tycho Andersen
# Copyright (c) 2012 Craig Barnes
# Copyright (c) 2013 horsik
# Copyright (c) 2013 Tao Sauvage
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from libqtile.config import Key, Screen, Group, Drag, Click
from libqtile.command import lazy
from libqtile import layout, bar, widget, hook
import os

def to_urgent(qtile):
    cg = qtile.currentGroup
    for group in qtile.groupMap.values():
        if group == cg:
            continue
        if len([w for w in group.windows if w.urgent]) > 0:
            qtile.currentScreen.setGroup(group)
            return

def get_interface():
    def filter_ethernet(iface):
        with open("/sys/class/net/" + iface + "/type") as f:
            return f.readline() == "1\n"

    def filter_up(iface):
        with open("/sys/class/net/" + iface + "/operstate") as f:
            return f.readline() == "up\n"

    return next(filter(filter_up,
                       filter(filter_ethernet,
                              os.listdir("/sys/class/net"))), "wlp2s0")

mod = "mod4"
alt = "mod1"
homedir = os.getenv("HOME")
terminal = os.getenv("TERMCMD")
dgroups_key_binder = None
dgroups_app_rules = []
main = None
follow_mouse_focus = True
bring_front_click = True
cursor_warp = False
auto_fullscreen = True
focus_on_window_activation = "smart"
wmname = "LG3D"

colorscheme = {
    "blue": "#5294E2",
    "black": "#000000",
    "white": "#FFFFFF",
    "red": "#F46067",
    "green": "#00C43E",
    "gray": "#858C98",
    "arc_darker": "#2F343F",
    "arc_dark": "#3E424D",
}

screenlock = "i3lock -S 0 -f -c '" + colorscheme["arc_dark"] + "'" \
    " --insidevercolor=00000000" \
    " --insidewrongcolor=00000000" \
    " --insidecolor=00000000" \
    " --ringvercolor='" + colorscheme["blue"] + "ff'" \
    " --ringwrongcolor='" + colorscheme["red"] + "ff'" \
    " --ringcolor='" + colorscheme["arc_darker"] + "ff'" \
    " --linecolor=00000000" \
    " --separatorcolor=00000000" \
    " --textcolor='" + colorscheme["white"] + "ff'" \
    " --keyhlcolor='" + colorscheme["blue"] + "ff'" \
    " --bshlcolor='" + colorscheme["blue"] + "ff'" \

rofi = "rofi -show %%s -terminal %s -ssh-command '{terminal} -e \"{ssh-client} {host}\"'" % terminal

keys = [
    Key([mod], "j", lazy.layout.down()),
    Key([mod], "k", lazy.layout.up()),
    Key([mod], "h", lazy.layout.left()),
    Key([mod], "l", lazy.layout.right()),
    Key([mod, "shift"], "j", lazy.layout.shuffle_down()),
    Key([mod, "shift"], "k", lazy.layout.shuffle_up()),
    Key([mod, "shift"], "h", lazy.layout.shuffle_left()),
    Key([mod, "shift"], "l", lazy.layout.shuffle_right()),
    Key([mod, "control"], "j", lazy.layout.grow_down()),
    Key([mod, "control"], "k", lazy.layout.grow_up()),
    Key([mod, "control"], "h", lazy.layout.grow_left()),
    Key([mod, "control"], "l", lazy.layout.grow_right()),
    Key([mod], "s", lazy.layout.toggle_split()),
    Key([mod], "n", lazy.layout.normalize()),
    Key([mod], "Escape", lazy.screen.toggle_group()),
    Key([mod], "Right", lazy.screen.next_group()),
    Key([mod], "Left", lazy.screen.prev_group()),
    Key([mod], "f", lazy.window.toggle_fullscreen()),
    Key([mod], "m", lazy.layout.maximize()),
    Key([mod, "control"], "space", lazy.window.toggle_floating()),
    Key([mod], "space", lazy.next_layout()),
    Key([mod], "c", lazy.window.kill()),
    Key([mod], "Tab", lazy.layout.next()),
    Key([mod, "shift"], "Tab", lazy.layout.previous()),
    Key([mod], "1", lazy.to_screen(0)),
    Key([mod], "2", lazy.to_screen(1)),
    Key([mod], "3", lazy.to_screen(2)),
    Key([mod], "space", lazy.next_layout()),
    Key([mod, "shift"], "space", lazy.prev_layout()),
    Key([mod], "c", lazy.window.kill()),
    Key([mod, "control"], "r", lazy.restart()),
    Key([mod, "control"], "q", lazy.shutdown()),
    Key([mod, "shift"], "period", lazy.spawncmd()),
    Key([mod], "udiaeresis", lazy.function(to_urgent)),

    # Multimedia/Function keys
    Key([], "XF86MonBrightnessDown", lazy.spawn("xbacklight -dec 1 -steps 1")),
    Key([], "XF86MonBrightnessUp", lazy.spawn("xbacklight -inc 1 -steps 1")),
    Key([], "XF86AudioRaiseVolume", lazy.spawn("amixer sset Master 2%+")),
    Key([], "XF86AudioLowerVolume", lazy.spawn("amixer sset Master 2%-")),
    Key([], "XF86AudioMute", lazy.spawn("amixer sset Master toggle")),
    Key([], "XF86Display", lazy.spawn("arandr")),
    Key([], "XF86WebCam", lazy.spawn("guvcview")),
    Key([], "XF86AudioNext", lazy.spawn("mocp --next")),
    Key([], "XF86AudioPrev", lazy.spawn("mocp --previous")),
    Key([], "XF86AudioPlay", lazy.spawn(homedir + "/.moc/mocp_toggle")),
    Key([], "KP_Right", lazy.spawn("mocp --next")),
    Key([], "KP_Left", lazy.spawn("mocp --previous")),
    Key([], "KP_Begin", lazy.spawn(homedir + "/.moc/mocp_toggle")),

    # Programs
    Key([mod], "Return", lazy.spawn(terminal)),
    Key([mod, alt], "Return", lazy.spawn("termite --class drop  -e 'tmux new-session -A -s drop'")),
    Key([], "Print", lazy.spawn("xfce4-screenshooter")),
    Key([mod, "control"], "n", lazy.spawn("xrandr --output LVDS1 --mode 1366x768 --output HDMI1 --off --output VGA1 --off")),
    Key([mod, alt], "f", lazy.spawn("nautilus --no-desktop")),
    Key([mod, alt], "r", lazy.spawn([terminal, "-e", "ranger"])),
    Key([mod, alt], "m", lazy.spawn([terminal, "-e", "mocp"])),
    Key([mod, alt], "n", lazy.spawn('gvim note:Notes')),
    Key([mod, alt], "b", lazy.spawn("firefox")),
    Key([mod, alt], "c", lazy.spawn("chromium --incognito")),
    Key([mod, alt], "p", lazy.spawn(["keepassx2", homedir + "/sync/passwords.kdbx"])),
    Key([mod, "control"], "s", lazy.spawn(screenlock)),

    # rofi launcher
    Key([mod], "x", lazy.spawn(rofi % "run")),
    Key([mod], "d", lazy.spawn(rofi % "drun")),
    Key([mod], "a", lazy.spawn(rofi % "window")),
    Key([mod], "y", lazy.spawn(rofi % "ssh")),
]

groups = [Group(i) for i in "qwertzuiop"]

for i in groups:
    # mod1 + letter of group = switch to group
    keys.append(
        Key([mod], i.name, lazy.group[i.name].toscreen())
    )

    # mod1 + shift + letter of group = switch to & move focused window to group
    keys.append(
        Key([mod, "shift"], i.name, lazy.window.togroup(i.name))
    )

border = {
    "border_focus": colorscheme["blue"],
    "border_normal": colorscheme["black"],
    "border_width": 4
}

layouts = [
    # TODO bordercolor, width
    layout.Columns(name="col", num_columns=2, **border),
    layout.VerticalTile(name="vert", **border),
    layout.Max(),
]

floating_layout = layout.Floating(**border)

widget_defaults = dict(
    font='Arial',
    fontsize=12,
    padding=1,
)

graph_config = {
    "width": 70,
    "background": None,
    "border_color": colorscheme["blue"],
    "border_width": 0,
    "fill_color": colorscheme["white"],
    "frequency": 2,
    "graph_color": colorscheme["white"],
    "line_width": 1,
    "margin_x": 3,
    "margin_y": 3,
    "samples": 50,
    "start_pos": 'bottom',
    "type": 'linefill'
}

sep_config = {
    "linewidth": 4,
    "padding": 10,
    "foreground": colorscheme["blue"],
}

group_box_config = {
    "highlight_method": "border",
    "inactive": colorscheme["gray"],
    "rounded": False,
    "borderwidth": 4,
    "active": colorscheme["white"],
    "this_current_screen_border": colorscheme["blue"],
    "this_screen_border": colorscheme["blue"],
    "other_screen_border": colorscheme["gray"],
    "urgent_border": colorscheme["red"],
    "urgent_text": colorscheme["red"],
}

task_list_config = {
    "highlight_method": "border",
    "border": colorscheme["blue"],
    "borderwidth": 4,
    "rounded": False,
    "max_title_width": 200,
    "urgent_border": colorscheme["red"],
}

widgets = [
    widget.GroupBox(**group_box_config),
    widget.Prompt(),
    widget.TaskList(**task_list_config),
    # widget.TextBox("default config", name="default"),
    widget.Sep(**sep_config),
    widget.Systray(),
    widget.Sep(**sep_config),
    widget.Net(interface=get_interface(), update_interval=2),
    widget.NetGraph(bandwidth_type="down", interface=get_interface(), **graph_config),
    widget.Sep(**sep_config),
    widget.TextBox("CPU:"),
    widget.CPUGraph(core='all', **graph_config),
    widget.Sep(**sep_config),
    widget.TextBox("🔊"),
    widget.Volume(update_interval=1),
]

if os.path.exists("/sys/class/power_supply/BAT0/present"):
    widgets.extend([
        widget.Sep(**sep_config),
        widget.Battery(low_foreground=colorscheme["red"],
                       discharge_char="🗲",
                       charge_char="🔌")
    ])

widgets.extend([
    widget.Sep(**sep_config),
    widget.Clock(format='%H:%M %a %d', update_interval=5),
    widget.Sep(**sep_config),
    widget.CurrentLayout(),
    widget.Sep(**sep_config),
])

screens = [
    Screen(
        top=bar.Bar(
            widgets,
            22,
            background=colorscheme["arc_darker"]
        ),
    ),
    Screen(
        top=bar.Bar(
            [
                widget.GroupBox(**group_box_config),
                widget.Prompt(),
                widget.TaskList(**task_list_config),
                widget.Sep(**sep_config),
                widget.Clock(format='%H:%M %a %d', update_interval=5),
                widget.Sep(**sep_config),
                widget.CurrentLayout(),
                widget.Sep(**sep_config),
            ],
            22,
            background=colorscheme["arc_darker"]
        ),
    ),
]

# Drag floating layouts.
mouse = [
    Drag([mod], "Button1", lazy.window.set_position_floating(),
         start=lazy.window.get_position()),
    Drag([mod], "Button3", lazy.window.set_size_floating(),
         start=lazy.window.get_size()),
    Click([mod], "Button2", lazy.window.bring_to_front())
]

@hook.subscribe.client_new
def floating_windows(window):
    floaters = ["mpv", "quake", "Gcr-prompter", "Keepassx"]
    if window.window.get_wm_class()[1] in floaters:
        window.floating = True

@hook.subscribe.client_managed
def drop(window):
    if window.window.get_wm_class()[1] == "drop":
        window.fullscreen = True
        #window.place(100, 200, 400, 200, 3, None, above=True, force=True, margin=None)

@hook.subscribe.startup
def set_wallpaper():
    import subprocess
    subprocess.run(["feh", "--bg-fill",  homedir + "/.wallpaper"])

<|endoftext|>


<commit_before># -----------------------------------------------------------------------------
# Copyright (c) 2014--, The Qiita Development Team.
#
# Distributed under the terms of the BSD 3-clause License.
#
# The full license is in the file LICENSE, distributed with this software.
# -----------------------------------------------------------------------------

from unittest import main
from tempfile import mkdtemp, mkstemp
from os import remove, close
from os.path import exists, isdir
from shutil import rmtree
from json import dumps
from time import sleep

import numpy as np
from biom import Table
from biom.util import biom_open
from qiita_client.testing import PluginTestCase

from qtp_biom import plugin

class PluginTests(PluginTestCase):
    def setUp(self):
        self.out_dir = mkdtemp()
        self._clean_up_files = [self.out_dir]

    def tearDown(self):
        for fp in self._clean_up_files:
            if exists(fp):
                if isdir(fp):
                    rmtree(fp)
                else:
                    remove(fp)

    def _wait_job(self, job_id):
        for i in range(5):
            status = self.qclient.get_job_info(job_id)['status']
            if status != 'running':
                break
            sleep(0.5)
            print "TRYING TO DEBUG IN HERE"
        return status

    def test_execute_job_summary(self):
        # Create a summary job
        data = {'command': dumps(['BIOM type', '2.1.4',
                                  'Generate HTML summary']),
                'parameters': dumps({'input_data': 4}),
                'status': 'queued'}
        job_id = self.qclient.post(
            '/apitest/processing_job/', data=data)['job']

        plugin("https://localhost:21174", job_id, self.out_dir)

        obs = self._wait_job(job_id)
        self.assertEqual(obs, 'success')

    def test_execute_job_validate(self):
        # Create a prep template
        prep_info = {'SKB8.640193': {'col': 'val1'},
                     'SKD8.640184': {'col': 'val2'}}
        data = {'prep_info': dumps(prep_info),
                'study': 1,
                'data_type': '16S'}
        template = self.qclient.post(
            '/apitest/prep_template/', data=data)['prep']
        # Create a new validate job
        fd, biom_fp = mkstemp(suffix=".biom")
        close(fd)
        data = np.random.randint(100, size=(2, 2))
        table = Table(data, ['O1', 'O2'], ['SKB8.640193', 'SKD8.640184'])
        with biom_open(biom_fp, 'w') as f:
            table.to_hdf5(f, "Test")
        data = {'command': dumps(['BIOM type', '2.1.4', 'Validate']),
                'parameters': dumps(
                    {'files': dumps({'biom': [biom_fp]}),
                     'template': template,
                     'artifact_type': 'BIOM'}),
                'artifact_type': 'BIOM',
                'status': 'queued'}
        job_id = self.qclient.post(
            '/apitest/processing_job/', data=data)['job']

        plugin("https://localhost:21174", job_id, self.out_dir)
        obs = self._wait_job(job_id)
        self.assertEqual(obs, 'success')

    def test_execute_job_error(self):
        # Create a prep template
        print "START TEST"
        prep_info = {'SKB8.640193': {'col': 'val1'},
                     'SKD8.640184': {'col': 'val2'}}
        data = {'prep_info': dumps(prep_info),
                'study': 1,
                'data_type': '16S'}
        template = self.qclient.post(
            '/apitest/prep_template/', data=data)['prep']
        print "PREP TEMPLATE CREATED"
        # Create a new validate job
        fd, biom_fp = mkstemp(suffix=".biom")
        close(fd)
        data = np.random.randint(100, size=(2, 2))
        table = Table(data, ['O1', 'O2'], ['S1', 'S2'])
        with biom_open(biom_fp, 'w') as f:
            table.to_hdf5(f, "Test")
        print "BIOM TABLE CREATED"
        data = {'command': dumps(['BIOM type', '2.1.4', 'Validate']),
                'parameters': dumps(
                    {'files': dumps({'biom': [biom_fp]}),
                     'template': template,
                     'artifact_type': 'BIOM'}),
                'artifact_type': 'BIOM',
                'status': 'queued'}
        job_id = self.qclient.post(
            '/apitest/processing_job/', data=data)['job']
        print "JOB CREATED"

        print "WHAT ABOUT HERE?"
        plugin("https://localhost:21174", job_id, self.out_dir)
        print "HEY DONE!!!"
        obs = self._wait_job(job_id)
        print "I CAN'T WAIT ANYMORE"
        self.assertEqual(obs, 'error')

if __name__ == '__main__':
    main()
<commit_msg>Commenting all the code on that file to see something?? Completely lost...<commit_after># -----------------------------------------------------------------------------
# Copyright (c) 2014--, The Qiita Development Team.
#
# Distributed under the terms of the BSD 3-clause License.
#
# The full license is in the file LICENSE, distributed with this software.
# -----------------------------------------------------------------------------

from unittest import main
from tempfile import mkdtemp, mkstemp
from os import remove, close
from os.path import exists, isdir
from shutil import rmtree
from json import dumps
from time import sleep

import numpy as np
from biom import Table
from biom.util import biom_open
from qiita_client.testing import PluginTestCase

from qtp_biom import plugin

class PluginTests(PluginTestCase):
    def setUp(self):
        self.out_dir = mkdtemp()
        self._clean_up_files = [self.out_dir]

    def tearDown(self):
        for fp in self._clean_up_files:
            if exists(fp):
                if isdir(fp):
                    rmtree(fp)
                else:
                    remove(fp)

    # def _wait_job(self, job_id):
    #     for i in range(5):
    #         status = self.qclient.get_job_info(job_id)['status']
    #         if status != 'running':
    #             break
    #         sleep(0.5)
    #     return status
    #
    # def test_execute_job_summary(self):
    #     # Create a summary job
    #     data = {'command': dumps(['BIOM type', '2.1.4',
    #                               'Generate HTML summary']),
    #             'parameters': dumps({'input_data': 4}),
    #             'status': 'queued'}
    #     job_id = self.qclient.post(
    #         '/apitest/processing_job/', data=data)['job']
    #
    #     plugin("https://localhost:21174", job_id, self.out_dir)
    #
    #     obs = self._wait_job(job_id)
    #     self.assertEqual(obs, 'success')
    #
    # def test_execute_job_validate(self):
    #     # Create a prep template
    #     prep_info = {'SKB8.640193': {'col': 'val1'},
    #                  'SKD8.640184': {'col': 'val2'}}
    #     data = {'prep_info': dumps(prep_info),
    #             'study': 1,
    #             'data_type': '16S'}
    #     template = self.qclient.post(
    #         '/apitest/prep_template/', data=data)['prep']
    #     # Create a new validate job
    #     fd, biom_fp = mkstemp(suffix=".biom")
    #     close(fd)
    #     data = np.random.randint(100, size=(2, 2))
    #     table = Table(data, ['O1', 'O2'], ['SKB8.640193', 'SKD8.640184'])
    #     with biom_open(biom_fp, 'w') as f:
    #         table.to_hdf5(f, "Test")
    #     data = {'command': dumps(['BIOM type', '2.1.4', 'Validate']),
    #             'parameters': dumps(
    #                 {'files': dumps({'biom': [biom_fp]}),
    #                  'template': template,
    #                  'artifact_type': 'BIOM'}),
    #             'artifact_type': 'BIOM',
    #             'status': 'queued'}
    #     job_id = self.qclient.post(
    #         '/apitest/processing_job/', data=data)['job']
    #
    #     plugin("https://localhost:21174", job_id, self.out_dir)
    #     obs = self._wait_job(job_id)
    #     self.assertEqual(obs, 'success')
    #
    # def test_execute_job_error(self):
    #     # Create a prep template
    #     prep_info = {'SKB8.640193': {'col': 'val1'},
    #                  'SKD8.640184': {'col': 'val2'}}
    #     data = {'prep_info': dumps(prep_info),
    #             'study': 1,
    #             'data_type': '16S'}
    #     template = self.qclient.post(
    #         '/apitest/prep_template/', data=data)['prep']
    #     # Create a new validate job
    #     fd, biom_fp = mkstemp(suffix=".biom")
    #     close(fd)
    #     data = np.random.randint(100, size=(2, 2))
    #     table = Table(data, ['O1', 'O2'], ['S1', 'S2'])
    #     with biom_open(biom_fp, 'w') as f:
    #         table.to_hdf5(f, "Test")
    #     data = {'command': dumps(['BIOM type', '2.1.4', 'Validate']),
    #             'parameters': dumps(
    #                 {'files': dumps({'biom': [biom_fp]}),
    #                  'template': template,
    #                  'artifact_type': 'BIOM'}),
    #             'artifact_type': 'BIOM',
    #             'status': 'queued'}
    #     job_id = self.qclient.post(
    #         '/apitest/processing_job/', data=data)['job']
    #
    #     plugin("https://localhost:21174", job_id, self.out_dir)
    #     obs = self._wait_job(job_id)
    #     self.assertEqual(obs, 'error')

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


<commit_before># This file is part of QuTiP: Quantum Toolbox in Python.
#
#    Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson.
#    All rights reserved.
#
#    Redistribution and use in source and binary forms, with or without
#    modification, are permitted provided that the following conditions are
#    met:
#
#    1. Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#
#    2. Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#
#    3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names
#       of its contributors may be used to endorse or promote products derived
#       from this software without specific prior written permission.
#
#    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
#    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###############################################################################
import pytest
from copy import deepcopy

from qutip.qip.circuit import QubitCircuit
from qutip.qip.scheduler import Instruction, Scheduler
from qutip.qip.operations.gates import gate_sequence_product
from qutip import process_fidelity, qeye, tracedist

def _circuit1():
    circuit1 = QubitCircuit(6)
    circuit1.add_gate("SNOT", 2)
    circuit1.add_gate("CNOT", 4, 2)
    circuit1.add_gate("CNOT", 3, 2)
    circuit1.add_gate("CNOT", 1, 2)
    circuit1.add_gate("CNOT", 5, 4)
    circuit1.add_gate("CNOT", 1, 5)
    circuit1.add_gate("SWAP", [0, 1])
    return circuit1

def _circuit2():
    circuit2 = QubitCircuit(8)
    circuit2.add_gate("SNOT", 1)
    circuit2.add_gate("SNOT", 2)
    circuit2.add_gate("SNOT", 3)
    circuit2.add_gate("CNOT", 4, 5)
    circuit2.add_gate("CNOT", 4, 6)
    circuit2.add_gate("CNOT", 3, 4)
    circuit2.add_gate("CNOT", 3, 5)
    circuit2.add_gate("CNOT", 3, 7)
    circuit2.add_gate("CNOT", 2, 4)
    circuit2.add_gate("CNOT", 2, 6)
    circuit2.add_gate("CNOT", 2, 7)
    circuit2.add_gate("CNOT", 1, 5)
    circuit2.add_gate("CNOT", 1, 6)
    circuit2.add_gate("CNOT", 1, 7)
    return circuit2

def _circuit3():
    circuit3 = QubitCircuit(4)
    instruction_list1 = [
        Instruction("SNOT", [0], duration=1),
        Instruction("SNOT", [1], duration=1),
        Instruction("CNOT", [2], [3], duration=2),
        Instruction("CNOT", [1], [2], duration=2),
        Instruction("CNOT", [1], [0], duration=2),
        Instruction("SNOT", [3], duration=1),
        Instruction("CNOT", [1], [3], duration=2),
        Instruction("CNOT", [1], [3], duration=2)
    ]
    circuit3.gates = instruction_list1
    return circuit3

@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        (deepcopy(_circuit1()), "ASAP", 4, False, False),
        (deepcopy(_circuit1()), "ALAP", 4, False, False),
        (deepcopy(_circuit3()), "ASAP", 7, False, False),
        (deepcopy(_circuit3()), "ALAP", 7, False, False),
        (deepcopy(_circuit3()), "ASAP", 4, False, True),  # treat instructions as gates
        (deepcopy(_circuit3()), "ALAP", 4, False, True),  # treat instructions as gates
    ])
def test_scheduling_gates1(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)

# There is some problem with circuit2 on Mac.
# When I list all three tests together, a segment fault arise.
# I suspect it has something to do with pytest.
@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        (deepcopy(_circuit2()), "ASAP", 4, False, False),
    ])
def test_scheduling_gates2(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)

@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        (deepcopy(_circuit2()), "ALAP", 5, False, False),
    ])
def test_scheduling_gates4(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)

@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        (deepcopy(_circuit2()), "ALAP", 4, True,  False),  # with random shuffling
    ])
def test_scheduling_gates5(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)
<commit_msg>add tests id<commit_after># This file is part of QuTiP: Quantum Toolbox in Python.
#
#    Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson.
#    All rights reserved.
#
#    Redistribution and use in source and binary forms, with or without
#    modification, are permitted provided that the following conditions are
#    met:
#
#    1. Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#
#    2. Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#
#    3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names
#       of its contributors may be used to endorse or promote products derived
#       from this software without specific prior written permission.
#
#    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
#    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#    HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###############################################################################
import pytest
from copy import deepcopy

from qutip.qip.circuit import QubitCircuit
from qutip.qip.scheduler import Instruction, Scheduler
from qutip.qip.operations.gates import gate_sequence_product
from qutip import process_fidelity, qeye, tracedist

def _circuit1():
    circuit1 = QubitCircuit(6)
    circuit1.add_gate("SNOT", 2)
    circuit1.add_gate("CNOT", 4, 2)
    circuit1.add_gate("CNOT", 3, 2)
    circuit1.add_gate("CNOT", 1, 2)
    circuit1.add_gate("CNOT", 5, 4)
    circuit1.add_gate("CNOT", 1, 5)
    circuit1.add_gate("SWAP", [0, 1])
    return circuit1

def _circuit2():
    circuit2 = QubitCircuit(8)
    circuit2.add_gate("SNOT", 1)
    circuit2.add_gate("SNOT", 2)
    circuit2.add_gate("SNOT", 3)
    circuit2.add_gate("CNOT", 4, 5)
    circuit2.add_gate("CNOT", 4, 6)
    circuit2.add_gate("CNOT", 3, 4)
    circuit2.add_gate("CNOT", 3, 5)
    circuit2.add_gate("CNOT", 3, 7)
    circuit2.add_gate("CNOT", 2, 4)
    circuit2.add_gate("CNOT", 2, 6)
    circuit2.add_gate("CNOT", 2, 7)
    circuit2.add_gate("CNOT", 1, 5)
    circuit2.add_gate("CNOT", 1, 6)
    circuit2.add_gate("CNOT", 1, 7)
    return circuit2

def _circuit3():
    circuit3 = QubitCircuit(4)
    instruction_list1 = [
        Instruction("SNOT", [0], duration=1),
        Instruction("SNOT", [1], duration=1),
        Instruction("CNOT", [2], [3], duration=2),
        Instruction("CNOT", [1], [2], duration=2),
        Instruction("CNOT", [1], [0], duration=2),
        Instruction("SNOT", [3], duration=1),
        Instruction("CNOT", [1], [3], duration=2),
        Instruction("CNOT", [1], [3], duration=2)
    ]
    circuit3.gates = instruction_list1
    return circuit3

@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        pytest.param(deepcopy(_circuit1()), "ASAP", 4, False, False, id="circuit1 ASAP)"),
        pytest.param(deepcopy(_circuit1()), "ALAP", 4, False, False, id="circuit1 ALAP)"),
        pytest.param(deepcopy(_circuit3()), "ASAP", 7, False, False, id="circuit1 pulse ASAP)"),
        pytest.param(deepcopy(_circuit3()), "ALAP", 7, False, False, id="circuit1 pulse ALAP)"),
        pytest.param(deepcopy(_circuit3()), "ASAP", 4, False, True, id="circuit1 gate ASAP)"),  # treat instructions as gates
        pytest.param(deepcopy(_circuit3()), "ALAP", 4, False, True, id="circuit1 gate ALAP)"),  # treat instructions as gates
    ])
def test_scheduling_gates1(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)

# There is some problem with circuit2 on Mac.
# When I list all three tests together, a segment fault arise.
# I suspect it has something to do with pytest.
@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        pytest.param(deepcopy(_circuit2()), "ASAP", 4, False, False, id="circuit2 ASAP"),
    ])
def test_scheduling_gates2(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)

@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        pytest.param(deepcopy(_circuit2()), "ALAP", 5, False, False, id="circuit2 ALAP no shuffle")
    ])
def test_scheduling_gates4(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)

@pytest.mark.parametrize(
    "circuit, method, expected_length, random_shuffle, gates_schedule",
    [
        pytest.param(deepcopy(_circuit2()), "ALAP", 4, True, False, id="circuit2 ALAP shuffle"),  # with random shuffling
    ])
def test_scheduling_gates5(
        circuit, method, expected_length, random_shuffle, gates_schedule):
    if random_shuffle:
        repeat_num = 5
    else:
        repeat_num = 0
    result0 = gate_sequence_product(circuit.propagators())

    # run the scheduler
    scheduler = Scheduler(method)
    gate_cycle_indices = scheduler.schedule(
        circuit, gates_schedule=gates_schedule, repeat_num=repeat_num)

    # check if the scheduled length is expected
    assert(max(gate_cycle_indices) == expected_length)
    scheduled_gate = [[] for i in range(max(gate_cycle_indices)+1)]

    # check if the scheduled circuit is correct
    for i, cycles in enumerate(gate_cycle_indices):
        scheduled_gate[cycles].append(circuit.gates[i])
    circuit.gates = sum(scheduled_gate, [])
    result1 = gate_sequence_product(circuit.propagators())
    assert(tracedist(result0*result1.dag(), qeye(result0.dims[0])) < 1.0e-7)
<|endoftext|>


<commit_before>"""
Intended to fix any inconsistencies that may arise during the rollout of the CohortMembership model.
Illustration: https://gist.github.com/efischer19/d62f8ee42b7fbfbc6c9a
"""
from django.core.management.base import BaseCommand
from django.db import IntegrityError

from openedx.core.djangoapps.course_groups.models import CourseUserGroup, CohortMembership

class Command(BaseCommand):
    """
    Repair any inconsistencies between CourseUserGroup and CohortMembership. To be run after migration 0006.
    """
    help = '''
    Repairs any potential inconsistencies made in the window between running migrations 0005 and 0006, and deploying
    the code changes to enforce use of CohortMembership that go with said migrations.
    |commit|: optional argument. If not provided, will dry-run and list number of operations that would be made.
    '''

    def handle(self, *args, **options):
        """
        Execute the command. Since this is designed to fix any issues cause by running pre-CohortMembership code
        with the database already migrated to post-CohortMembership state, we will use the pre-CohortMembership
        table CourseUserGroup as the canonical source of truth. This way, changes made in the window are persisted.
        """
        commit = 'commit' in options
        memberships_to_delete = 0
        memberships_to_add = 0

        # Begin by removing any data in CohortMemberships that does not match CourseUserGroups data
        for membership in CohortMembership.objects.all():
            try:
                CourseUserGroup.objects.get(
                    group_type=CourseUserGroup.COHORT,
                    users__id=membership.user.id,
                    course_id=membership.course_id,
                    id=membership.course_user_group.id
                )
            except CourseUserGroup.DoesNotExist:
                memberships_to_delete += 1
                if commit:
                    membership.delete()

        # Now we can add any CourseUserGroup data that is missing a backing CohortMembership
        for course_group in CourseUserGroup.objects.filter(group_type=CourseUserGroup.COHORT):
            for user in course_group.users.all():
                try:
                    CohortMembership.objects.get(
                        user=user,
                        course_id=course_group.course_id,
                        course_user_group_id=course_group.id
                    )
                except CohortMembership.DoesNotExist:
                    memberships_to_add += 1
                    if commit:
                        membership = CohortMembership(
                            course_user_group=course_group,
                            user=user,
                            course_id=course_group.course_id
                        )
                        try:
                            membership.save()
                        except IntegrityError:  # If the user is in multiple cohorts, we arbitrarily choose between them
                            # In this case, allow the pre-existing entry to be "correct"
                            course_group.users.remove(user)
                            user.course_groups.remove(course_group)

        print '{} CohortMemberships did not match the CourseUserGroup table and will be deleted'.format(
            memberships_to_delete
        )
        print '{} CourseUserGroup users do not have a CohortMembership; one will be added if it is valid'.format(
            memberships_to_add
        )
        if commit:
            print 'Changes have been made and saved.'
        else:
            print 'Dry run, changes have not been saved. Run again with "commit" argument to save changes'
<commit_msg>Update post_cohort_management_fix to Django 1.8<commit_after>"""
Intended to fix any inconsistencies that may arise during the rollout of the CohortMembership model.
Illustration: https://gist.github.com/efischer19/d62f8ee42b7fbfbc6c9a
"""
from django.core.management.base import BaseCommand
from django.db import IntegrityError

from openedx.core.djangoapps.course_groups.models import CourseUserGroup, CohortMembership

class Command(BaseCommand):
    """
    Repair any inconsistencies between CourseUserGroup and CohortMembership. To be run after migration 0006.
    """
    help = '''
    Repairs any potential inconsistencies made in the window between running migrations 0005 and 0006, and deploying
    the code changes to enforce use of CohortMembership that go with said migrations.

    commit: optional argument. If not provided, will dry-run and list number of operations that would be made.
    '''

    def add_arguments(self, parser):
        """
        Add arguments to the command parser.
        """
        parser.add_argument(
            '--commit',
            action='store_true',
            dest='commit',
            default=False,
            help='Really commit the changes, otherwise, just dry run',
        )

    def handle(self, *args, **options):
        """
        Execute the command. Since this is designed to fix any issues cause by running pre-CohortMembership code
        with the database already migrated to post-CohortMembership state, we will use the pre-CohortMembership
        table CourseUserGroup as the canonical source of truth. This way, changes made in the window are persisted.
        """
        commit = options['commit']
        memberships_to_delete = 0
        memberships_to_add = 0

        # Begin by removing any data in CohortMemberships that does not match CourseUserGroups data
        for membership in CohortMembership.objects.all():
            try:
                CourseUserGroup.objects.get(
                    group_type=CourseUserGroup.COHORT,
                    users__id=membership.user.id,
                    course_id=membership.course_id,
                    id=membership.course_user_group.id
                )
            except CourseUserGroup.DoesNotExist:
                memberships_to_delete += 1
                if commit:
                    membership.delete()

        # Now we can add any CourseUserGroup data that is missing a backing CohortMembership
        for course_group in CourseUserGroup.objects.filter(group_type=CourseUserGroup.COHORT):
            for user in course_group.users.all():
                try:
                    CohortMembership.objects.get(
                        user=user,
                        course_id=course_group.course_id,
                        course_user_group_id=course_group.id
                    )
                except CohortMembership.DoesNotExist:
                    memberships_to_add += 1
                    if commit:
                        membership = CohortMembership(
                            course_user_group=course_group,
                            user=user,
                            course_id=course_group.course_id
                        )
                        try:
                            membership.save()
                        except IntegrityError:  # If the user is in multiple cohorts, we arbitrarily choose between them
                            # In this case, allow the pre-existing entry to be "correct"
                            course_group.users.remove(user)
                            user.course_groups.remove(course_group)

        print '{} CohortMemberships did not match the CourseUserGroup table and will be deleted'.format(
            memberships_to_delete
        )
        print '{} CourseUserGroup users do not have a CohortMembership; one will be added if it is valid'.format(
            memberships_to_add
        )
        if commit:
            print 'Changes have been made and saved.'
        else:
            print 'Dry run, changes have not been saved. Run again with "commit" argument to save changes'
<|endoftext|>


<commit_before>import hashlib
import hmac

from flask import (
    Blueprint,
    render_template,
    flash,
    redirect,
    url_for,
    abort,
    jsonify,
    request,
    current_app
)

from flask.ext.security import login_required
from flask.ext.login import current_user
from flask.ext.mongoengine import DoesNotExist

from application.models import (
    LogEntry,
    Tag,
    User
)

from application.mylog.forms import LogEntryForm

mylog = Blueprint('mylog', __name__, template_folder='templates')

@mylog.route('/my-log')
@login_required
def view_mylog():
    owner = current_user._get_current_object()
    filtered = False
    if request.args.get('tag'):
        tag = Tag.objects.filter(name__iexact=request.args.get('tag'), owner=owner).first()
        log_entries = LogEntry.objects.filter(owner=owner, tags__in=[tag]).all()
        filtered = True
    else:
        log_entries = LogEntry.objects.filter(owner=owner).all()

    tags = Tag.objects.filter(owner=owner).all()
    return render_template('mylog/log.html', log_entries=log_entries, tags=tags, filtered=filtered)

@mylog.route('/my-log/entry', methods=['GET', 'POST'])
@login_required
def add_log_entry():
    form = LogEntryForm()
    if form.validate_on_submit():
        entry = LogEntry(content=form.content.data)
        entry.owner = current_user._get_current_object()
        entry.save()
        if form.tags.data:
            tags = form.tags.data.split(',')
            for tag in tags:
                entry.add_tag(tag.strip())
        flash('Entry saved')
        return redirect(url_for('mylog.view_mylog'))
    return render_template('mylog/add-entry.html', form=form)

@mylog.route('/my-log/entry/<id>', methods=['GET', 'POST'])
@login_required
def view_log_entry(id):
    entry = LogEntry.objects(id=id)
    if not entry:
        abort(404)
    entry = entry.get()
    if request.method == 'GET':
        return render_template('mylog/entry.html', entry=entry)
    else:
        content = request.form['content']
        tags = request.form['tags']
        if tags:
            tags = tags.split(',')
            for tag in tags:
                entry.add_tag(tag)
        entry.content = content
        entry.save()
        entry = LogEntry.objects(id=id).get()
        flash('entry updated')
        return render_template('mylog/entry.html', entry=entry)

@mylog.route('/my-log/entry/<id>/tags', methods=['GET', 'POST'])
@login_required
def tag_entry(id):
    entry = LogEntry.objects(id=id).get()
    if not entry:
        abort(404)
    if request.method == 'GET':
        tags = [tag.name for tag in entry.tags]
        return jsonify({"tags": tags})
    else:
        tag_name = request.json.get('tag')
        entry.add_tag(tag_name)
        entry.save()
        return 'OK', 200

@mylog.route('/my-log/tags.json')
@login_required
def find_tags():
    tag_name = request.args.get('tag-name')
    owner = current_user._get_current_object()
    if tag_name:
        tags = Tag.objects.filter(name__istartswith=tag_name, owner=owner).all()
    else:
        tags = Tag.objects.filter(owner=owner).all()
    return jsonify({"tags": tags})

#TODO verify request is from mailgun!
@mylog.route('/my-log/inbox', methods=['POST'])
def inbox():
    if not _verified(request):
        # just ignore and move along
        current_app.logger.info('Unverfied request')
        return 'OK', 200
    else:
        _send_to_mylog(request)
    return 'OK', 200

def _verified(req):
    token = req.form.get('token')
    timestamp = req.form.get('timestamp')
    signature = req.form.get('signature')
    if None in (token, timestamp, signature):
        return False
    key = current_app.config['MAILGUN_API_KEY'].encode('utf-8')
    return signature == hmac.new(key=key,
                                 msg='{}{}'.format(timestamp, token),
                                 digestmod=hashlib.sha256).hexdigest()

def _send_to_mylog(req):
    sender = request.form.get('sender')
    recipient = request.form.get('recipient')
    subject = request.form.get('subject', '')
    body = request.form.get('body-plain', '')

    current_app.logger.info('Inbound email')
    current_app.logger.info(sender)
    current_app.logger.info(recipient)
    current_app.logger.info(subject)
    current_app.logger.info(body)
    current_app.logger.info('End inbound email')

    try:
        user = User.objects.filter(_inbox_email=recipient).get()
        log_entry = LogEntry(owner=user)
        sender = "From: %s" % sender
        content = '\n'.join([subject, body, sender])
        log_entry.content = content
        log_entry.save()
        log_entry.add_tag('Email')
    except DoesNotExist:
        # log and raise so we get sentry notification
        current_app.logger.error('No inbox email:' + recipient)
        raise

<commit_msg>grasp one more straw<commit_after>import hashlib
import hmac

from flask import (
    Blueprint,
    render_template,
    flash,
    redirect,
    url_for,
    abort,
    jsonify,
    request,
    current_app
)

from flask.ext.security import login_required
from flask.ext.login import current_user
from flask.ext.mongoengine import DoesNotExist

from application.models import (
    LogEntry,
    Tag,
    User
)

from application.mylog.forms import LogEntryForm

mylog = Blueprint('mylog', __name__, template_folder='templates')

@mylog.route('/my-log')
@login_required
def view_mylog():
    owner = current_user._get_current_object()
    filtered = False
    if request.args.get('tag'):
        tag = Tag.objects.filter(name__iexact=request.args.get('tag'), owner=owner).first()
        log_entries = LogEntry.objects.filter(owner=owner, tags__in=[tag]).all()
        filtered = True
    else:
        log_entries = LogEntry.objects.filter(owner=owner).all()

    tags = Tag.objects.filter(owner=owner).all()
    return render_template('mylog/log.html', log_entries=log_entries, tags=tags, filtered=filtered)

@mylog.route('/my-log/entry', methods=['GET', 'POST'])
@login_required
def add_log_entry():
    form = LogEntryForm()
    if form.validate_on_submit():
        entry = LogEntry(content=form.content.data)
        entry.owner = current_user._get_current_object()
        entry.save()
        if form.tags.data:
            tags = form.tags.data.split(',')
            for tag in tags:
                entry.add_tag(tag.strip())
        flash('Entry saved')
        return redirect(url_for('mylog.view_mylog'))
    return render_template('mylog/add-entry.html', form=form)

@mylog.route('/my-log/entry/<id>', methods=['GET', 'POST'])
@login_required
def view_log_entry(id):
    entry = LogEntry.objects(id=id)
    if not entry:
        abort(404)
    entry = entry.get()
    if request.method == 'GET':
        return render_template('mylog/entry.html', entry=entry)
    else:
        content = request.form['content']
        tags = request.form['tags']
        if tags:
            tags = tags.split(',')
            for tag in tags:
                entry.add_tag(tag)
        entry.content = content
        entry.save()
        entry = LogEntry.objects(id=id).get()
        flash('entry updated')
        return render_template('mylog/entry.html', entry=entry)

@mylog.route('/my-log/entry/<id>/tags', methods=['GET', 'POST'])
@login_required
def tag_entry(id):
    entry = LogEntry.objects(id=id).get()
    if not entry:
        abort(404)
    if request.method == 'GET':
        tags = [tag.name for tag in entry.tags]
        return jsonify({"tags": tags})
    else:
        tag_name = request.json.get('tag')
        entry.add_tag(tag_name)
        entry.save()
        return 'OK', 200

@mylog.route('/my-log/tags.json')
@login_required
def find_tags():
    tag_name = request.args.get('tag-name')
    owner = current_user._get_current_object()
    if tag_name:
        tags = Tag.objects.filter(name__istartswith=tag_name, owner=owner).all()
    else:
        tags = Tag.objects.filter(owner=owner).all()
    return jsonify({"tags": tags})

#TODO verify request is from mailgun!
@mylog.route('/my-log/inbox', methods=['POST'])
def inbox():
    if not _verified(request):
        # just ignore and move along
        current_app.logger.info('Unverfied request')
        return 'OK', 200
    else:
        _send_to_mylog(request)
    return 'OK', 200

def _verified(req):
    token = req.form.get('token')
    timestamp = req.form.get('timestamp')
    signature = req.form.get('signature')
    if None in (token, timestamp, signature):
        return False
    key = current_app.config['MAILGUN_API_KEY'].encode('utf-8')
    msg = '{}{}'.format(timestamp, token).encode('utf-8')
    return signature == hmac.new(key=key,
                                 msg=msg,
                                 digestmod=hashlib.sha256).hexdigest()

def _send_to_mylog(req):
    sender = request.form.get('sender')
    recipient = request.form.get('recipient')
    subject = request.form.get('subject', '')
    body = request.form.get('body-plain', '')

    current_app.logger.info('Inbound email')
    current_app.logger.info(sender)
    current_app.logger.info(recipient)
    current_app.logger.info(subject)
    current_app.logger.info(body)
    current_app.logger.info('End inbound email')

    try:
        user = User.objects.filter(_inbox_email=recipient).get()
        log_entry = LogEntry(owner=user)
        sender = "From: %s" % sender
        content = '\n'.join([subject, body, sender])
        log_entry.content = content
        log_entry.save()
        log_entry.add_tag('Email')
    except DoesNotExist:
        # log and raise so we get sentry notification
        current_app.logger.error('No inbox email:' + recipient)
        raise

<|endoftext|>


<commit_before>import re

# TODO: make configurable
MAXLINE = 2 ** 19

def _cut(s, to=MAXLINE):
    return s[:to]

class _callable_staticmethod(staticmethod):

    def __call__(self, *args, **kwargs):
        return self.__func__(*args, **kwargs)

def advancer(regex, flags=0):
    r = re.compile(regex, flags)

    @_callable_staticmethod
    def advance(string, matchonly=False):
        m = r.match(string)
        if matchonly:
            return m
        if m:
            return string[m.end():], m
        return string, None

    return advance

# RFC 2616 p.17
CLRF = '\r\n'
LWS = CLRF + ' \t'
# <any US-ASCII control character (octets 0 - 31) and DEL (127)>
CTL = ''.join(chr(i) for i in xrange(0, 32)) + chr(127)

SEPARATORS = r'()<>@,;:\"/[]?={} \t'
TOKEN_EXCLUDE = ''.join(set(CTL) | set(SEPARATORS))

# <any OCTET except CTLs, but including LWS>
TEXT_EXCLUDE = ''.join(set(CTL) - set(LWS))

# this *should* be CLRF but not everything uses that as its delineator
# TODO: do we have to be able to recognize just carriage returns?
DELINEATOR = '(?:(?:\r\n)|\n)'
HAS_LINE_END = advancer('.*?' + DELINEATOR, re.DOTALL)
HAS_HEADERS_END = advancer('.*?' + (DELINEATOR * 2), re.DOTALL)
IS_LINE_END = advancer(DELINEATOR, re.DOTALL)
IS_HEADERS_END = advancer((DELINEATOR * 2), re.DOTALL)

def istext(t):
    return t.translate('', '', TEXT_EXCLUDE) == t
<commit_msg>minor improvement to _cut. is this just meant for strings in error messages?<commit_after>import re

# TODO: make configurable
MAXLINE = 2 ** 19

def _cut(s, to=MAXLINE):
    if len(s) <= to:
        return s
    return s[:to]

class _callable_staticmethod(staticmethod):

    def __call__(self, *args, **kwargs):
        return self.__func__(*args, **kwargs)

def advancer(regex, flags=0):
    r = re.compile(regex, flags)

    @_callable_staticmethod
    def advance(string, matchonly=False):
        m = r.match(string)
        if matchonly:
            return m
        if m:
            return string[m.end():], m
        return string, None

    return advance

# RFC 2616 p.17
CLRF = '\r\n'
LWS = CLRF + ' \t'
# <any US-ASCII control character (octets 0 - 31) and DEL (127)>
CTL = ''.join(chr(i) for i in xrange(0, 32)) + chr(127)

SEPARATORS = r'()<>@,;:\"/[]?={} \t'
TOKEN_EXCLUDE = ''.join(set(CTL) | set(SEPARATORS))

# <any OCTET except CTLs, but including LWS>
TEXT_EXCLUDE = ''.join(set(CTL) - set(LWS))

# this *should* be CLRF but not everything uses that as its delineator
# TODO: do we have to be able to recognize just carriage returns?
DELINEATOR = '(?:(?:\r\n)|\n)'
HAS_LINE_END = advancer('.*?' + DELINEATOR, re.DOTALL)
HAS_HEADERS_END = advancer('.*?' + (DELINEATOR * 2), re.DOTALL)
IS_LINE_END = advancer(DELINEATOR, re.DOTALL)
IS_HEADERS_END = advancer((DELINEATOR * 2), re.DOTALL)

def istext(t):
    return t.translate('', '', TEXT_EXCLUDE) == t
<|endoftext|>