<commit_before># python -m unittest boggle

import copy
import unittest

# TODO does this handle Qu?
# TODO always lowercase
# TODO travis
# TODO replace letter with tile

def get_positions(letter, board):
    """
    Return a list of positions a letter can be found on a board.

    letter: A letter on a tile.
    return: List of (column, row) co-ordinates of tiles containing this letter.
    """
    positions = []
    for row_index, row in enumerate(board):
        for column_index, piece in enumerate(row):
            # TODO direct test for this
            if piece[0] == letter[0]:
                positions.append((column_index, row_index))
    return positions

def positions_touching(first, second):
    """
    Given two tile positions, check whether they are touching.

    first: Tuple of co-ordinates of a tile.
    second: Tuple of co-ordinates of a tile.

    return: Bool, true iff the tiles are touching - immediately above, below
        or diagonal.
    """
    return abs(first[0] - second[0]) <= 1 and abs(first[1] - second[1]) <= 1

def get_routes(word, board):
    """
    Get available routes to make a word in a board.

    A route is a path of positions from first tile to next, to next... until
    the last tile. It cannot include the same tile multiple times.

    word: A string.
    board: A list of lists of tiles. Each list in the list of lists represents
        a row of a Boggle board.

    returns: List of lists of tile positions.
    """
    routes = []

    for letter in word:
        positions = get_positions(letter, board)
        if not len(routes):
            new_routes = [[position] for position in positions]
        else:
            new_routes = []

            for route in routes:
                for position in positions:
                    if positions_touching(route[len(route) - 1], position):
                        new_route = copy.copy(route)
                        new_route.append(position)
                        new_routes.append(new_route)

        routes = copy.copy(new_routes)

    valid_routes = []
    for route in routes:
        no_duplicates = len(set(route)) == len(route)
        includes_whole_word = len(route) == len(word)
        if no_duplicates and includes_whole_word:
            valid_routes.append(route)

    return valid_routes

def list_words(board, dictionary):
    """
    Return all words from a given dictionary which are in a board.

    dictionary: A set of valid words.
    board: A list of lists of tiles. Each list in the list of lists represents
        a row of a Boggle board.

    returns: A set of strings.
    """
    word_list = set()
    for word in dictionary:
        word = word.upper()
        routes = get_routes(word.replace('QU', 'Q'), board)
        if len(routes) and len(word) > 2:
            word_list.add(word)
    return word_list

class GetRoutesTests(unittest.TestCase):
    """
    Tests for `get_routes`.
    """

    def test_route(self):
        """
        A list of lists positions between the first and last letter is
        returned.
        """
        self.assertEqual(
            [
                [(0, 0), (1, 0), (2, 0)],
            ],
            get_routes(
                word='ABC',
                board=[
                    ['A', 'B', 'C'],
                ],
            )
        )

    def test_not_in_board(self):
        """
        If a word is not available in the board, an empty list is returned.
        """
        self.assertEqual(
            [],
            get_routes(
                word='ABC',
                board=[
                    ['D', 'E', 'F'],
                ]
            )
        )

    def test_cannot_reuse_tile(self):
        """
        The same tile cannot be reused.
        """
        self.assertEqual(
            [],
            get_routes(
                word='ABA',
                board=[
                    ['A', 'B'],
                ],
            )
        )

    def test_all_letters_necessary(self):
        """
        A route does not exist if not all letters are available.
        """
        self.assertEqual(
            [],
            get_routes(
                word='ABCD',
                board=[
                    ['A', 'C', 'D'],
                ],
            )
        )

class ListWordsTests(unittest.TestCase):
    """
    Tests for `list_words`.
    """
    def test_list_words(self):
        """
        A set of available words is returned.
        """
        self.assertEqual(
            set(['ABC', 'DEF']),
            list_words(
                dictionary=set(['ABC', 'DEF', 'GHI']),
                board=[
                    ['A', 'B', 'C'],
                    ['D', 'E', 'F'],
                ],
            )
        )

    def test_short_word_ignored(self):
        """
        Only words of 3 or more letters are returned.
        """
        self.assertEqual(
            set(),
            list_words(
                dictionary=set(['AB']),
                board=[
                    ['A', 'B'],
                ],
            )
        )

    def test_q_u_together(self):
        """
        Q and U are on the same tile.
        """
        self.assertEqual(
            set(['QUA']),
            list_words(
                dictionary=set(['QUA']),
                board=[
                    ['QU', 'A'],
                ],
            )
        )

class GetPositionsTests(unittest.TestCase):
    """
    Tests for get_positions.
    """

    def test_get_positions(self):
        """
        A list of position tuples
        """
        self.assertEqual(
            [(0, 0), (2, 0), (0, 1)],
            get_positions(
                letter='A',
                board=[
                    ['A', 'X', 'A', 'X', 'X'],
                    ['A', 'X', 'X', 'X', 'X'],
                ],
            )
        )

class PositionsTouchingTests(unittest.TestCase):
    """
    Tests for `positions_touching`.
    """

    def test_touching(self):
        """
        If tiles are touching, positions_touching returns True.
        """
        self.assertTrue(
            all([
                    # Second on right on first.
                    positions_touching(first=(1, 0), second=(0, 0)),
                    # Second on left of first.
                    positions_touching(first=(1, 0), second=(0, 0)),
                    # Second above first.
                    positions_touching(first=(0, 1), second=(0, 0)),
                    # Second below first.
                    positions_touching(first=(0, 0), second=(0, 1)),
                ]
            ))

    def test_not_touching(self):
        """
        If tiles are not touching, positions_touching returns False.
        """
        self.assertFalse(positions_touching(first=(0, 0), second=(0, 2)))

if __name__ == "__main__":
    with open("english_words.txt") as word_file:
        english_words = set(word.strip() for word in word_file)
    found_words = list_words(
        dictionary=english_words,
        board=[
            ['Qu', 'A', 'A', 'M', 'D'],
            ['A', 'L', 'G', 'O', 'O'],
            ['R', 'G', 'I', 'D', 'E'],
            ['O', 'N', 'F', 'Y', 'R'],
            ['R', 'E', 'L', 'L', 'S'],
        ],
    )
    print len(found_words)
    from pprint import pprint
    pprint(sorted(list(found_words)))<commit_msg>Tests for case insensitive first letter comparison<commit_after># python -m unittest boggle

import copy
import unittest

# TODO travis

def get_positions(letter, board):
    """
    Return a list of positions a letter can be found on a board.

    letter: A letter on a tile.
    return: List of (column, row) co-ordinates of tiles containing this letter.
    """
    positions = []
    for row_index, row in enumerate(board):
        for column_index, piece in enumerate(row):
            if piece[0].upper() == letter[0].upper():
                positions.append((column_index, row_index))
    return positions

def positions_touching(first, second):
    """
    Given two tile positions, check whether they are touching.

    first: Tuple of co-ordinates of a tile.
    second: Tuple of co-ordinates of a tile.

    return: Bool, true iff the tiles are touching - immediately above, below
        or diagonal.
    """
    return abs(first[0] - second[0]) <= 1 and abs(first[1] - second[1]) <= 1

def get_routes(word, board):
    """
    Get available routes to make a word in a board.

    A route is a path of positions from first tile to next, to next... until
    the last tile. It cannot include the same tile multiple times.

    word: A string.
    board: A list of lists of tiles. Each list in the list of lists represents
        a row of a Boggle board.

    returns: List of lists of tile positions.
    """
    routes = []

    for letter in word:
        positions = get_positions(letter, board)
        if not len(routes):
            new_routes = [[position] for position in positions]
        else:
            new_routes = []

            for route in routes:
                for position in positions:
                    if positions_touching(route[len(route) - 1], position):
                        new_route = copy.copy(route)
                        new_route.append(position)
                        new_routes.append(new_route)

        routes = copy.copy(new_routes)

    valid_routes = []
    for route in routes:
        no_duplicates = len(set(route)) == len(route)
        includes_whole_word = len(route) == len(word)
        if no_duplicates and includes_whole_word:
            valid_routes.append(route)

    return valid_routes

def list_words(board, dictionary):
    """
    Return all words from a given dictionary which are in a board.

    dictionary: A set of valid words.
    board: A list of lists of tiles. Each list in the list of lists represents
        a row of a Boggle board.

    returns: A set of strings.
    """
    word_list = set()
    for word in dictionary:
        word = word.upper()
        routes = get_routes(word.replace('QU', 'Q'), board)
        if len(routes) and len(word) > 2:
            word_list.add(word)
    return word_list

class GetRoutesTests(unittest.TestCase):
    """
    Tests for `get_routes`.
    """

    def test_route(self):
        """
        A list of lists positions between the first and last letter is
        returned.
        """
        self.assertEqual(
            [
                [(0, 0), (1, 0), (2, 0)],
            ],
            get_routes(
                word='ABC',
                board=[
                    ['A', 'B', 'C'],
                ],
            )
        )

    def test_not_in_board(self):
        """
        If a word is not available in the board, an empty list is returned.
        """
        self.assertEqual(
            [],
            get_routes(
                word='ABC',
                board=[
                    ['D', 'E', 'F'],
                ]
            )
        )

    def test_cannot_reuse_tile(self):
        """
        The same tile cannot be reused.
        """
        self.assertEqual(
            [],
            get_routes(
                word='ABA',
                board=[
                    ['A', 'B'],
                ],
            )
        )

    def test_all_letters_necessary(self):
        """
        A route does not exist if not all letters are available.
        """
        self.assertEqual(
            [],
            get_routes(
                word='ABCD',
                board=[
                    ['A', 'C', 'D'],
                ],
            )
        )

class ListWordsTests(unittest.TestCase):
    """
    Tests for `list_words`.
    """
    def test_list_words(self):
        """
        A set of available words is returned.
        """
        self.assertEqual(
            set(['ABC', 'DEF']),
            list_words(
                dictionary=set(['ABC', 'DEF', 'GHI']),
                board=[
                    ['A', 'B', 'C'],
                    ['D', 'E', 'F'],
                ],
            )
        )

    def test_short_word_ignored(self):
        """
        Only words of 3 or more letters are returned.
        """
        self.assertEqual(
            set(),
            list_words(
                dictionary=set(['AB']),
                board=[
                    ['A', 'B'],
                ],
            )
        )

    def test_q_u_together(self):
        """
        Q and u are on the same tile.
        """
        self.assertEqual(
            set(['QUA']),
            list_words(
                dictionary=set(['QUA']),
                board=[
                    ['Qu', 'A'],
                ],
            )
        )

    def test_case_insensitive_dictionary(self):
        """
        Listing words is case insensitive to dictionary case.
        """
        self.assertEqual(
            set(['ABC']),
            list_words(
                dictionary=set(['AbC']),
                board=[
                    ['A', 'B', 'C'],
                ],
            )
        )

    def test_case_insensitive_board(self):
        """
        Listing words is case insensitive to board case.
        """
        self.assertEqual(
            set(['ABC']),
            list_words(
                dictionary=set(['ABC']),
                board=[
                    ['A', 'B', 'c'],
                ],
            )
        )

class GetPositionsTests(unittest.TestCase):
    """
    Tests for get_positions.
    """

    def test_get_positions(self):
        """
        A list of position tuples
        """
        self.assertEqual(
            [(0, 0), (2, 0), (0, 1)],
            get_positions(
                letter='A',
                board=[
                    ['A', 'X', 'A', 'X', 'X'],
                    ['A', 'X', 'X', 'X', 'X'],
                ],
            )
        )

    def test_case_insensitive(self):
        """
        The case of the letter does not matter.
        """
        self.assertEqual(
            [(0, 0), (0, 1)],
            get_positions(
                letter='a',
                board=[
                    ['a'],
                    ['A'],
                ],
            )
        )

    def test_first_letter_only(self):
        """
        Only the first letter is compared. This is to handle the "Qu" tile.
        """
        self.assertEqual(
            [(0, 0)],
            get_positions(
                letter='AB',
                board=[
                    ['AC'],
                ],
            )
        )

class PositionsTouchingTests(unittest.TestCase):
    """
    Tests for `positions_touching`.
    """

    def test_touching(self):
        """
        If tiles are touching, positions_touching returns True.
        """
        self.assertTrue(
            all([
                    # Second on right on first.
                    positions_touching(first=(1, 0), second=(0, 0)),
                    # Second on left of first.
                    positions_touching(first=(1, 0), second=(0, 0)),
                    # Second above first.
                    positions_touching(first=(0, 1), second=(0, 0)),
                    # Second below first.
                    positions_touching(first=(0, 0), second=(0, 1)),
                ]
            ))

    def test_not_touching(self):
        """
        If tiles are not touching, positions_touching returns False.
        """
        self.assertFalse(positions_touching(first=(0, 0), second=(0, 2)))

if __name__ == "__main__":
    with open("english_words.txt") as word_file:
        english_words = set(word.strip() for word in word_file)
    found_words = list_words(
        dictionary=english_words,
        board=[
            ['Qu', 'A', 'A', 'M', 'D'],
            ['A', 'L', 'G', 'O', 'O'],
            ['R', 'G', 'I', 'D', 'E'],
            ['O', 'N', 'F', 'Y', 'R'],
            ['R', 'E', 'L', 'L', 'S'],
        ],
    )
    print len(found_words)
    from pprint import pprint
    pprint(sorted(list(found_words)))<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

"""
envoy.core
~~~~~~~~~~

This module provides envoy awesomeness.
"""

import os
import sys
import shlex
import signal
import subprocess
import threading
import traceback

__version__ = '0.0.2'
__license__ = 'MIT'
__author__ = 'Kenneth Reitz'

def _terminate_process(process):
    if sys.platform == 'win32':
        import ctypes
        PROCESS_TERMINATE = 1
        handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, process.pid)
        ctypes.windll.kernel32.TerminateProcess(handle, -1)
        ctypes.windll.kernel32.CloseHandle(handle)
    else:
        os.kill(process.pid, signal.SIGTERM)

def _kill_process(process):
    if sys.platform == 'win32':
        _terminate_process(process)
    else:
        os.kill(process.pid, signal.SIGKILL)

def _is_alive(thread):
    if hasattr(thread, "is_alive"):
        return thread.is_alive()
    else:
        return thread.isAlive()

class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None
        self.out = None
        self.err = None
        self.returncode = None
        self.data = None
        self.exc = None

    def run(self, data, timeout, kill_timeout, env, cwd):
        self.data = data
        environ = dict(os.environ)
        environ.update(env or {})

        def target():

            try:
                self.process = subprocess.Popen(self.cmd,
                    universal_newlines=True,
                    shell=False,
                    env=environ,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    bufsize=0,
                    cwd=cwd,
                )

                if sys.version_info[0] >= 3:
                    self.out, self.err = self.process.communicate(
                        input = bytes(self.data, "UTF-8") if self.data else None
                    )
                else:
                    self.out, self.err = self.process.communicate(self.data)
            except Exception as exc:
                self.exc = exc

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if self.exc:
            raise self.exc
        if _is_alive(thread) :
            _terminate_process(self.process)
            thread.join(kill_timeout)
            if _is_alive(thread):
                _kill_process(self.process)
                thread.join()
        self.returncode = self.process.returncode
        return self.out, self.err

class ConnectedCommand(object):
    def __init__(self,
        process=None,
        std_in=None,
        std_out=None,
        std_err=None):

        self._process = process
        self.std_in = std_in
        self.std_out = std_out
        self.std_err = std_out
        self._status_code = None

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.kill()

    @property
    def status_code(self):
        """The status code of the process.
        If the code is None, assume that it's still running.
        """
        return self._status_code

    @property
    def pid(self):
        """The process' PID."""
        return self._process.pid

    def kill(self):
        """Kills the process."""
        return self._process.kill()

    def expect(self, bytes, stream=None):
        """Block until given bytes appear in the stream."""
        if stream is None:
            stream = self.std_out

    def send(self, str, end='\n'):
        """Sends a line to std_in."""
        return self._process.stdin.write(str+end)

    def block(self):
        """Blocks until command finishes. Returns Response instance."""
        self._status_code = self._process.wait()

class Response(object):
    """A command's response"""

    def __init__(self, process=None):
        super(Response, self).__init__()

        self._process = process
        self.command = None
        self.std_err = None
        self.std_out = None
        self.status_code = None
        self.history = []

    def __repr__(self):
        if len(self.command):
            return '<Response [{0}]>'.format(self.command[0])
        else:
            return '<Response>'

def expand_args(command):
    """Parses command strings and returns a Popen-ready list."""

    # Prepare arguments.
    if isinstance(command, str):
        splitter = shlex.shlex(command)
        splitter.whitespace = '|'
        splitter.whitespace_split = True
        command = []

        while True:
            token = splitter.get_token()
            if token:
                command.append(token)
            else:
                break

        command = list(map(shlex.split, command))

    return command

def run(command, data=None, timeout=None, kill_timeout=None, env=None, cwd=None):
    """Executes a given commmand and returns Response.

    Blocks until process is complete, or timeout is reached.
    """

    command = expand_args(command)

    history = []
    for c in command:

        if len(history):
            # due to broken pipe problems pass only first 10 KiB
            data = history[-1].std_out[0:10*1024]

        cmd = Command(c)
        try:
            out, err = cmd.run(data, timeout, kill_timeout, env, cwd)
            status_code = cmd.returncode
        except OSError as e:
            out, err = '', u"\n".join([e.strerror, traceback.format_exc()])
            status_code = 127

        r = Response(process=cmd)

        r.command = c
        r.std_out = out
        r.std_err = err
        r.status_code = status_code

        history.append(r)

    r = history.pop()
    r.history = history

    return r

def connect(command, data=None, env=None, cwd=None):
    """Spawns a new process from the given command."""

    # TODO: support piped commands
    command_str = expand_args(command).pop()
    environ = dict(os.environ)
    environ.update(env or {})

    process = subprocess.Popen(command_str,
        universal_newlines=True,
        shell=False,
        env=environ,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        bufsize=0,
        cwd=cwd,
    )

    return ConnectedCommand(process=process)
<commit_msg>v0.0.3<commit_after># -*- coding: utf-8 -*-

"""
envoy.core
~~~~~~~~~~

This module provides envoy awesomeness.
"""

import os
import sys
import shlex
import signal
import subprocess
import threading
import traceback

__version__ = '0.0.3'
__license__ = 'MIT'
__author__ = 'Kenneth Reitz'

def _terminate_process(process):
    if sys.platform == 'win32':
        import ctypes
        PROCESS_TERMINATE = 1
        handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, process.pid)
        ctypes.windll.kernel32.TerminateProcess(handle, -1)
        ctypes.windll.kernel32.CloseHandle(handle)
    else:
        os.kill(process.pid, signal.SIGTERM)

def _kill_process(process):
    if sys.platform == 'win32':
        _terminate_process(process)
    else:
        os.kill(process.pid, signal.SIGKILL)

def _is_alive(thread):
    if hasattr(thread, "is_alive"):
        return thread.is_alive()
    else:
        return thread.isAlive()

class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None
        self.out = None
        self.err = None
        self.returncode = None
        self.data = None
        self.exc = None

    def run(self, data, timeout, kill_timeout, env, cwd):
        self.data = data
        environ = dict(os.environ)
        environ.update(env or {})

        def target():

            try:
                self.process = subprocess.Popen(self.cmd,
                    universal_newlines=True,
                    shell=False,
                    env=environ,
                    stdin=subprocess.PIPE,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    bufsize=0,
                    cwd=cwd,
                )

                if sys.version_info[0] >= 3:
                    self.out, self.err = self.process.communicate(
                        input = bytes(self.data, "UTF-8") if self.data else None
                    )
                else:
                    self.out, self.err = self.process.communicate(self.data)
            except Exception as exc:
                self.exc = exc

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if self.exc:
            raise self.exc
        if _is_alive(thread) :
            _terminate_process(self.process)
            thread.join(kill_timeout)
            if _is_alive(thread):
                _kill_process(self.process)
                thread.join()
        self.returncode = self.process.returncode
        return self.out, self.err

class ConnectedCommand(object):
    def __init__(self,
        process=None,
        std_in=None,
        std_out=None,
        std_err=None):

        self._process = process
        self.std_in = std_in
        self.std_out = std_out
        self.std_err = std_out
        self._status_code = None

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.kill()

    @property
    def status_code(self):
        """The status code of the process.
        If the code is None, assume that it's still running.
        """
        return self._status_code

    @property
    def pid(self):
        """The process' PID."""
        return self._process.pid

    def kill(self):
        """Kills the process."""
        return self._process.kill()

    def expect(self, bytes, stream=None):
        """Block until given bytes appear in the stream."""
        if stream is None:
            stream = self.std_out

    def send(self, str, end='\n'):
        """Sends a line to std_in."""
        return self._process.stdin.write(str+end)

    def block(self):
        """Blocks until command finishes. Returns Response instance."""
        self._status_code = self._process.wait()

class Response(object):
    """A command's response"""

    def __init__(self, process=None):
        super(Response, self).__init__()

        self._process = process
        self.command = None
        self.std_err = None
        self.std_out = None
        self.status_code = None
        self.history = []

    def __repr__(self):
        if len(self.command):
            return '<Response [{0}]>'.format(self.command[0])
        else:
            return '<Response>'

def expand_args(command):
    """Parses command strings and returns a Popen-ready list."""

    # Prepare arguments.
    if isinstance(command, str):
        splitter = shlex.shlex(command)
        splitter.whitespace = '|'
        splitter.whitespace_split = True
        command = []

        while True:
            token = splitter.get_token()
            if token:
                command.append(token)
            else:
                break

        command = list(map(shlex.split, command))

    return command

def run(command, data=None, timeout=None, kill_timeout=None, env=None, cwd=None):
    """Executes a given commmand and returns Response.

    Blocks until process is complete, or timeout is reached.
    """

    command = expand_args(command)

    history = []
    for c in command:

        if len(history):
            # due to broken pipe problems pass only first 10 KiB
            data = history[-1].std_out[0:10*1024]

        cmd = Command(c)
        try:
            out, err = cmd.run(data, timeout, kill_timeout, env, cwd)
            status_code = cmd.returncode
        except OSError as e:
            out, err = '', u"\n".join([e.strerror, traceback.format_exc()])
            status_code = 127

        r = Response(process=cmd)

        r.command = c
        r.std_out = out
        r.std_err = err
        r.status_code = status_code

        history.append(r)

    r = history.pop()
    r.history = history

    return r

def connect(command, data=None, env=None, cwd=None):
    """Spawns a new process from the given command."""

    # TODO: support piped commands
    command_str = expand_args(command).pop()
    environ = dict(os.environ)
    environ.update(env or {})

    process = subprocess.Popen(command_str,
        universal_newlines=True,
        shell=False,
        env=environ,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        bufsize=0,
        cwd=cwd,
    )

    return ConnectedCommand(process=process)
<|endoftext|>


<commit_before>#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This script is used to synthesize generated parts of this library."""

import synthtool as s
import synthtool.gcp as gcp
import synthtool.languages.node as node
import subprocess
import logging

logging.basicConfig(level=logging.DEBUG)

# run the gapic generator
gapic = gcp.GAPICBazel()
versions = ["v1"]
name = 'accessapproval'
for version in versions:
  library = gapic.node_library(
  name,
  version,
  proto_path = f'google/cloud/accessapproval/{version}')
  s.copy(library, excludes=[])

# Copy common templates
common_templates = gcp.CommonTemplates()
templates = common_templates.node_library(
    source_location='build/src', versions=["v1"], default_version="v1")
s.copy(templates, excludes=[])

node.postprocess_gapic_library()
<commit_msg>fix: header<commit_after># Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This script is used to synthesize generated parts of this library."""

import synthtool as s
import synthtool.gcp as gcp
import synthtool.languages.node as node
import subprocess
import logging

logging.basicConfig(level=logging.DEBUG)

# run the gapic generator
gapic = gcp.GAPICBazel()
versions = ["v1"]
name = 'accessapproval'
for version in versions:
  library = gapic.node_library(
  name,
  version,
  proto_path = f'google/cloud/accessapproval/{version}')
  s.copy(library, excludes=["README.md", "package.json"])

# Copy common templates
common_templates = gcp.CommonTemplates()
templates = common_templates.node_library(
    source_location='build/src', versions=["v1"], default_version="v1")
s.copy(templates, excludes=[])

node.postprocess_gapic_library()
<|endoftext|>


<commit_before>"""
Matrix declaration rules

Nodes
-----
Matrix : Matrix container
    Example: "[x;y]"
    Contains: Vector, ...

Vector : (Column)-Vector container
    Contains: Expr, ...
"""
from _code_block import Statement
import assign
import armadillo as arma

def Vector(node):
    """A (row-)vector
    """

    if node.value == "scalarsonly":
        return "", ", ", ""

    if node.type == "string":
        return "", " + ", ""

    nodes = map(str, node)

    #max mem in list and type list
    try:
        mem = max([int(n.mem) if n.num else -1 for n in node])
    except:
        mem = -1
    mem_type = ["uword", "sword", "float", "double", "cx_double"]

    #Join columns: a = [0, my_rowvec, b]
    for i in xrange(len(nodes)):
        # scalars must be converted first
        if node[i].value or node[i].dim == 0: # value=scalarsonly
            node[i].include("m2cpp")
            if mem != -1:
                nodes[i] = "m2cpp::srow<" + mem_type[mem] + ">(" + nodes[i] + ")"
            else:
                nodes[i] = "m2cpp::srow(" + nodes[i] + ")"

    if nodes:
        return reduce(lambda x,y: ("arma::join_rows(%s, %s)" % (x, y)), nodes)
    return ""

def Matrix(node):

    # ensure all vectors in matrix same length
    m = len(node[0])
    if any([len(n)-m for n in node if n.value == "scalarsonly"]):
        shape = str([len(n) for n in node if n.value == "scalarsonly"])
        node.error("shape missmatch %s" % shape)

    if node.type == "string":
        if len(node) > 1:
            return "", " + ", ""
        return "", " ", ""

    #clims in imagesc needs two {{ and }} for the python implementation
    if node.parent.name in ("imagesc", "wigb"):
        if all([n.dim == 0 for n in node[0]]):
            return "{{", ", ", "}}"
        if node.parent.name in ("imagesc", "wigb", "plot"):
            return "{", ", ", "}"
        return "", ", ", ""

    # non-numerical elements in matrix
    if not node.num:
        if len(node[0]) == 1 and node[0][0].cls == "Colon":
            return "", ", ", ""
        return "{", ", ", "}"

    dims = {n.dim for n in node}

    # single vector with no content
    if len(node) == 1 and len(node[0]) == 0:
        return "{", ", ", "}"

    # everything on scalarsonly form
    elif all([n.value for n in node]):

        # Inline matrices are moved to own lines
        if node.parent.cls not in ("Assign", "Statement") and \
                    node.parent.backend != "reserved":
            if node.parent.cls in ("Get", "Set") and node.mem != 0:
                if node.parent.type == "TYPE":
                    node.type = (node.dim, 3)
                else:
                    node.type = (node.dim, 0)
            return str(node.auxiliary())

        # if node.parent.cls in ("Assign", "Statement"):
        #     node.parent.backend = "matrix"

        return "{", ", ", "}"

    # mix of scalars and colvecs, scalar and matrix, scalar and vec and matrix
    elif dims in ({0,1}, {1}, {0,3}, {0,1,3}):

        # make string of each vector in matrix
        nodes = []
        for i in xrange(len(node)):

            #max mem in list and type list
            try:
                mem = max([int(n.mem) if n.num else -1 for n in node])
            except:
                mem = -1
            mem_type = ["uword", "sword", "float", "double", "cx_double"]

            # scalars must be converted first
            if node[i].value or node[i].dim == 0: # value=scalarsonly
                node[i].include("m2cpp")
                if mem != -1:
                    nodes.append("m2cpp::scol<" + mem_type[mem] + ">(" + str(node[i]) + ")")
                else:
                    nodes.append("m2cpp::scol(" + str(node[i]) + ")")
            else:
                nodes.append(str(node[i]))

    # mix of rowvecs and matrices, mix of columnvecs and matrices
    elif dims in ({2}, {3}, {2,3}, {1,3}):

        # make string of each vector in matrix
        nodes = []
        for i in xrange(len(node)):

            # decomposed vectors should be moved to own lines
            if node[i].value:
                nodes.append(str(node[i].auxiliary()))
            else:
                nodes.append(str(node[i]))

    try:
        return reduce(lambda a,b: ("arma::join_cols(%s, %s)" % (a,b)), nodes)
    except:
        node.error("No match for handling matrix arg found")
        return "{", ", ", "}"

def Assign(node):

    #left-hand-side, right-hand-side
    lhs, rhs = node

    assert rhs.cls in ("Matrix", "Cell")

    # no content in matrix
    if len(rhs[0]) == 0:
        return "%(0)s.reset() ;"

    # non-numerical values in matrix or variable assign
    if not lhs.num or not rhs.num:
        return "%(0)s = %(1)s ;"

    # new local variable 'ctype' contains convertion type
    node.type = node["ctype"] = node[0].type
    dim = node.dim
    node.dim = 0

    # decomposed matrix
    if rhs.value:

        type = node.type
        if type == "int":
            type = "sword"

        # scalar
        if rhs.dim == 0:
            return arma.scalar_assign(node)

        # colvec
        elif rhs.dim == 1:

            # save number of rows as 'rows'
            node["rows"] = len(node[1][0])*len(node[1])

            return type + " _" + node[0].name + " [] = %(1)s ;\n"+\
                "%(0)s = %(ctype)s(_" + node[0].name + ", %(rows)s, false) ;"

        # rowvec
        elif rhs.dim == 2:

            # save number of cols as 'cols'
            node["cols"] = len(node[1][0])*len(node[1])
            return type + " _" + node[0].name + " [] = %(1)s ;\n"+\
                "%(0)s = %(ctype)s(_" + node[0].name + ", %(cols)s, false) ;"

        # matrix
        elif rhs.dim == 3:
            # save number of rows and columns
            node["rows"] = len(node[1][0])
            node["cols"] = len(node[1])
            return type + " _" + node[0].name + " [] = %(1)s ;\n"+\
        "%(0)s = arma::strans(%(ctype)s(_" + node[0].name + ", %(rows)s, %(cols)s, false)) ;"

        assert False

    else:
        node.dim = dim

    return assign.Assign(node)

Var = "%(name)s"

def Cell(node):

    # move inline cells to own lines
    if node.parent.cls not in ("Assign", "Assigns"):
        node.auxiliary()

    return "{", ", ", "}"
<commit_msg>Some more stuff about arma::join_rows/cols and plotting<commit_after>"""
Matrix declaration rules

Nodes
-----
Matrix : Matrix container
    Example: "[x;y]"
    Contains: Vector, ...

Vector : (Column)-Vector container
    Contains: Expr, ...
"""
from _code_block import Statement
import assign
import armadillo as arma

def Vector(node):
    """A (row-)vector
    """

    if node.value == "scalarsonly":
        return "", ", ", ""

    if node.type == "string":
        return "", " + ", ""

    nodes = map(str, node)

    #max mem in list and type list
    try:
        mem = max([int(n.mem) if n.num else -1 for n in node])
    except:
        mem = -1
    mem_type = ["uword", "sword", "float", "double", "cx_double"]

    #Join columns: a = [0, my_rowvec, b]
    for i in xrange(len(nodes)):
        # scalars must be converted first
        if node[i].value or node[i].dim == 0: # value=scalarsonly
            node[i].include("m2cpp")
            if mem != -1:
                nodes[i] = "m2cpp::srow<" + mem_type[mem] + ">(" + nodes[i] + ")"
            else:
                nodes[i] = "m2cpp::srow(" + nodes[i] + ")"

    if nodes:
        return reduce(lambda x,y: ("arma::join_rows(%s, %s)" % (x, y)), nodes)
    return ""

def Matrix(node):

    # ensure all vectors in matrix same length
    m = len(node[0])
    if any([len(n)-m for n in node if n.value == "scalarsonly"]):
        shape = str([len(n) for n in node if n.value == "scalarsonly"])
        node.error("shape missmatch %s" % shape)

    if node.type == "string":
        if len(node) > 1:
            return "", " + ", ""
        return "", " ", ""

    #clims in imagesc needs two {{ and }} for the python implementation
    if node.parent.name in ("imagesc", "wigb") and \
      len(node) == 1 and len(node[0]) > 1:
        if all([n.dim == 0 for n in node[0]]):
            return "{{", ", ", "}}"
        #{ } around arma::join_rows()
        return "{", ", ", "}"

    # non-numerical elements in matrix
    if not node.num:
        if len(node[0]) == 1 and node[0][0].cls == "Colon":
            return "", ", ", ""
        return "{", ", ", "}"

    dims = {n.dim for n in node}

    # single vector with no content
    if len(node) == 1 and len(node[0]) == 0:
        return "{", ", ", "}"

    # everything on scalarsonly form
    elif all([n.value for n in node]):

        # Inline matrices are moved to own lines
        if node.parent.cls not in ("Assign", "Statement") and \
                    node.parent.backend != "reserved":
            if node.parent.cls in ("Get", "Set") and node.mem != 0:
                if node.parent.type == "TYPE":
                    node.type = (node.dim, 3)
                else:
                    node.type = (node.dim, 0)
            return str(node.auxiliary())

        # if node.parent.cls in ("Assign", "Statement"):
        #     node.parent.backend = "matrix"

        return "{", ", ", "}"

    # mix of scalars and colvecs, scalar and matrix, scalar and vec and matrix
    elif dims in ({0,1}, {1}, {0,3}, {0,1,3}):

        # make string of each vector in matrix
        nodes = []
        for i in xrange(len(node)):

            #max mem in list and type list
            try:
                mem = max([int(n.mem) if n.num else -1 for n in node])
            except:
                mem = -1
            mem_type = ["uword", "sword", "float", "double", "cx_double"]

            # scalars must be converted first
            if node[i].value or node[i].dim == 0: # value=scalarsonly
                node[i].include("m2cpp")
                if mem != -1:
                    nodes.append("m2cpp::scol<" + mem_type[mem] + ">(" + str(node[i]) + ")")
                else:
                    nodes.append("m2cpp::scol(" + str(node[i]) + ")")
            else:
                nodes.append(str(node[i]))

    # mix of rowvecs and matrices, mix of columnvecs and matrices
    elif dims in ({2}, {3}, {2,3}, {1,3}):

        # make string of each vector in matrix
        nodes = []
        for i in xrange(len(node)):

            # decomposed vectors should be moved to own lines
            if node[i].value:
                nodes.append(str(node[i].auxiliary()))
            else:
                nodes.append(str(node[i]))

    try:
        if node.parent.name in ("imagesc", "wigb"):
            return reduce(lambda a,b: ("arma::join_cols(%s, %s)" % (a,b)), nodes)
        return reduce(lambda a,b: ("arma::join_cols(%s, %s)" % (a,b)), nodes)
    except:
        node.error("No match for handling matrix arg found")
        return "{", ", ", "}"

def Assign(node):

    #left-hand-side, right-hand-side
    lhs, rhs = node

    assert rhs.cls in ("Matrix", "Cell")

    # no content in matrix
    if len(rhs[0]) == 0:
        return "%(0)s.reset() ;"

    # non-numerical values in matrix or variable assign
    if not lhs.num or not rhs.num:
        return "%(0)s = %(1)s ;"

    # new local variable 'ctype' contains convertion type
    node.type = node["ctype"] = node[0].type
    dim = node.dim
    node.dim = 0

    # decomposed matrix
    if rhs.value:

        type = node.type
        if type == "int":
            type = "sword"

        # scalar
        if rhs.dim == 0:
            return arma.scalar_assign(node)

        # colvec
        elif rhs.dim == 1:

            # save number of rows as 'rows'
            node["rows"] = len(node[1][0])*len(node[1])

            return type + " _" + node[0].name + " [] = %(1)s ;\n"+\
                "%(0)s = %(ctype)s(_" + node[0].name + ", %(rows)s, false) ;"

        # rowvec
        elif rhs.dim == 2:

            # save number of cols as 'cols'
            node["cols"] = len(node[1][0])*len(node[1])
            return type + " _" + node[0].name + " [] = %(1)s ;\n"+\
                "%(0)s = %(ctype)s(_" + node[0].name + ", %(cols)s, false) ;"

        # matrix
        elif rhs.dim == 3:
            # save number of rows and columns
            node["rows"] = len(node[1][0])
            node["cols"] = len(node[1])
            return type + " _" + node[0].name + " [] = %(1)s ;\n"+\
        "%(0)s = arma::strans(%(ctype)s(_" + node[0].name + ", %(rows)s, %(cols)s, false)) ;"

        assert False

    else:
        node.dim = dim

    return assign.Assign(node)

Var = "%(name)s"

def Cell(node):

    # move inline cells to own lines
    if node.parent.cls not in ("Assign", "Assigns"):
        node.auxiliary()

    return "{", ", ", "}"
<|endoftext|>


<commit_before>#!/usr/bin/env python2.5
#
# Copyright 2011 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module for the GSoC participant dashboard.
"""

__authors__ = [
  '"Lennard de Rijk" <ljvderijk@gmail.com>',
  ]

from google.appengine.api import users

from django.conf.urls.defaults import url

from soc.logic.exceptions import AccessViolation
from soc.logic.helper import timeline as timeline_helper
from soc.views.template import Template

from soc.modules.gsoc.logic.models.org_app_survey import logic as \
    org_app_logic
from soc.modules.gsoc.logic.models.student_project import logic as \
    project_logic
from soc.modules.gsoc.views.base import RequestHandler
from soc.modules.gsoc.views.helper import lists
from soc.modules.gsoc.views.helper import url_patterns

class Dashboard(RequestHandler):
  """View for the participant dashboard.
  """

  def djangoURLPatterns(self):
    """The URL pattern for the dashboard.
    """
    return [
        url(r'^gsoc/dashboard/%s$' %url_patterns.PROGRAM, self,
            name='gsoc_dashboard')]

  def checkAccess(self):
    """Denies access if you don't have a role in the current program.
    """
    self.check.isLoggedIn()

  def templatePath(self):
    """Returns the path to the template.
    """
    return 'v2/modules/gsoc/dashboard/base.html'

  def jsonContext(self):
    """Handler for JSON requests.
    """
    components = self._getActiveComponents()

    list_content = None
    for component in components:
      list_content = component.getListData()
      if list_content:
        break

    if not list_content:
      raise AccessViolation(
          'You do not have access to this data')
    return list_content.content()

  def context(self):
    """Handler for default HTTP GET request.
    """
    components = self._getActiveComponents()

    context = {}
    context['page_name'] = self.data.program.name
    context['user'] = self.data.user
    context['logout_link'] = users.create_logout_url(self.data.full_path)
    # TODO(ljvderijk): Implement code for setting dashboard messages.
    #context['alert_msg'] = 'Default alert goes here'
    context['components'] = components

    return context

  def _getActiveComponents(self):
    """Returns the components that are active on the page.
    """
    if self.data.student:
      return self._getStudentComponents()
    elif self.data.mentor or self.data.org_admin:
      return self._getOrgMemberComponents()
    else:
      return self._getLoneUserComponents()

  def _getStudentComponents(self):
    """Get the dashboard components for a student.
    """
    # Add all the proposals of this current user
    components = [MyProposalsComponent(self.request, self.data)]

    fields = {'student': self.data.student}
    project = project_logic.getForFields(fields, unique=True)
    if project:
      # Add a component to show all the projects
      components.append(MyProjectsComponent(self.request, self.data))
      # Add a component to show the evaluations
      # TODO(ljvderijk): Enable after the right information can be displayed
      #components.append(MyEvaluationsComponent(self.request, self.data))

    return components

  def _getOrgMemberComponents(self):
    """Get the dashboard components for Organization members.
    """
    components = []

    if self.data.mentor:
      if timeline_helper.isAfterEvent(
          self.data.program_timeline, 'accepted_students_announced_deadline'):
        # add a component to show all projects a user is mentoring
        components.append(
            ProjectsIMentorComponent(self.request, self.data))

    if self.data.org_admin:
      # add a component for all organization that this user administers
      components.append(OrganizationsIAdminComponent(self.request, self.data))

    if timeline_helper.isBeforeEvent(
      self.data.program_timeline, 'student_signup_start'):
      # Add the submitted proposals component
      #components.append(
      #    SubmittedProposalsComponent(self.request, self.data))
      pass

    return components

  def _getLoneUserComponents(self):
    """Get the dashboard components for users without any role.
    """
    components = []

    org_app_survey = org_app_logic.getForProgram(self.data.program)

    fields = {'survey': org_app_survey}
    org_app_record = org_app_logic.getRecordLogic().getForFields(fields, unique=True)

    if org_app_record:
      # add a component showing the organization application of the user
      components.append(MyOrgApplicationsComponent(self.request, self.data,
                                                   org_app_survey))

    return components

class Component(Template):
  """Base component for the dashboard.
  """

  def __init__(self, request, data):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
    """
    self.request = request
    self.data = data

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    # by default no list is present
    return None

class MyOrgApplicationsComponent(Component):
  """Component for listing the Organization Applications of the current user.
  """

  def __init__(self, request, data, org_app_survey):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
      org_app_survey: the OrgApplicationSurvey entity
    """
    # passed in so we don't have to do double queries
    self.org_app_survey = org_app_survey
    super(MyOrgApplicationsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    # TODO(ljvderijk): List redirects
    list_params = org_app_view.getParams()['record_list_params']
    list_params['list_description'] = 'List of your Organization Applications'
    list_config = lists.getListGenerator(self.request, list_params,
                                         visibility='self', idx=0)
    return {
        'name': 'org_applications',
        'title': 'MY ORGANIZATION APPLICATIONS',
        'lists': Lists([list_config]),
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 0:
      list_data = lists.getListData(
          self.request, org_app_view.getParams()['record_list_params'],
          {'survey': self.org_app_survey, 'main_admin': self.data.user},
          visibility='self')
      return list_data
    else:
      return None

class MyProposalsComponent(Component):
  """Component for listing all the proposals of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(self.request,
                                         proposal_view.getParams(), idx=1)
    return {
        'name': 'proposals',
        'title': 'PROPOSALS',
        'lists': Lists([list_config]),
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 1:
      list_data = lists.getListData(self.request, proposal_view.getParams(),
                                   {'program': self.data.program,
                                    'scope': self.data.student})
      return list_data
    else:
      return None

class MyProjectsComponent(Component):
  """Component for listing all the projects of the current Student.
  """

  def __init__(self, request, data):
    """Initializes this component.
    """
    list_config = lists.ListConfiguration()
    list_config.addColumn('title', 'Title', lambda ent, *args: ent.title)
    list_config.addColumn('org_name', 'Organization Name',
                          lambda ent, *args: ent.scope.name)
    self._list_config = list_config

    super(MyProjectsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 2:
      fields = {'program': self.data.program,
                'student': self.data.student}
      prefetch = ['scope']
      response_builder = lists.QueryContentResponseBuilder(
          self.request, self._list_config, project_logic, fields, prefetch)
      return response_builder.build()
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list = lists.ListConfigurationResponse(
        self._list_config, idx=2, description='List of my student projects')
    return {
        'name': 'projects',
        'title': 'PROJECTS',
        'lists': [list],
    }

class MyEvaluationsComponent(Component):
  """Component for listing all the Evaluations of the current Student.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 3:
      list_data = lists.getListData(self.request, project_survey_view.getParams(),
                                    {'scope': self.data.program})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, project_survey_view.getParams(), idx=3)

    return {
        'name': 'evaluations',
        'title': 'EVALUATIONS',
        'lists': Lists([list_config]),
    }

class SubmittedProposalsComponent(Component):
  """Component for listing all the Evaluations of the current Student.
  """
  # TODO(ljvderijk): Implement
  pass

class ProjectsIMentorComponent(Component):
  """Component for listing all the Projects mentored by the current user.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 4:
      list_data = lists.getListData(self.request, project_view.getParams(),
                                    {'program': self.data.program,
                                     'mentor': self.data.mentor})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, project_view.getParams(), idx=4)

    return {
        'name': 'mentoring_projects',
        'title': 'PROJECTS I AM A MENTOR FOR',
        'lists': Lists([list_config]),
    }

class OrganizationsIAdminComponent(Component):
  """Component for listing all the Organizations controlled by the current
  user.
  """

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 5:
      # TODO(ljvderijk): Feels weird that if you have access to all the keys
      # already that you need to use the list code in this way. The rewrite
      # should probably allow the caller to control the entities to put in?
      list_data = lists.getListData(
          self.request, org_view.getParams(),
          {'scope': self.data.program,
           'link_id': [org_admin.scope.link_id
                       for org_admin in self.data.org_admin]})
      return list_data
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list_config = lists.getListGenerator(
        self.request, org_view.getParams(), idx=5)

    return {
        'name': 'adminning_organizations',
        'title': 'ORGANIZATIONS THAT I AM AN ADMIN FOR',
        'lists': Lists([list_config]),
    }
<commit_msg>Convert all lists on Dashboard to the new lists.<commit_after>#!/usr/bin/env python2.5
#
# Copyright 2011 the Melange authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Module for the GSoC participant dashboard.
"""

__authors__ = [
  '"Lennard de Rijk" <ljvderijk@gmail.com>',
  ]

from google.appengine.api import users

from django.conf.urls.defaults import url

from soc.logic.exceptions import AccessViolation
from soc.logic.helper import timeline as timeline_helper
from soc.views.template import Template

from soc.modules.gsoc.logic.models.org_app_survey import logic as \
    org_app_logic
from soc.modules.gsoc.logic.models.student_project import logic as \
    project_logic
# TODO: Change this to the logic for the new proposals
from soc.modules.gsoc.logic.models.student_proposal import logic as \
    proposal_logic
from soc.modules.gsoc.logic.models.survey import project_logic as \
    ps_logic
from soc.modules.gsoc.views.base import RequestHandler
from soc.modules.gsoc.views.helper import lists
from soc.modules.gsoc.views.helper import url_patterns

class Dashboard(RequestHandler):
  """View for the participant dashboard.
  """

  def djangoURLPatterns(self):
    """The URL pattern for the dashboard.
    """
    return [
        url(r'^gsoc/dashboard/%s$' %url_patterns.PROGRAM, self,
            name='gsoc_dashboard')]

  def checkAccess(self):
    """Denies access if you don't have a role in the current program.
    """
    self.check.isLoggedIn()

  def templatePath(self):
    """Returns the path to the template.
    """
    return 'v2/modules/gsoc/dashboard/base.html'

  def jsonContext(self):
    """Handler for JSON requests.
    """
    components = self._getActiveComponents()

    list_content = None
    for component in components:
      list_content = component.getListData()
      if list_content:
        break

    if not list_content:
      raise AccessViolation(
          'You do not have access to this data')
    return list_content.content()

  def context(self):
    """Handler for default HTTP GET request.
    """
    components = self._getActiveComponents()

    context = {}
    context['page_name'] = self.data.program.name
    context['user'] = self.data.user
    context['logout_link'] = users.create_logout_url(self.data.full_path)
    # TODO(ljvderijk): Implement code for setting dashboard messages.
    #context['alert_msg'] = 'Default alert goes here'
    context['components'] = components

    return context

  def _getActiveComponents(self):
    """Returns the components that are active on the page.
    """
    if self.data.student_info:
      return self._getStudentComponents()
    elif self.data.mentor_for or self.data.org_admin_for:
      return self._getOrgMemberComponents()
    else:
      return self._getLoneUserComponents()

  def _getStudentComponents(self):
    """Get the dashboard components for a student.
    """
    # Add all the proposals of this current user
    components = [MyProposalsComponent(self.request, self.data)]

    fields = {'student': self.data.student}
    project = project_logic.getForFields(fields, unique=True)
    if project:
      # Add a component to show all the projects
      components.append(MyProjectsComponent(self.request, self.data))
      # Add a component to show the evaluations
      # TODO(ljvderijk): Enable after the right information can be displayed
      #components.append(MyEvaluationsComponent(self.request, self.data))

    return components

  def _getOrgMemberComponents(self):
    """Get the dashboard components for Organization members.
    """
    components = []

    if self.data.mentor:
      if timeline_helper.isAfterEvent(
          self.data.program_timeline, 'accepted_students_announced_deadline'):
        # add a component to show all projects a user is mentoring
        components.append(
            ProjectsIMentorComponent(self.request, self.data))

    if timeline_helper.isAfterEvent(
      self.data.program_timeline, 'student_signup_start'):
      # Add the submitted proposals component
      #components.append(
      #    SubmittedProposalsComponent(self.request, self.data))
      pass

    if self.data.org_admin:
      # add a component for all organization that this user administers
      components.append(OrganizationsIAdminComponent(self.request, self.data))

    return components

  def _getLoneUserComponents(self):
    """Get the dashboard components for users without any role.
    """
    components = []

    org_app_survey = org_app_logic.getForProgram(self.data.program)

    fields = {'survey': org_app_survey}
    org_app_record = org_app_logic.getRecordLogic().getForFields(fields,
                                                                 unique=True)

    if org_app_record:
      # add a component showing the organization application of the user
      components.append(MyOrgApplicationsComponent(self.request, self.data,
                                                   org_app_survey))

    return components

class Component(Template):
  """Base component for the dashboard.
  """

  def __init__(self, request, data):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
    """
    self.request = request
    self.data = data

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    # by default no list is present
    return None

class MyOrgApplicationsComponent(Component):
  """Component for listing the Organization Applications of the current user.
  """

  def __init__(self, request, data, org_app_survey):
    """Initializes the component.

    Args:
      request: The HTTPRequest object
      data: The RequestData object
      org_app_survey: the OrgApplicationSurvey entity
    """
    # passed in so we don't have to do double queries
    self.org_app_survey = org_app_survey

    list_config = lists.ListConfiguration()
    list_config.addSimpleColumn('name', 'Organization Name')
    self._list_config = list_config

    super(MyOrgApplicationsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    list = lists.ListConfigurationResponse(
        self._list_config, idx=0, description='List of your Organization Applications')

    return {
        'name': 'org_applications',
        'title': 'MY ORGANIZATION APPLICATIONS',
        'lists': [list],
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 0:
      fields = {'survey': self.org_app_survey,
                'main_admin': self.data.user}
      response_builder = lists.QueryContentResponseBuilder(
          self.request, self._list_config, org_app_logic.getRecordLogic(),
          fields)
      return response_builder.build()
    else:
      return None

class MyProposalsComponent(Component):
  """Component for listing all the proposals of the current Student.
  """

  def __init__(self, request, data):
    """Initializes this component.
    """
    list_config = lists.ListConfiguration()
    list_config.addSimpleColumn('title', 'Title')
    list_config.addColumn('org', 'Organization',
                          lambda ent, *args: ent.org.name)
    self._list_config = list_config

    super(MyProposalsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def context(self):
    """Returns the context of this component.
    """
    list = lists.ListConfigurationResponse(
        self._list_config, idx=1, description='List of my project proposals')
    return {
        'name': 'proposals',
        'title': 'PROPOSALS',
        'lists': [list],
        }

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 1:
      fields = {'program': self.data.program}
      response_builder = lists.QueryContentResponseBuilder(
          self.request, self._list_config, proposal_logic, fields,
          ancestors=[self.data.profile], prefetch=['org'])
      return response_builder.build()
    else:
      return None

class MyProjectsComponent(Component):
  """Component for listing all the projects of the current Student.
  """

  def __init__(self, request, data):
    """Initializes this component.
    """
    list_config = lists.ListConfiguration()
    list_config.addSimpleColumn('title', 'Title')
    list_config.addColumn('org_name', 'Organization Name',
                          lambda ent, *args: ent.scope.name)
    self._list_config = list_config

    super(MyProjectsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 2:
      fields = {'program': self.data.program,
                'student': self.data.student}
      prefetch = ['scope']
      response_builder = lists.QueryContentResponseBuilder(
          self.request, self._list_config, project_logic, fields,
          prefetch=prefetch)
      return response_builder.build()
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list = lists.ListConfigurationResponse(
        self._list_config, idx=2, description='List of my student projects')
    return {
        'name': 'projects',
        'title': 'PROJECTS',
        'lists': [list],
    }

class MyEvaluationsComponent(Component):
  """Component for listing all the Evaluations of the current Student.
  """

  def __init__(self, request, data):
    """Initializes this component.
    """
    # TODO: This list should allow one to view or edit a record for each project
    # available to the student.
    list_config = lists.ListConfiguration()
    list_config.addSimpleColumn('title', 'Title')
    list_config.addSimpleColumn('survey_start', 'Survey Starts')
    list_config.addSimpleColumn('survey_end', 'Survey Ends')
    self._list_config = list_config

    super(MyEvaluationsComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 3:
      fields = {'program': self.data.program}
      response_builder = lists.QueryContentResponseBuilder(
          self.request, self._list_config, ps_logic, fields)
      return response_builder.build()
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list = lists.ListConfigurationResponse(
        self._list_config, idx=3, description='List of my evaluations')

    return {
        'name': 'evaluations',
        'title': 'EVALUATIONS',
        'lists': [list],
    }

class SubmittedProposalsComponent(Component):
  """Component for listing all the proposals send to orgs this user is a member
  of.
  """
  # TODO(ljvderijk): Implement
  pass

class ProjectsIMentorComponent(Component):
  """Component for listing all the Projects mentored by the current user.
  """

  def __init__(self, request, data):
    """Initializes this component.
    """
    list_config = lists.ListConfiguration()
    list_config.addSimpleColumn('title', 'Title')
    list_config.addColumn('org_name', 'Organization',
                          lambda ent, *args: ent.scope.name)
    self._list_config = list_config

    super(ProjectsIMentorComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 4:
      fields =  {'program': self.data.program,
                 'mentor': self.data.profile}
      response_builder = lists.QueryContentResponseBuilder(
          self.request, self._list_config, project_logic, fields, prefetch=['scope'])
      return response_builder.build()
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list = lists.ListConfigurationResponse(
        self._list_config, idx=4, description='List of projects I mentor')

    return {
        'name': 'mentoring_projects',
        'title': 'PROJECTS I AM A MENTOR FOR',
        'lists': [list],
    }

class OrganizationsIAdminComponent(Component):
  """Component for listing all the Organizations controlled by the current
  user.
  """

  def __init__(self, request, data):
    """Initializes this component.
    """
    list_config = lists.ListConfiguration()
    list_config.addSimpleColumn('name', 'name')
    self._list_config = list_config

    super(OrganizationsIAdminComponent, self).__init__(request, data)

  def templatePath(self):
    """Returns the path to the template that should be used in render().
    """
    return'v2/modules/gsoc/dashboard/list_component.html'

  def getListData(self):
    """Returns the list data as requested by the current request.

    If the lists as requested is not supported by this component None is
    returned.
    """
    idx = lists.getListIndex(self.request)
    if idx == 5:
      response = lists.ListContentResponse(self.request, self._list_config)

      if response.start != 'done':
        # Add all organizations in one go since we already queried for it.
        for org in self.data.org_admin_for:
          response.addRow(org)
        response.next = 'done'

      return response
    else:
      return None

  def context(self):
    """Returns the context of this component.
    """
    list = lists.ListConfigurationResponse(
        self._list_config, idx=5, description='Organizations I am an admin for')

    return {
        'name': 'adminning_organizations',
        'title': 'ORGANIZATIONS THAT I AM AN ADMIN FOR',
        'lists': [list],
    }
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import tempfile
from six import b
import subprocess
import json

from ..command import Command, Arg, Option, expand_paths
from ..resource import Resource
from ..exceptions import CommandError
from ..utils import md5

class Edit(Command):
    """Edit a resource.

    The resource JSON will be opened in an editor. If modifications
    have been made and the file is saved the resource will be sent
    to the API server.

    The `--template` option can be used to create a new resource based
    on an existing resource.
    """
    description = "Edit resource"
    path = Arg(help="Resource path",
               complete='resources::path')
    template = Option('-t',
                      help="Create new resource from existing",
                      action="store_true", default=False)
    aliases = ['vim = edit', 'emacs = edit', 'nano = edit']

    def __call__(self, path='', template=False):
        resources = expand_paths([path],
                                 predicate=lambda r: isinstance(r, Resource))
        if len(resources) > 1:
            raise CommandError("Can't edit multiple resources")
        resource = resources[0]
        # don't show childs or back_refs
        resource.fetch(exclude_children=True, exclude_back_refs=True)
        resource.pop('id_perms')
        if template:
            resource.pop('href')
            resource.pop('uuid')
        editor = os.environ.get('EDITOR', 'vim')
        with tempfile.NamedTemporaryFile(suffix='tmp.json') as tmp:
            tmp.write(b(resource.json()))
            tmp.flush()
            tmp_md5 = md5(tmp.name)
            subprocess.call([editor, tmp.name])
            tmp.seek(0)
            if tmp_md5 == md5(tmp.name):
                print("No modification made, doing nothing...")
                return
            data_json = tmp.read().decode('utf-8')
        try:
            data = json.loads(data_json)
        except ValueError as e:
            raise CommandError('Provided JSON is not valid: ' + str(e))
        if template:
            # create new resource
            resource = Resource(resource.type, **data)
        else:
            resource.update(data)
        resource.save()
<commit_msg>Edit command takes 1 argument<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import tempfile
from six import b
import subprocess
import json

from ..command import Command, Arg, Option, expand_paths
from ..resource import Resource
from ..exceptions import CommandError
from ..utils import md5

class Edit(Command):
    """Edit a resource.

    The resource JSON will be opened in an editor. If modifications
    have been made and the file is saved the resource will be sent
    to the API server.

    The `--template` option can be used to create a new resource based
    on an existing resource.
    """
    description = "Edit resource"
    path = Arg(nargs=1, help="Resource path",
               complete='resources::path')
    template = Option('-t',
                      help="Create new resource from existing",
                      action="store_true", default=False)
    aliases = ['vim = edit', 'emacs = edit', 'nano = edit']

    def __call__(self, path=None, template=False):
        resources = expand_paths([path],
                                 predicate=lambda r: isinstance(r, Resource))
        if len(resources) > 1:
            raise CommandError("Can't edit multiple resources")
        resource = resources[0]
        # don't show childs or back_refs
        resource.fetch(exclude_children=True, exclude_back_refs=True)
        resource.pop('id_perms')
        if template:
            resource.pop('href')
            resource.pop('uuid')
        editor = os.environ.get('EDITOR', 'vim')
        with tempfile.NamedTemporaryFile(suffix='tmp.json') as tmp:
            tmp.write(b(resource.json()))
            tmp.flush()
            tmp_md5 = md5(tmp.name)
            subprocess.call([editor, tmp.name])
            tmp.seek(0)
            if tmp_md5 == md5(tmp.name):
                print("No modification made, doing nothing...")
                return
            data_json = tmp.read().decode('utf-8')
        try:
            data = json.loads(data_json)
        except ValueError as e:
            raise CommandError('Provided JSON is not valid: ' + str(e))
        if template:
            # create new resource
            resource = Resource(resource.type, **data)
        else:
            resource.update(data)
        resource.save()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
from django.template import engines
from django.template.loader import select_template
from django.utils.translation import ugettext_lazy as _
from cms.plugin_pool import plugin_pool
from cmsplugin_cascade.bootstrap3.buttons import BootstrapButtonMixin

from djng.forms import fields, NgModelFormMixin
from djng.styling.bootstrap3.forms import Bootstrap3Form

from shop.conf import app_settings
from .plugin_base import ShopPluginBase

class ShopOrderViewsForm(forms.ModelForm):
    def clean(self):
        cleaned_data = super(ShopOrderViewsForm, self).clean()
        if self.instance.page and self.instance.page.application_urls != 'OrderApp':
            msg = "This plugin only makes sense if used on a CMS page with an application of type 'OrderApp'."
            raise ValidationError(msg)
        return cleaned_data

class ShopOrderViewsPlugin(ShopPluginBase):
    name = _("Order Views")
    require_parent = True
    parent_classes = ('BootstrapColumnPlugin',)
    form = ShopOrderViewsForm
    cache = False

    def get_render_template(self, context, instance, placeholder):
        many = context.get('many')
        if many is True:
            # render Order List View
            return select_template([
                '{}/order/list.html'.format(app_settings.APP_LABEL),
                'shop/order/list.html',
            ])
        if many is False:
            # render Order Detail View
            return select_template([
                '{}/order/detail.html'.format(app_settings.APP_LABEL),
                'shop/order/detail.html',
            ])
        # can happen, if this plugin is abused outside of an OrderView
        return engines['django'].from_string('
This {} plugin is used on a CMS page without an application of type "View Order".
'.format(self.name))

plugin_pool.register_plugin(ShopOrderViewsPlugin)

class ReorderButtonForm(ShopOrderViewsForm):
    button_content = fields.CharField(required=False, label=_("Button Content"),
                                      widget=widgets.TextInput())

    def __init__(self, raw_data=None, *args, **kwargs):
        instance = kwargs.get('instance')
        if instance:
            initial = {'button_content': instance.glossary.get('button_content') }
            kwargs.update(initial=initial)
        super(ReorderButtonForm, self).__init__(raw_data, *args, **kwargs)

    def clean(self):
        cleaned_data = super(ReorderButtonForm, self).clean()
        if self.is_valid():
            cleaned_data['glossary']['button_content'] = cleaned_data['button_content']
        return cleaned_data

class ShopReorderFormPlugin(BootstrapButtonMixin, ShopPluginBase):
    name = _("Reorder Button")
    parent_classes = ('BootstrapColumnPlugin', 'SimpleWrapperPlugin',)
    form = ReorderButtonForm
    fields = ('button_content', 'glossary',)

    class Media:
        css = {'all': ('cascade/css/admin/bootstrap.min.css', 'cascade/css/admin/bootstrap-theme.min.css',)}

    def get_render_template(self, context, instance, placeholder):
        template_names = [
            '{}/order/reorder-form.html'.format(app_settings.APP_LABEL),
            'shop/order/reorder-form.html',
        ]
        return select_template(template_names)

plugin_pool.register_plugin(ShopReorderFormPlugin)

class AddendumForm(NgModelFormMixin, Bootstrap3Form):
    scope_prefix = 'data'
    annotation = fields.CharField(label=_("Supplementary annotation for this Order"), required=False,
                              widget=widgets.Textarea(attrs={'rows': 4}))

class ShopOrderAddendumFormPlugin(BootstrapButtonMixin, ShopPluginBase):
    name = _("Order Addendum Form")
    parent_classes = ('BootstrapColumnPlugin', 'SimpleWrapperPlugin',)
    form = ReorderButtonForm
    fields = ('button_content', 'glossary',)

    class Media:
        css = {'all': ('cascade/css/admin/bootstrap.min.css', 'cascade/css/admin/bootstrap-theme.min.css',)}

    def get_render_template(self, context, instance, placeholder):
        template_names = [
            '{}/order/addenum-form.html'.format(app_settings.APP_LABEL),
            'shop/order/addenum-form.html',
        ]
        return select_template(template_names)

    def render(self, context, instance, placeholder):
        super(ShopOrderAddendumFormPlugin, self).render(context, instance, placeholder)
        context['addenum_form'] = AddendumForm()
        return context

plugin_pool.register_plugin(ShopOrderAddendumFormPlugin)
<commit_msg>use Left- & RightExtensions to enrich the Order Detail View<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError
from django.template import engines
from django.template.loader import select_template
from django.utils.translation import ugettext_lazy as _
from cms.plugin_pool import plugin_pool
from cmsplugin_cascade.bootstrap3.buttons import BootstrapButtonMixin
from cmsplugin_cascade.plugin_base import TransparentWrapper

from djng.forms import fields, NgModelFormMixin
from djng.styling.bootstrap3.forms import Bootstrap3Form

from shop.conf import app_settings
from .extensions import ShopExtendableMixin, LeftRightExtensionMixin
from .plugin_base import ShopPluginBase

class ShopOrderViewsForm(forms.ModelForm):
    def clean(self):
        cleaned_data = super(ShopOrderViewsForm, self).clean()
        if self.instance.page and self.instance.page.application_urls != 'OrderApp':
            msg = "This plugin only makes sense if used on a CMS page with an application of type 'OrderApp'."
            raise ValidationError(msg)
        return cleaned_data

class ShopOrderViewsPlugin(LeftRightExtensionMixin, TransparentWrapper, ShopPluginBase):
    name = _("Order Views")
    require_parent = True
    parent_classes = ('BootstrapColumnPlugin',)
    allow_children = True
    model_mixins = (ShopExtendableMixin,)
    form = ShopOrderViewsForm
    cache = False

    def get_render_template(self, context, instance, placeholder):
        many = context.get('many')
        if many is True:
            # render Order List View
            return select_template([
                '{}/order/list.html'.format(app_settings.APP_LABEL),
                'shop/order/list.html',
            ])
        if many is False:
            # render Order Detail View
            return select_template([
                '{}/order/detail.html'.format(app_settings.APP_LABEL),
                'shop/order/detail.html',
            ])
        # can happen, if this plugin is abused outside of an OrderView
        return engines['django'].from_string('
This {} plugin is used on a CMS page without an application of type "View Order".
'.format(self.name))

plugin_pool.register_plugin(ShopOrderViewsPlugin)

class ReorderButtonForm(ShopOrderViewsForm):
    button_content = fields.CharField(required=False, label=_("Button Content"),
                                      widget=widgets.TextInput())

    def __init__(self, raw_data=None, *args, **kwargs):
        instance = kwargs.get('instance')
        if instance:
            initial = {'button_content': instance.glossary.get('button_content') }
            kwargs.update(initial=initial)
        super(ReorderButtonForm, self).__init__(raw_data, *args, **kwargs)

    def clean(self):
        cleaned_data = super(ReorderButtonForm, self).clean()
        if self.is_valid():
            cleaned_data['glossary']['button_content'] = cleaned_data['button_content']
        return cleaned_data

class ShopReorderFormPlugin(BootstrapButtonMixin, ShopPluginBase):
    name = _("Reorder Button")
    parent_classes = ('ShopOrderViewsPlugin',)
    form = ReorderButtonForm
    fields = ('button_content', 'glossary',)
    glossary_field_order = ('button_type', 'button_size', 'button_options', 'quick_float',
                            'icon_align', 'icon_font', 'symbol')

    class Media:
        css = {'all': ('cascade/css/admin/bootstrap.min.css', 'cascade/css/admin/bootstrap-theme.min.css',)}

    def get_render_template(self, context, instance, placeholder):
        template_names = [
            '{}/order/reorder-form.html'.format(app_settings.APP_LABEL),
            'shop/order/reorder-form.html',
        ]
        return select_template(template_names)

plugin_pool.register_plugin(ShopReorderFormPlugin)

class AddendumForm(NgModelFormMixin, Bootstrap3Form):
    scope_prefix = 'data'
    annotation = fields.CharField(label=_("Supplementary annotation for this Order"), required=False,
                              widget=widgets.Textarea(attrs={'rows': 4}))

class ShopOrderAddendumFormPlugin(BootstrapButtonMixin, ShopPluginBase):
    name = _("Order Addendum Form")
    parent_classes = ('BootstrapColumnPlugin', 'SimpleWrapperPlugin',)
    form = ReorderButtonForm
    fields = ('button_content', 'glossary',)

    class Media:
        css = {'all': ('cascade/css/admin/bootstrap.min.css', 'cascade/css/admin/bootstrap-theme.min.css',)}

    def get_render_template(self, context, instance, placeholder):
        template_names = [
            '{}/order/addenum-form.html'.format(app_settings.APP_LABEL),
            'shop/order/addenum-form.html',
        ]
        return select_template(template_names)

    def render(self, context, instance, placeholder):
        super(ShopOrderAddendumFormPlugin, self).render(context, instance, placeholder)
        context['addenum_form'] = AddendumForm()
        return context

plugin_pool.register_plugin(ShopOrderAddendumFormPlugin)
<|endoftext|>