<commit_before>from functools import wraps

from telegram import ParseMode, InlineKeyboardMarkup, InlineKeyboardButton
from telegram.ext import CallbackQueryHandler
from telegram.ext import ConversationHandler
from tinydb import TinyDB, Query

from constants import DB_FILE
from i18n import _
from util import id_from_update

SETTINGS_TEXT = _("""Settings for {bot_name}
{type}  interface language: {interface}

{type}  VocaDB language: {voca}

{type}  originals only: {originals}
(If enabled will only return original songs when searching using !s (inline) or /song)

VocaDB language is the language used for song and artist titles.
User  language is used for private messages and inline requests whereas chat  language is the language used in the current group chat.""")

db = TinyDB(str(DB_FILE))
User = Query()

INTERFACE_LANGUAGES = {'en_us': 'English'}
VOCADB_LANGUAGES = {'Default': _('Default'), 'Japanese': _('Japanese'), 'Romaji': _('Romaji'), 'English': _('English')}
ON_OFF = {'True': _('Enabled'), 'False': _('Disabled')}

settings_state = 42
default_settings = {}
settings = {}

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

def add_setting(name, nice_name, msg, button_text, trans, default):
    global settings, default_settings
    settings[name] = dict(nice_name=nice_name, msg=msg, button_text=button_text, trans=trans, default=default)
    default_settings[name] = default

def get_user(bot, update):
    global settings, default_settings
    iden = id_from_update(update)
    user = db.get(User.id == iden)
    if user is None:
        user = {'id': iden}
        db.insert(user)
    # Merge with default without overwriting
    for key, val in default_settings.items():
        if key not in user:
            user[key] = val
    db.update(user, User.id == iden)
    return user

def get_setting(name, bot, update):
    iden = id_from_update(update)
    user = get_user(bot, update)
    return user[name]

def with_voca_lang(f):
    @wraps(f)
    def wrapper(bot, update, *args, **kwargs):
        return f(bot, update, *args, lang=get_setting('voca', bot, update), **kwargs)

    return wrapper

def translate(f):
    @wraps(f)
    def wrapper(bot, update, *args, **kwargs):
        with _.using(get_setting('interface', bot, update)):
            return f(bot, update, *args, **kwargs)

    return wrapper

@translate
def start(bot, update):
    global settings
    user = get_user(bot, update)
    # noinspection PyTypeChecker
    buttons = [InlineKeyboardButton(setting['button_text'], callback_data=name) for name, setting in settings.items()]
    replace = {}
    for name, setting in settings.items():
        # noinspection PyTypeChecker
        replace[name] = setting['trans'][user[name]]
    replace.update({'bot_name': bot.name,
                    'type': _('User') if update.message.chat.type == 'private' else _('Chat')})
    text = SETTINGS_TEXT.format(**replace)
    bot.send_message(chat_id=update.message.chat.id,
                     text=text,
                     reply_markup=InlineKeyboardMarkup(list(chunks(buttons, 2))),
                     parse_mode=ParseMode.HTML)

    return settings_state

def change_setting(name):
    @translate
    def changer(bot, update):
        user = get_user(bot, update)
        iden = id_from_update(update)

        if update.callback_query.data not in settings[name]['trans']:
            bot.answer_callback_query(callback_query_id=update.callback_query.id, text=_('Unknown setting, try again.'))
            return name

        old = settings[name]['trans'][user[name]]
        db.update({name: update.callback_query.data}, User.id == iden)
        new = settings[name]['trans'][update.callback_query.data]

        msg_type = _('User') if update.callback_query.message.chat.type == 'private' else _('Chat')
        text = _("{type}  {nice_name} changed from {old} to "
                 "{new}. Please wait up to 5 minutes for all changes to take effect.")
        text = text.format(type=msg_type, nice_name=settings[name]['nice_name'], old=old, new=new)
        bot.edit_message_text(chat_id=update.callback_query.message.chat.id,
                              message_id=update.callback_query.message.message_id,
                              text=text,
                              parse_mode=ParseMode.HTML)

        return ConversationHandler.END

    return changer

@translate
def send_changer(bot, update):
    user = get_user(bot, update)
    if update.callback_query.data in user:
        global settings
        keyboard = [InlineKeyboardButton(button_text, callback_data=button_id) for button_id, button_text in
                    settings[update.callback_query.data]['trans'].items()]
        keyboard = InlineKeyboardMarkup([keyboard])
        bot.edit_message_text(chat_id=update.callback_query.message.chat.id,
                              message_id=update.callback_query.message.message_id,
                              text=settings[update.callback_query.data]['msg'],
                              reply_markup=keyboard,
                              parse_mode=ParseMode.HTML)

        return update.callback_query.data
    else:
        bot.answer_callback_query(callback_query_id=update.callback_query.id, text=_('Unknown setting, try again.'))

def get_states():
    global settings
    states = {name: [CallbackQueryHandler(change_setting(name))] for name, setting in settings.items()}
    states[settings_state] = [CallbackQueryHandler(send_changer)]
    return states

add_setting('interface', _('interface language'),
            _('Please choose preferred interface language.'),
            _('Change interface language'), INTERFACE_LANGUAGES, 'en_us')
add_setting('voca', _('VocaDB'),
            _('Please choose preferred VocaDB language.\n'
              'Default refers to the language the artist indented.'),
            _('Change VocaDB language'), VOCADB_LANGUAGES, 'English')
# TODO:: Change msg
add_setting('originals', _('originals only'),
            _('Would you like to only show original songs when searching via !s or /song?'),
            _('Change originals only'), ON_OFF, 'False')
<commit_msg>Order settings as written.<commit_after>from collections import OrderedDict
from functools import wraps

from telegram import ParseMode, InlineKeyboardMarkup, InlineKeyboardButton
from telegram.ext import CallbackQueryHandler
from telegram.ext import ConversationHandler
from tinydb import TinyDB, Query

from constants import DB_FILE
from i18n import _
from util import id_from_update

SETTINGS_TEXT = _("""Settings for {bot_name}
{type}  interface language: {interface}

{type}  VocaDB language: {voca}

{type}  originals only: {originals}
(If enabled will only return original songs when searching using !s (inline) or /song)

VocaDB language is the language used for song and artist titles.
User  language is used for private messages and inline requests whereas chat  language is the language used in the current group chat.""")

db = TinyDB(str(DB_FILE))
User = Query()

INTERFACE_LANGUAGES = OrderedDict((('en_us', 'English'),))
VOCADB_LANGUAGES = OrderedDict((('Default', _('Default')),
                                ('Japanese', _('Japanese')),
                                ('Romaji', _('Romaji')),
                                ('English', _('English'))))
ON_OFF = OrderedDict((('True', _('Enabled')),
                      ('False', _('Disabled'))))

settings_state = 42
default_settings = {}
settings = OrderedDict()

def chunks(l, n):
    """Yield successive n-sized chunks from l."""
    for i in range(0, len(l), n):
        yield l[i:i + n]

def add_setting(name, nice_name, msg, button_text, trans, default):
    global settings, default_settings
    settings[name] = dict(nice_name=nice_name, msg=msg, button_text=button_text, trans=trans, default=default)
    default_settings[name] = default

def get_user(bot, update):
    global settings, default_settings
    iden = id_from_update(update)
    user = db.get(User.id == iden)
    if user is None:
        user = {'id': iden}
        db.insert(user)
    # Merge with default without overwriting
    for key, val in default_settings.items():
        if key not in user:
            user[key] = val
    db.update(user, User.id == iden)
    return user

def get_setting(name, bot, update):
    iden = id_from_update(update)
    user = get_user(bot, update)
    return user[name]

def with_voca_lang(f):
    @wraps(f)
    def wrapper(bot, update, *args, **kwargs):
        return f(bot, update, *args, lang=get_setting('voca', bot, update), **kwargs)

    return wrapper

def translate(f):
    @wraps(f)
    def wrapper(bot, update, *args, **kwargs):
        with _.using(get_setting('interface', bot, update)):
            return f(bot, update, *args, **kwargs)

    return wrapper

@translate
def start(bot, update):
    global settings
    user = get_user(bot, update)
    # noinspection PyTypeChecker
    buttons = [InlineKeyboardButton(setting['button_text'], callback_data=name) for name, setting in settings.items()]
    replace = {}
    for name, setting in settings.items():
        # noinspection PyTypeChecker
        replace[name] = setting['trans'][user[name]]
    replace.update({'bot_name': bot.name,
                    'type': _('User') if update.message.chat.type == 'private' else _('Chat')})
    text = SETTINGS_TEXT.format(**replace)
    bot.send_message(chat_id=update.message.chat.id,
                     text=text,
                     reply_markup=InlineKeyboardMarkup(list(chunks(buttons, 2))),
                     parse_mode=ParseMode.HTML)

    return settings_state

def change_setting(name):
    @translate
    def changer(bot, update):
        user = get_user(bot, update)
        iden = id_from_update(update)

        if update.callback_query.data not in settings[name]['trans']:
            bot.answer_callback_query(callback_query_id=update.callback_query.id, text=_('Unknown setting, try again.'))
            return name

        old = settings[name]['trans'][user[name]]
        db.update({name: update.callback_query.data}, User.id == iden)
        new = settings[name]['trans'][update.callback_query.data]

        msg_type = _('User') if update.callback_query.message.chat.type == 'private' else _('Chat')
        text = _("{type}  {nice_name} changed from {old} to "
                 "{new}. Please wait up to 5 minutes for all changes to take effect.")
        text = text.format(type=msg_type, nice_name=settings[name]['nice_name'], old=old, new=new)
        bot.edit_message_text(chat_id=update.callback_query.message.chat.id,
                              message_id=update.callback_query.message.message_id,
                              text=text,
                              parse_mode=ParseMode.HTML)

        return ConversationHandler.END

    return changer

@translate
def send_changer(bot, update):
    user = get_user(bot, update)
    if update.callback_query.data in user:
        global settings
        keyboard = [InlineKeyboardButton(button_text, callback_data=button_id) for button_id, button_text in
                    settings[update.callback_query.data]['trans'].items()]
        keyboard = InlineKeyboardMarkup([keyboard])
        bot.edit_message_text(chat_id=update.callback_query.message.chat.id,
                              message_id=update.callback_query.message.message_id,
                              text=settings[update.callback_query.data]['msg'],
                              reply_markup=keyboard,
                              parse_mode=ParseMode.HTML)

        return update.callback_query.data
    else:
        bot.answer_callback_query(callback_query_id=update.callback_query.id, text=_('Unknown setting, try again.'))

def get_states():
    global settings
    states = {name: [CallbackQueryHandler(change_setting(name))] for name, setting in settings.items()}
    states[settings_state] = [CallbackQueryHandler(send_changer)]
    return states

add_setting('interface', _('interface language'),
            _('Please choose preferred interface language.'),
            _('Change interface language'), INTERFACE_LANGUAGES, 'en_us')
add_setting('voca', _('VocaDB'),
            _('Please choose preferred VocaDB language.\n'
              'Default refers to the language the artist indented.'),
            _('Change VocaDB language'), VOCADB_LANGUAGES, 'English')
# TODO:: Change msg
add_setting('originals', _('originals only'),
            _('Would you like to only show original songs when searching via !s or /song?'),
            _('Change originals only'), ON_OFF, 'False')
<|endoftext|>


<commit_before>"""
This module tests the text frontend module (pyqode.core.frontend.text)
"""
import os
import sys

from PyQt4 import QtGui
from PyQt4.QtTest import QTest

import pytest
from pyqode.core import frontend
from ..helpers import cwd_at, wait_for_connected

app = None
editor = None
window = None

def process_events():
    global app
    app.processEvents()

@cwd_at('test')
def setup_module():
    """
    Setup a QApplication and QCodeEdit which open the client module code
    """
    global app, editor, window
    app = QtGui.QApplication(sys.argv)
    window = QtGui.QMainWindow()
    editor = frontend.QCodeEdit(window)
    window.setCentralWidget(editor)
    window.resize(800, 600)
    frontend.open_file(editor, __file__)
    window.show()
    frontend.start_server(editor, os.path.join(os.getcwd(), 'server.py'))
    wait_for_connected(editor)

def teardown_module():
    """
    Close server and exit QApplication
    """
    global editor, app
    frontend.stop_server(editor)
    app.exit(0)
    QTest.qWait(1000)
    del editor
    del app

def test_line_count():
    global editor
    with open(__file__, 'r') as f:
        nb_lines = len(f.read().splitlines()) + 1
    assert frontend.line_count(editor) == nb_lines

def test_goto_line():
    global editor, window
    QTest.qWaitForWindowShown(window)
    assert editor.textCursor().blockNumber() == 0
    assert editor.textCursor().columnNumber() == 0
    cursor = frontend.goto_line(editor, 2, 0, move=False)
    process_events()
    assert editor.textCursor().blockNumber() != cursor.blockNumber()
    assert editor.textCursor().columnNumber() == cursor.columnNumber()
    cursor = frontend.goto_line(editor, 10, move=True)
    process_events()
    assert editor.textCursor().blockNumber() == cursor.blockNumber() == 9
    assert editor.textCursor().columnNumber() == cursor.columnNumber() == 0
    assert frontend.current_line_nbr(editor) == 10
    assert frontend.current_column_nbr(editor) == 0

def test_selected_text():
    global editor
    frontend.goto_line(editor, 2, 1, move=True)
    process_events()
    assert frontend.word_under_cursor(editor).selectedText() == 'T'
    assert frontend.word_under_cursor(
        editor, select_whole_word=True).selectedText() == 'This'

def test_line_text():
    global editor
    frontend.goto_line(editor, 2, 0, move=True)
    assert frontend.current_line_text(editor) == __doc__.splitlines()[1]

def test_set_line_text():
    global editor
    frontend.set_line_text(editor, 2, 'haha')
    frontend.goto_line(editor, 2, 0, move=True)
    assert frontend.current_line_text(editor) == 'haha'

def test_remove_last_line():
    global editor
    count = frontend.line_count(editor)
    frontend.remove_last_line(editor)
    assert frontend.line_count(editor) == count - 1

def test_clean_document():
    global editor
    count = frontend.line_count(editor) + 1
    editor.appendPlainText("\n\n\n")
    assert frontend.line_count(editor) == count + 3
    frontend.clean_document(editor)
    process_events()
    assert frontend.line_count(editor) == count

def test_select_lines():
    global editor
    frontend.select_lines(editor, 1, 5)
    process_events()
    QTest.qWait(1000)
    assert frontend.selection_range(editor) == (1, 5)

def test_line_pos_line_nbr():
    global editor
    # ensure we are at the top of the document
    frontend.goto_line(editor, 1, 0, move=True)
    process_events()
    pos = frontend.line_pos_from_number(editor, 2)
    assert pos is not None
    nbr = frontend.line_nbr_from_position(editor, pos)
    assert nbr == 2

def test_open_file():
    global editor
    frontend.open_file(editor, __file__)
    assert editor.file_path == __file__
    assert editor.mime_type == 'text/x-python'

def test_save_file():
    global editor
    path = os.path.join(os.getcwd(), 'tmp.py')
    # set line text to force change encoding
    frontend.set_line_text(editor, 2, 'éêà')
    QTest.qWait(1000)
    frontend.save_to_file(editor, path=path, encoding='utf-8')
    assert os.path.exists(path)
    assert editor.file_encoding == 'utf-8'
    frontend.save_to_file(editor, path=path, encoding='latin-1')
    assert editor.file_encoding == 'latin-1'
    frontend.open_file(editor, path, detect_encoding_func=None,
                       default_encoding='latin-1')
    QTest.qWait(1000)
    assert editor.file_encoding == 'latin-1'
    os.remove('tmp.py')
    frontend.open_file(editor, __file__)

def test_mark_whole_doc_dirty():
    global editor
    frontend.mark_whole_doc_dirty(editor)

src = """def test_mark_whole_doc_dirty():
    global editor
    frontend.mark_whole_doc_dirty(editor)
"""

def test_line_indent():
    global editor
    editor.setPlainText(src, 'text/x-python', 'utf-8')
    assert frontend.line_indent(editor, 1) == 0
    assert frontend.line_indent(editor, 2) == 4
    frontend.open_file(editor, __file__)
    assert frontend.line_indent(editor, frontend.line_count(editor) - 1) == 4

def test_right_word():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 2)
    assert frontend.get_right_word(editor) == 'This'

def test_right_char():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 2)
    assert frontend.get_right_character(editor) == 'T'

def test_insert_text():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 2)
    frontend.insert_text(editor, 'haha', keep_position=True)
    assert frontend.get_right_word(editor) == 'hahaThis'
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 2)
    frontend.insert_text(editor, 'haha', keep_position=False)
    assert frontend.get_right_word(editor) == 'This'
    assert frontend.line_text(editor, 2).startswith('hahaThis')

def test_clear_selection():
    global editor
    frontend.open_file(editor, __file__)
    frontend.select_lines(editor, 1, 2)
    assert frontend.selected_text(editor) != ''
    frontend.clear_selection(editor)
    assert frontend.selected_text(editor) == ''

def test_move_right():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 2)
    frontend.move_right(editor)
    assert frontend.get_right_character(editor) == 'h'

def test_to_upper():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 2)
    assert frontend.get_right_word(editor) == 'This'
    frontend.select_lines(editor, 2, 2)
    frontend.selected_text_to_upper(editor)
    frontend.goto_line(editor, 2)
    assert frontend.get_right_word(editor) == 'THIS'

def test_to_lower():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 2)
    assert frontend.get_right_word(editor) == 'This'
    frontend.select_lines(editor, 2, 2)
    frontend.selected_text_to_lower(editor)
    frontend.goto_line(editor, 2)
    assert frontend.get_right_word(editor) == 'this'
<commit_msg>Add a test for search_text<commit_after># -*- coding: utf-8 -*-
"""
This module tests the text frontend module (pyqode.core.frontend.text)
"""
import os
import sys

from PyQt4 import QtGui
from PyQt4.QtTest import QTest

import pytest
from pyqode.core import frontend
from ..helpers import cwd_at, wait_for_connected

app = None
editor = None
window = None

def process_events():
    global app
    app.processEvents()

@cwd_at('test')
def setup_module():
    """
    Setup a QApplication and QCodeEdit which open the client module code
    """
    global app, editor, window
    app = QtGui.QApplication(sys.argv)
    window = QtGui.QMainWindow()
    editor = frontend.QCodeEdit(window)
    window.setCentralWidget(editor)
    window.resize(800, 600)
    frontend.open_file(editor, __file__)
    window.show()
    frontend.start_server(editor, os.path.join(os.getcwd(), 'server.py'))
    wait_for_connected(editor)

def teardown_module():
    """
    Close server and exit QApplication
    """
    global editor, app
    frontend.stop_server(editor)
    app.exit(0)
    QTest.qWait(1000)
    del editor
    del app

def test_line_count():
    global editor
    with open(__file__, 'r') as f:
        nb_lines = len(f.read().splitlines()) + 1
    assert frontend.line_count(editor) == nb_lines

def test_goto_line():
    global editor, window
    QTest.qWaitForWindowShown(window)
    assert editor.textCursor().blockNumber() == 0
    assert editor.textCursor().columnNumber() == 0
    cursor = frontend.goto_line(editor, 3, 0, move=False)
    process_events()
    assert editor.textCursor().blockNumber() != cursor.blockNumber()
    assert editor.textCursor().columnNumber() == cursor.columnNumber()
    cursor = frontend.goto_line(editor, 10, move=True)
    process_events()
    assert editor.textCursor().blockNumber() == cursor.blockNumber() == 9
    assert editor.textCursor().columnNumber() == cursor.columnNumber() == 0
    assert frontend.current_line_nbr(editor) == 10
    assert frontend.current_column_nbr(editor) == 0

def test_selected_text():
    global editor
    frontend.goto_line(editor, 3, 1, move=True)
    process_events()
    assert frontend.word_under_cursor(editor).selectedText() == 'T'
    assert frontend.word_under_cursor(
        editor, select_whole_word=True).selectedText() == 'This'

def test_line_text():
    global editor
    frontend.goto_line(editor, 3, 0, move=True)
    assert frontend.current_line_text(editor) == __doc__.splitlines()[1]

def test_set_line_text():
    global editor
    frontend.set_line_text(editor, 3, 'haha')
    frontend.goto_line(editor, 3, 0, move=True)
    assert frontend.current_line_text(editor) == 'haha'

def test_remove_last_line():
    global editor
    count = frontend.line_count(editor)
    frontend.remove_last_line(editor)
    assert frontend.line_count(editor) == count - 1

def test_clean_document():
    global editor
    count = frontend.line_count(editor) + 1
    editor.appendPlainText("\n\n\n")
    assert frontend.line_count(editor) == count + 3
    frontend.clean_document(editor)
    process_events()
    assert frontend.line_count(editor) == count

def test_select_lines():
    global editor
    frontend.select_lines(editor, 1, 5)
    process_events()
    QTest.qWait(1000)
    assert frontend.selection_range(editor) == (1, 5)

def test_line_pos_line_nbr():
    global editor
    # ensure we are at the top of the document
    frontend.goto_line(editor, 1, 0, move=True)
    process_events()
    pos = frontend.line_pos_from_number(editor, 3)
    assert pos is not None
    nbr = frontend.line_nbr_from_position(editor, pos)
    assert nbr == 3

def test_open_file():
    global editor
    frontend.open_file(editor, __file__)
    assert editor.file_path == __file__
    assert editor.mime_type == 'text/x-python'

def test_save_file():
    global editor
    path = os.path.join(os.getcwd(), 'tmp.py')
    # set line text to force change encoding
    frontend.set_line_text(editor, 3, 'éêê')
    QTest.qWait(1000)
    frontend.save_to_file(editor, path=path, encoding='utf-8')
    assert os.path.exists(path)
    assert editor.file_encoding == 'utf-8'
    frontend.save_to_file(editor, path=path, encoding='latin-1')
    assert editor.file_encoding == 'latin-1'
    frontend.open_file(editor, path, detect_encoding_func=None,
                       default_encoding='latin-1')
    QTest.qWait(1000)
    assert editor.file_encoding == 'latin-1'
    os.remove('tmp.py')
    frontend.open_file(editor, __file__)

def test_mark_whole_doc_dirty():
    global editor
    frontend.mark_whole_doc_dirty(editor)

src = """def test_mark_whole_doc_dirty():
    global editor
    frontend.mark_whole_doc_dirty(editor)
"""

def test_line_indent():
    global editor
    editor.setPlainText(src, 'text/x-python', 'utf-8')
    assert frontend.line_indent(editor, 1) == 0
    assert frontend.line_indent(editor, 2) == 4
    frontend.open_file(editor, __file__)
    assert frontend.line_indent(editor, frontend.line_count(editor) - 1) == 4

def test_right_word():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 3)
    assert frontend.get_right_word(editor) == 'This'

def test_right_char():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 3)
    assert frontend.get_right_character(editor) == 'T'

def test_insert_text():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 3)
    frontend.insert_text(editor, 'haha', keep_position=True)
    assert frontend.get_right_word(editor) == 'hahaThis'
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 3)
    frontend.insert_text(editor, 'haha', keep_position=False)
    assert frontend.get_right_word(editor) == 'This'
    assert frontend.line_text(editor, 3).startswith('hahaThis')

def test_clear_selection():
    global editor
    frontend.open_file(editor, __file__)
    frontend.select_lines(editor, 1, 3)
    assert frontend.selected_text(editor) != ''
    frontend.clear_selection(editor)
    assert frontend.selected_text(editor) == ''

def test_move_right():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 3)
    frontend.move_right(editor)
    assert frontend.get_right_character(editor) == 'h'

def test_to_upper():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 3)
    assert frontend.get_right_word(editor) == 'This'
    frontend.select_lines(editor, 3, 2)
    frontend.selected_text_to_upper(editor)
    frontend.goto_line(editor, 3)
    assert frontend.get_right_word(editor) == 'THIS'

def test_to_lower():
    global editor
    frontend.open_file(editor, __file__)
    frontend.goto_line(editor, 3)
    assert frontend.get_right_word(editor) == 'This'
    frontend.select_lines(editor, 3, 2)
    frontend.selected_text_to_lower(editor)
    frontend.goto_line(editor, 3)
    assert frontend.get_right_word(editor) == 'this'

def test_search_text():
    global editor
    import os.path
    frontend.open_file(editor, os.path.__file__)
    occurences, index = frontend.search_text(
        editor.document(), editor.textCursor(),
        'import', QtGui.QTextDocument.FindCaseSensitively)
    assert index == -1
    assert len(occurences) == 11
<|endoftext|>


<commit_before>#  -*- coding: utf-8 -*-
#  vim: tabstop=4 shiftwidth=4 softtabstop=4

#  Copyright (c) 2018, GEM Foundation

#  OpenQuake is free software: you can redistribute it and/or modify it
#  under the terms of the GNU Affero General Public License as published
#  by the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

#  OpenQuake is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Affero General Public License for more details.

#  You should have received a copy of the GNU Affero General Public License
#  along with OpenQuake.  If not, see <http://www.gnu.org/licenses/>.

import operator
from openquake.baselib.general import block_splitter
from openquake.hazardlib.geo.utils import get_bounding_box
from openquake.hazardlib.source.base import ParametricSeismicSource
from openquake.hazardlib import mfd

MINWEIGHT = 100

class RuptureCollectionSource(ParametricSeismicSource):
    """
    A parametric source obtained from the splitting of a ComplexFaultSource
    """
    # the mosaic test for Canada is sensitive to such _slots_
    _slots_ = ['source_id', 'name', 'tectonic_region_type', 'num_ruptures',
               'min_mag', 'mfd']

    MODIFICATIONS = set()
    RUPTURE_WEIGHT = 4.0  # the same as ComplexFaultSources

    def __init__(self, source_id, name, tectonic_region_type, mfd, ruptures):
        self.source_id = source_id
        self.name = name  # used in disagg
        self.tectonic_region_type = tectonic_region_type
        self.mfd = mfd
        self.ruptures = ruptures
        self.num_ruptures = len(ruptures)

    def count_ruptures(self):
        return self.num_ruptures

    def iter_ruptures(self):
        return iter(self.ruptures)

    def get_bounding_box(self, maxdist):
        """
        Bounding box containing all the hypocenters, enlarged by the
        maximum distance
        """
        locations = [rup.hypocenter for rup in self.ruptures]
        return get_bounding_box(locations, maxdist)

def split(src, chunksize=MINWEIGHT):
    """
    Split a complex fault source in chunks
    """
    for i, block in enumerate(block_splitter(src.iter_ruptures(), chunksize,
                                             kind=operator.attrgetter('mag'))):
        rup = block[0]
        source_id = '%s:%d' % (src.source_id, i)
        amfd = mfd.ArbitraryMFD([rup.mag], [rup.mag_occ_rate])
        rcs = RuptureCollectionSource(
            source_id, src.name, src.tectonic_region_type, amfd, block)
        yield rcs
<commit_msg>Fix<commit_after>#  -*- coding: utf-8 -*-
#  vim: tabstop=4 shiftwidth=4 softtabstop=4

#  Copyright (c) 2018, GEM Foundation

#  OpenQuake is free software: you can redistribute it and/or modify it
#  under the terms of the GNU Affero General Public License as published
#  by the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.

#  OpenQuake is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Affero General Public License for more details.

#  You should have received a copy of the GNU Affero General Public License
#  along with OpenQuake.  If not, see <http://www.gnu.org/licenses/>.

import operator
from openquake.baselib.general import block_splitter
from openquake.hazardlib.geo.utils import get_bounding_box
from openquake.hazardlib.source.base import ParametricSeismicSource
from openquake.hazardlib import mfd

MINWEIGHT = 100

class RuptureCollectionSource(ParametricSeismicSource):
    """
    A parametric source obtained from the splitting of a ComplexFaultSource
    """
    # the mosaic test for Canada is sensitive to such _slots_
    _slots_ = ['source_id', 'name', 'tectonic_region_type', 'num_ruptures',
               'min_mag', 'mfd']

    MODIFICATIONS = set()
    RUPTURE_WEIGHT = 4.0  # the same as ComplexFaultSources

    def __init__(self, source_id, name, tectonic_region_type, mfd, ruptures):
        self.source_id = source_id
        self.name = name  # used in disagg
        self.tectonic_region_type = tectonic_region_type
        self.mfd = mfd
        self.ruptures = ruptures
        self.num_ruptures = len(ruptures)

    def count_ruptures(self):
        return self.num_ruptures

    def iter_ruptures(self):
        return iter(self.ruptures)

    def get_bounding_box(self, maxdist):
        """
        Bounding box containing all the hypocenters, enlarged by the
        maximum distance
        """
        locations = [rup.hypocenter for rup in self.ruptures]
        return get_bounding_box(locations, maxdist)

def split(src, chunksize=MINWEIGHT):
    """
    Split a complex fault source in chunks
    """
    for i, block in enumerate(block_splitter(src.iter_ruptures(), chunksize,
                                             key=operator.attrgetter('mag'))):
        rup = block[0]
        source_id = '%s:%d' % (src.source_id, i)
        amfd = mfd.ArbitraryMFD([rup.mag], [rup.mag_occ_rate])
        rcs = RuptureCollectionSource(
            source_id, src.name, src.tectonic_region_type, amfd, block)
        yield rcs
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Generated by Django 1.9.1 on 2016-02-04 11:42
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('rtei', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='rteipage',
            name='search_description_ar',
            field=models.TextField(blank=True, null=True, verbose_name='search description'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='search_description_en',
            field=models.TextField(blank=True, null=True, verbose_name='search description'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='search_description_es',
            field=models.TextField(blank=True, null=True, verbose_name='search description'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='search_description_fr',
            field=models.TextField(blank=True, null=True, verbose_name='search description'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='seo_title_ar',
            field=models.CharField(blank=True, help_text="Optional. 'Search Engine Friendly' title. This will appear at the top of the browser window.", max_length=255, null=True, verbose_name='page title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='seo_title_en',
            field=models.CharField(blank=True, help_text="Optional. 'Search Engine Friendly' title. This will appear at the top of the browser window.", max_length=255, null=True, verbose_name='page title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='seo_title_es',
            field=models.CharField(blank=True, help_text="Optional. 'Search Engine Friendly' title. This will appear at the top of the browser window.", max_length=255, null=True, verbose_name='page title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='seo_title_fr',
            field=models.CharField(blank=True, help_text="Optional. 'Search Engine Friendly' title. This will appear at the top of the browser window.", max_length=255, null=True, verbose_name='page title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='slug_ar',
            field=models.SlugField(help_text='The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/', max_length=255, null=True, verbose_name='slug'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='slug_en',
            field=models.SlugField(help_text='The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/', max_length=255, null=True, verbose_name='slug'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='slug_es',
            field=models.SlugField(help_text='The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/', max_length=255, null=True, verbose_name='slug'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='slug_fr',
            field=models.SlugField(help_text='The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/', max_length=255, null=True, verbose_name='slug'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='title_ar',
            field=models.CharField(help_text="The page title as you'd like it to be seen by the public", max_length=255, null=True, verbose_name='title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='title_en',
            field=models.CharField(help_text="The page title as you'd like it to be seen by the public", max_length=255, null=True, verbose_name='title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='title_es',
            field=models.CharField(help_text="The page title as you'd like it to be seen by the public", max_length=255, null=True, verbose_name='title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='title_fr',
            field=models.CharField(help_text="The page title as you'd like it to be seen by the public", max_length=255, null=True, verbose_name='title'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='url_path_ar',
            field=models.TextField(blank=True, editable=False, null=True, verbose_name='URL path'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='url_path_en',
            field=models.TextField(blank=True, editable=False, null=True, verbose_name='URL path'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='url_path_es',
            field=models.TextField(blank=True, editable=False, null=True, verbose_name='URL path'),
        ),
        migrations.AddField(
            model_name='rteipage',
            name='url_path_fr',
            field=models.TextField(blank=True, editable=False, null=True, verbose_name='URL path'),
        ),
    ]
<commit_msg>Remove migration as fields are already added in 0001<commit_after><|endoftext|>


<commit_before># -*- coding: cp949 -*-
import linear_algebra as la
import math
from pprint import pprint

def power_method(A, epsilon=1e-9):
    n = len(A)

    lambda_k = 0.0
    x0 = [1.0] * n

    counter = 0
    while True:
        y1 = la.multiply_matrix_vector(A, x0)

        lambda_k1 = abs(y1[0])
        for y1i in y1[1:]:
            if abs(y1i) > lambda_k1:
                lambda_k1 = abs(y1i)

        for k in xrange(n):
            x0[k] = y1[k] / lambda_k1

        if abs(lambda_k1 - lambda_k) < epsilon:
            break
        lambda_k = lambda_k1

        del y1
        counter += 1

    print("power method counter = %d" % counter)

    return lambda_k1, x0

def alloc_vec(n):
    return [0.0] * n

def alloc_mat(m, n):
    result = alloc_vec(m)
    for k in xrange(m):
        result[k] = alloc_vec(n)
    return result

def identity(n_row):
    identity_matrix = alloc_mat(n_row, n_row)
    for iPivot in xrange(n_row):
        identity_matrix[iPivot][iPivot] = 1.0
    return identity_matrix

def find_r_s(A0, n):
    r = 0
    s = 1
    ars = A0[r][s]
    abs_ars = abs(ars)

    for i in xrange(n - 1):
        for j in xrange(i + 1, n):
            aij = abs(A0[i][j])
            if aij > abs_ars:
                r = i
                s = j
                abs_ars = aij
                ars = A0[i][j]

    return abs_ars, ars, r, s

def calc_theta(ars, arr, ass):
    theta_rad = 0.5 * math.atan2((2.0 * ars), (arr - ass))
    return theta_rad

def jacobi_method(A, epsilon = 1e-9, bVerbose=False):
    n = len(A)

    A0 = alloc_mat(n, n)
    for i in xrange(n):
        for j in xrange(n):
            A0[i][j] = A[i][j]

    X = identity(n)

    #########################
    counter = 0
    while True:
        abs_ars, ars, r, s = find_r_s(A0, n)

        if abs_ars < epsilon:
            break
        if bVerbose:
            print "ars =", ars
            print "r, s =", r, s

        arr = A0[r][r]
        ass = A0[s][s]

        theta_rad = calc_theta(ars, arr, ass)
        if bVerbose:
            print "theta =", theta_rad * 180 / math.pi, "(deg)"
        cos = math.cos(theta_rad)
        sin = math.sin(theta_rad)

        for k in xrange(n):
            if k == r:
                pass
            elif k == s:
                pass
            else:
                akr = A0[k][r]
                aks = A0[k][s]
                A0[r][k] = akr * cos + aks * sin
                A0[s][k] = aks * cos - akr * sin

                A0[k][r] = A0[r][k]
                A0[k][s] = A0[s][k]

            xkr = X[k][r]
            xks = X[k][s]
            X[k][r] = xkr * cos + xks *sin
            X[k][s] = xks * cos - xkr *sin

        A0[r][r] = arr * cos*cos + 2.0 * ars * sin * cos + ass * sin*sin
        A0[s][s] = arr * sin*sin - 2.0 * ars * sin * cos + ass * cos*cos
        A0[r][s] = A0[s][r] = 0.0
        if bVerbose:
            print "A0"
            pprint(A0)
            print "X"
            pprint(X)
        counter += 1

    print("Jacobi method counter = %d" % counter)

    return A0, X

if "__main__" == __name__:
    A = [[2.0, 1.0],
         [1.0, 3.0]]

    lamda1, x1 = power_method(A)
    print "lambda =", lamda1
    print "x =", x1

    lamda, x = jacobi_method(A)
    print "lambda =", lamda
    print "x ="
    pprint(x)
<commit_msg>power_method() 주석 추가<commit_after># -*- coding: cp949 -*-
import linear_algebra as la
import math
from pprint import pprint

def power_method(A, epsilon=1e-9):
    #  ũ
    n = len(A)

    #  ū ġ
    lambda_k = 0.0
    #  ġ  ͸
    x0 = [1.0] * n

    counter = 0
    while True:
        #
        y1 = la.multiply_matrix_vector(A, x0)

        # y1 Ϳ 밪  ū Ҹ ã
        lambda_k1 = abs(y1[0])
        for y1i in y1[1:]:
            if abs(y1i) > lambda_k1:
                lambda_k1 = abs(y1i)

        #  ã  y1  Ҹ  x Ϳ
        # " ã  y1  normalize Ѵ"
        for k in xrange(n):
            x0[k] = y1[k] / lambda_k1

        #  ܰ  ū ġ
        if abs(lambda_k1 - lambda_k) < epsilon:
            break
        lambda_k = lambda_k1

        #  ޷ y1  ޸  ȯ
        del y1
        counter += 1

    print("power method counter = %d" % counter)

    return lambda_k1, x0

def alloc_vec(n):
    return [0.0] * n

def alloc_mat(m, n):
    result = alloc_vec(m)
    for k in xrange(m):
        result[k] = alloc_vec(n)
    return result

def identity(n_row):
    identity_matrix = alloc_mat(n_row, n_row)
    for iPivot in xrange(n_row):
        identity_matrix[iPivot][iPivot] = 1.0
    return identity_matrix

def find_r_s(A0, n):
    r = 0
    s = 1
    ars = A0[r][s]
    abs_ars = abs(ars)

    for i in xrange(n - 1):
        for j in xrange(i + 1, n):
            aij = abs(A0[i][j])
            if aij > abs_ars:
                r = i
                s = j
                abs_ars = aij
                ars = A0[i][j]

    return abs_ars, ars, r, s

def calc_theta(ars, arr, ass):
    theta_rad = 0.5 * math.atan2((2.0 * ars), (arr - ass))
    return theta_rad

def jacobi_method(A, epsilon = 1e-9, bVerbose=False):
    n = len(A)

    A0 = alloc_mat(n, n)
    for i in xrange(n):
        for j in xrange(n):
            A0[i][j] = A[i][j]

    X = identity(n)

    #########################
    counter = 0
    while True:
        abs_ars, ars, r, s = find_r_s(A0, n)

        if abs_ars < epsilon:
            break
        if bVerbose:
            print "ars =", ars
            print "r, s =", r, s

        arr = A0[r][r]
        ass = A0[s][s]

        theta_rad = calc_theta(ars, arr, ass)
        if bVerbose:
            print "theta =", theta_rad * 180 / math.pi, "(deg)"
        cos = math.cos(theta_rad)
        sin = math.sin(theta_rad)

        for k in xrange(n):
            if k == r:
                pass
            elif k == s:
                pass
            else:
                akr = A0[k][r]
                aks = A0[k][s]
                A0[r][k] = akr * cos + aks * sin
                A0[s][k] = aks * cos - akr * sin

                A0[k][r] = A0[r][k]
                A0[k][s] = A0[s][k]

            xkr = X[k][r]
            xks = X[k][s]
            X[k][r] = xkr * cos + xks *sin
            X[k][s] = xks * cos - xkr *sin

        A0[r][r] = arr * cos*cos + 2.0 * ars * sin * cos + ass * sin*sin
        A0[s][s] = arr * sin*sin - 2.0 * ars * sin * cos + ass * cos*cos
        A0[r][s] = A0[s][r] = 0.0
        if bVerbose:
            print "A0"
            pprint(A0)
            print "X"
            pprint(X)
        counter += 1

    print("Jacobi method counter = %d" % counter)

    return A0, X

if "__main__" == __name__:
    A = [[2.0, 1.0],
         [1.0, 3.0]]

    lamda1, x1 = power_method(A)
    print "lambda =", lamda1
    print "x =", x1

    lamda, x = jacobi_method(A)
    print "lambda =", lamda
    print "x ="
    pprint(x)
<|endoftext|>


<commit_before>from __future__ import absolute_import

import h5py
import numpy

from .common import ut, TestCase

@ut.skipUnless(h5py.version.hdf5_version_tuple >= (1, 8, 11), 'Direct Chunk Writing requires HDF5 >= 1.8.11')
class TestWriteDirectChunk(TestCase):
    def test_write_direct_chunk(self):

        filename = self.mktemp().encode()
        filehandle = h5py.File(filename, "w")

        dataset = filehandle.create_dataset("data", (100, 100, 100),
                                            maxshape=(None, 100, 100),
                                            chunks=(1, 100, 100),
                                            dtype='float32')

        # writing
        array = numpy.zeros((10, 100, 100))
        for index in range(10):
            a = numpy.random.rand(100, 100).astype('float32')
            dataset.id.write_direct_chunk((index, 0, 0), a.tostring(), filter_mask=1)
            array[index] = a

        filehandle.close()

        # checking
        filehandle = h5py.File(filename, "r")
        for i in range(10):
            read_data = filehandle["data"][i]
            self.assertTrue(array[i] == read_data).all()
<commit_msg>TST: fix missing parenthesis around .all()<commit_after>from __future__ import absolute_import

import h5py
import numpy

from .common import ut, TestCase

@ut.skipUnless(h5py.version.hdf5_version_tuple >= (1, 8, 11), 'Direct Chunk Writing requires HDF5 >= 1.8.11')
class TestWriteDirectChunk(TestCase):
    def test_write_direct_chunk(self):

        filename = self.mktemp().encode()
        filehandle = h5py.File(filename, "w")

        dataset = filehandle.create_dataset("data", (100, 100, 100),
                                            maxshape=(None, 100, 100),
                                            chunks=(1, 100, 100),
                                            dtype='float32')

        # writing
        array = numpy.zeros((10, 100, 100))
        for index in range(10):
            a = numpy.random.rand(100, 100).astype('float32')
            dataset.id.write_direct_chunk((index, 0, 0), a.tostring(), filter_mask=1)
            array[index] = a

        filehandle.close()

        # checking
        filehandle = h5py.File(filename, "r")
        for i in range(10):
            read_data = filehandle["data"][i]
            self.assertTrue((array[i] == read_data).all())
<|endoftext|>


<commit_before>import json

from django.shortcuts import get_object_or_404
from django.core.exceptions import ObjectDoesNotExist
from django.utils.feedgenerator import Atom1Feed, rfc3339_date
from django.contrib.contenttypes.models import ContentType
from django.contrib.syndication.views import Feed, add_domain
from django.contrib.sites.models import Site
from django.utils.encoding import force_text
from django.utils.six import text_type
from django.utils import datetime_safe
from django.views.generic import View
from django.http import HttpResponse, Http404

try:
    from django.core.urlresolvers import reverse
except ImportError:
    from django.urls import reverse

from actstream.models import Action, model_stream, user_stream, any_stream

class AbstractActivityStream(object):
    """
    Abstract base class for all stream rendering.
    Supports hooks for fetching streams and formatting actions.
    """
    def get_stream(self, *args, **kwargs):
        """
        Returns a stream method to use.
        """
        raise NotImplementedError

    def get_object(self, *args, **kwargs):
        """
        Returns the object (eg user or actor) that the stream is for.
        """
        raise NotImplementedError

    def items(self, *args, **kwargs):
        """
        Returns a queryset of Actions to use based on the stream method and object.
        """
        return self.get_stream()(self.get_object(*args, **kwargs))

    def get_uri(self, action, obj=None, date=None):
        """
        Returns an RFC3987 IRI ID for the given object, action and date.
        """
        if date is None:
            date = action.timestamp
        date = datetime_safe.new_datetime(date).strftime('%Y-%m-%d')
        return 'tag:%s,%s:%s' % (Site.objects.get_current().domain, date,
                                 self.get_url(action, obj, False))

    def get_url(self, action, obj=None, domain=True):
        """
        Returns an RFC3987 IRI for a HTML representation of the given object, action.
        If domain is true, the current site's domain will be added.
        """
        if not obj:
            url = reverse('actstream_detail', None, (action.pk,))
        elif hasattr(obj, 'get_absolute_url'):
            url = obj.get_absolute_url()
        else:
            ctype = ContentType.objects.get_for_model(obj)
            url = reverse('actstream_actor', None, (ctype.pk, obj.pk))
        if domain:
            return add_domain(Site.objects.get_current().domain, url)
        return url

    def format(self, action):
        """
        Returns a formatted dictionary for the given action.
        """
        item = {
            'id': self.get_uri(action),
            'url': self.get_url(action),
            'verb': action.verb,
            'published': rfc3339_date(action.timestamp),
            'actor': self.format_actor(action),
            'title': text_type(action),
        }
        if action.description:
            item['content'] = action.description
        if action.target:
            item['target'] = self.format_target(action)
        if action.action_object:
            item['object'] = self.format_action_object(action)
        return item

    def format_item(self, action, item_type='actor'):
        """
        Returns a formatted dictionary for an individual item based on the action and item_type.
        """
        obj = getattr(action, item_type)
        return {
            'id': self.get_uri(action, obj),
            'url': self.get_url(action, obj),
            'objectType': ContentType.objects.get_for_model(obj).name,
            'displayName': text_type(obj)
        }

    def format_actor(self, action):
        """
        Returns a formatted dictionary for the actor of the action.
        """
        return self.format_item(action)

    def format_target(self, action):
        """
        Returns a formatted dictionary for the target of the action.
        """
        return self.format_item(action, 'target')

    def format_action_object(self, action):
        """
        Returns a formatted dictionary for the action object of the action.
        """
        return self.format_item(action, 'action_object')

class ActivityStreamsAtomFeed(Atom1Feed):
    """
    Feed rendering class for the v1.0 Atom Activity Stream Spec
    """
    def root_attributes(self):
        attrs = super(ActivityStreamsAtomFeed, self).root_attributes()
        attrs['xmlns:activity'] = 'http://activitystrea.ms/spec/1.0/'
        return attrs

    def add_root_elements(self, handler):
        super(ActivityStreamsAtomFeed, self).add_root_elements(handler)

    def quick_elem(self, handler, key, value):
        if key == 'link':
            handler.addQuickElement(key, None, {
                'href': value, 'type': 'text/html', 'rel': 'alternate'})
        else:
            handler.addQuickElement(key, value)

    def item_quick_handler(self, handler, name, item):
        handler.startElement(name, {})
        for key, value in item.items():
            self.quick_elem(handler, key, value)
        handler.endElement(name)

    def add_item_elements(self, handler, item):
        item.pop('unique_id')
        actor = item.pop('actor')
        target = item.pop('target', None)
        action_object = item.pop('action_object', None)
        content = item.pop('content', None)

        if content:
            handler.addQuickElement('content', content, {'type': 'html'})

        for key, value in item.items():
            if value:
                self.quick_elem(handler, key, value)

        self.item_quick_handler(handler, 'author', actor)

        if action_object:
            self.item_quick_handler(handler, 'activity:object', action_object)

        if target:
            self.item_quick_handler(handler, 'activity:target', target)

class ActivityStreamsBaseFeed(AbstractActivityStream, Feed):

    def feed_extra_kwargs(self, obj):
        """
        Returns an extra keyword arguments dictionary that is used when
        initializing the feed generator.
        """
        return {}

    def item_extra_kwargs(self, action):
        """
        Returns an extra keyword arguments dictionary that is used with
        the `add_item` call of the feed generator.
        Add the 'content' field of the 'Entry' item, to be used by the custom
        feed generator.
        """
        item = self.format(action)
        item.pop('title', None)
        item['uri'] = item.pop('url')
        item['activity:verb'] = item.pop('verb')
        return item

    def format_item(self, action, item_type='actor'):
        name = item_type == 'actor' and 'name' or 'title'
        item = super(ActivityStreamsBaseFeed, self).format_item(action, item_type)
        item[name] = item.pop('displayName')
        item['activity:object-type'] = item.pop('objectType')
        item.pop('url')
        return item

    def item_link(self, action):
        return self.get_url(action)

    def item_description(self, action):
        if action.description:
            return force_text(action.description)

    def items(self, obj):
        return self.get_stream()(obj)[:30]

class JSONActivityFeed(AbstractActivityStream, View):
    """
    Feed that generates feeds compatible with the v1.0 JSON Activity Stream spec
    """
    def dispatch(self, request, *args, **kwargs):
        return HttpResponse(self.serialize(request, *args, **kwargs),
                            content_type='application/json')

    def serialize(self, request, *args, **kwargs):
        items = self.items(request, *args, **kwargs)
        return json.dumps({
            'totalItems': len(items),
            'items': [self.format(action) for action in items]
        }, indent=4 if 'pretty' in request.GET or 'pretty' in request.POST else None)

class ModelActivityMixin(object):

    def get_object(self, request, content_type_id):
        return get_object_or_404(ContentType, pk=content_type_id).model_class()

    def get_stream(self):
        return model_stream

class ObjectActivityMixin(object):

    def get_object(self, request, content_type_id, object_id):
        ct = get_object_or_404(ContentType, pk=content_type_id)
        try:
            obj = ct.get_object_for_this_type(pk=object_id)
        except ObjectDoesNotExist:
            raise Http404('No %s matches the given query.' % ct.model_class()._meta.object_name)
        return obj

    def get_stream(self):
        return any_stream

class UserActivityMixin(object):

    def get_object(self, request):
        if request.user.is_authenticated():
            return request.user

    def get_stream(self):
        return user_stream

class CustomStreamMixin(object):
    name = None

    def get_object(self):
        return

    def get_stream(self):
        return getattr(Action.objects, self.name)

    def items(self, *args, **kwargs):
        return self.get_stream()(*args[1:], **kwargs)

class ModelActivityFeed(ModelActivityMixin, ActivityStreamsBaseFeed):

    def title(self, model):
        return 'Activity feed from %s' % model.__name__

    def link(self, model):
        ctype = ContentType.objects.get_for_model(model)
        return reverse('actstream_model', None, (ctype.pk,))

    def description(self, model):
        return 'Public activities of %s' % model.__name__

class ObjectActivityFeed(ObjectActivityMixin, ActivityStreamsBaseFeed):
    def title(self, obj):
        return 'Activity for %s' % obj

    def link(self, obj):
        return self.get_url(obj)

    def description(self, obj):
        return 'Activity for %s' % obj

class UserActivityFeed(UserActivityMixin, ActivityStreamsBaseFeed):

    def title(self, user):
        return 'Activity feed for your followed actors'

    def link(self, user):
        if not user:
            return reverse('actstream')
        if hasattr(user, 'get_absolute_url'):
            return user.get_absolute_url()
        ctype = ContentType.objects.get_for_model(user)
        return reverse('actstream_actor', None, (ctype.pk, user.pk))

    def description(self, user):
        return 'Public activities of actors you follow'

class AtomUserActivityFeed(UserActivityFeed):
    """
    Atom feed of Activity for a given user (where actions are those that the given user follows).
    """
    feed_type = ActivityStreamsAtomFeed
    subtitle = UserActivityFeed.description

class AtomModelActivityFeed(ModelActivityFeed):
    """
    Atom feed of Activity for a given model (where actions involve the given model as any of the entities).
    """
    feed_type = ActivityStreamsAtomFeed
    subtitle = ModelActivityFeed.description

class AtomObjectActivityFeed(ObjectActivityFeed):
    """
    Atom feed of Activity for a given object (where actions involve the given object as any of the entities).
    """
    feed_type = ActivityStreamsAtomFeed
    subtitle = ObjectActivityFeed.description

class UserJSONActivityFeed(UserActivityMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a given user (where actions are those that the given user follows).
    """
    pass

class ModelJSONActivityFeed(ModelActivityMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a given model (where actions involve the given model as any of the entities).
    """
    pass

class ObjectJSONActivityFeed(ObjectActivityMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a given object (where actions involve the given object as any of the entities).
    """
    pass

class CustomJSONActivityFeed(CustomStreamMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a custom stream. self.name should be the name of the custom stream as defined in the Manager
    and arguments may be passed either in the url or when calling as_view(...)
    """
    pass
<commit_msg>used is_authenticated property instead of method<commit_after>import json

from django.shortcuts import get_object_or_404
from django.core.exceptions import ObjectDoesNotExist
from django.utils.feedgenerator import Atom1Feed, rfc3339_date
from django.contrib.contenttypes.models import ContentType
from django.contrib.syndication.views import Feed, add_domain
from django.contrib.sites.models import Site
from django.utils.encoding import force_text
from django.utils.six import text_type
from django.utils import datetime_safe
from django.views.generic import View
from django.http import HttpResponse, Http404

try:
    from django.core.urlresolvers import reverse
except ImportError:
    from django.urls import reverse

from actstream.models import Action, model_stream, user_stream, any_stream

class AbstractActivityStream(object):
    """
    Abstract base class for all stream rendering.
    Supports hooks for fetching streams and formatting actions.
    """
    def get_stream(self, *args, **kwargs):
        """
        Returns a stream method to use.
        """
        raise NotImplementedError

    def get_object(self, *args, **kwargs):
        """
        Returns the object (eg user or actor) that the stream is for.
        """
        raise NotImplementedError

    def items(self, *args, **kwargs):
        """
        Returns a queryset of Actions to use based on the stream method and object.
        """
        return self.get_stream()(self.get_object(*args, **kwargs))

    def get_uri(self, action, obj=None, date=None):
        """
        Returns an RFC3987 IRI ID for the given object, action and date.
        """
        if date is None:
            date = action.timestamp
        date = datetime_safe.new_datetime(date).strftime('%Y-%m-%d')
        return 'tag:%s,%s:%s' % (Site.objects.get_current().domain, date,
                                 self.get_url(action, obj, False))

    def get_url(self, action, obj=None, domain=True):
        """
        Returns an RFC3987 IRI for a HTML representation of the given object, action.
        If domain is true, the current site's domain will be added.
        """
        if not obj:
            url = reverse('actstream_detail', None, (action.pk,))
        elif hasattr(obj, 'get_absolute_url'):
            url = obj.get_absolute_url()
        else:
            ctype = ContentType.objects.get_for_model(obj)
            url = reverse('actstream_actor', None, (ctype.pk, obj.pk))
        if domain:
            return add_domain(Site.objects.get_current().domain, url)
        return url

    def format(self, action):
        """
        Returns a formatted dictionary for the given action.
        """
        item = {
            'id': self.get_uri(action),
            'url': self.get_url(action),
            'verb': action.verb,
            'published': rfc3339_date(action.timestamp),
            'actor': self.format_actor(action),
            'title': text_type(action),
        }
        if action.description:
            item['content'] = action.description
        if action.target:
            item['target'] = self.format_target(action)
        if action.action_object:
            item['object'] = self.format_action_object(action)
        return item

    def format_item(self, action, item_type='actor'):
        """
        Returns a formatted dictionary for an individual item based on the action and item_type.
        """
        obj = getattr(action, item_type)
        return {
            'id': self.get_uri(action, obj),
            'url': self.get_url(action, obj),
            'objectType': ContentType.objects.get_for_model(obj).name,
            'displayName': text_type(obj)
        }

    def format_actor(self, action):
        """
        Returns a formatted dictionary for the actor of the action.
        """
        return self.format_item(action)

    def format_target(self, action):
        """
        Returns a formatted dictionary for the target of the action.
        """
        return self.format_item(action, 'target')

    def format_action_object(self, action):
        """
        Returns a formatted dictionary for the action object of the action.
        """
        return self.format_item(action, 'action_object')

class ActivityStreamsAtomFeed(Atom1Feed):
    """
    Feed rendering class for the v1.0 Atom Activity Stream Spec
    """
    def root_attributes(self):
        attrs = super(ActivityStreamsAtomFeed, self).root_attributes()
        attrs['xmlns:activity'] = 'http://activitystrea.ms/spec/1.0/'
        return attrs

    def add_root_elements(self, handler):
        super(ActivityStreamsAtomFeed, self).add_root_elements(handler)

    def quick_elem(self, handler, key, value):
        if key == 'link':
            handler.addQuickElement(key, None, {
                'href': value, 'type': 'text/html', 'rel': 'alternate'})
        else:
            handler.addQuickElement(key, value)

    def item_quick_handler(self, handler, name, item):
        handler.startElement(name, {})
        for key, value in item.items():
            self.quick_elem(handler, key, value)
        handler.endElement(name)

    def add_item_elements(self, handler, item):
        item.pop('unique_id')
        actor = item.pop('actor')
        target = item.pop('target', None)
        action_object = item.pop('action_object', None)
        content = item.pop('content', None)

        if content:
            handler.addQuickElement('content', content, {'type': 'html'})

        for key, value in item.items():
            if value:
                self.quick_elem(handler, key, value)

        self.item_quick_handler(handler, 'author', actor)

        if action_object:
            self.item_quick_handler(handler, 'activity:object', action_object)

        if target:
            self.item_quick_handler(handler, 'activity:target', target)

class ActivityStreamsBaseFeed(AbstractActivityStream, Feed):

    def feed_extra_kwargs(self, obj):
        """
        Returns an extra keyword arguments dictionary that is used when
        initializing the feed generator.
        """
        return {}

    def item_extra_kwargs(self, action):
        """
        Returns an extra keyword arguments dictionary that is used with
        the `add_item` call of the feed generator.
        Add the 'content' field of the 'Entry' item, to be used by the custom
        feed generator.
        """
        item = self.format(action)
        item.pop('title', None)
        item['uri'] = item.pop('url')
        item['activity:verb'] = item.pop('verb')
        return item

    def format_item(self, action, item_type='actor'):
        name = item_type == 'actor' and 'name' or 'title'
        item = super(ActivityStreamsBaseFeed, self).format_item(action, item_type)
        item[name] = item.pop('displayName')
        item['activity:object-type'] = item.pop('objectType')
        item.pop('url')
        return item

    def item_link(self, action):
        return self.get_url(action)

    def item_description(self, action):
        if action.description:
            return force_text(action.description)

    def items(self, obj):
        return self.get_stream()(obj)[:30]

class JSONActivityFeed(AbstractActivityStream, View):
    """
    Feed that generates feeds compatible with the v1.0 JSON Activity Stream spec
    """
    def dispatch(self, request, *args, **kwargs):
        return HttpResponse(self.serialize(request, *args, **kwargs),
                            content_type='application/json')

    def serialize(self, request, *args, **kwargs):
        items = self.items(request, *args, **kwargs)
        return json.dumps({
            'totalItems': len(items),
            'items': [self.format(action) for action in items]
        }, indent=4 if 'pretty' in request.GET or 'pretty' in request.POST else None)

class ModelActivityMixin(object):

    def get_object(self, request, content_type_id):
        return get_object_or_404(ContentType, pk=content_type_id).model_class()

    def get_stream(self):
        return model_stream

class ObjectActivityMixin(object):

    def get_object(self, request, content_type_id, object_id):
        ct = get_object_or_404(ContentType, pk=content_type_id)
        try:
            obj = ct.get_object_for_this_type(pk=object_id)
        except ObjectDoesNotExist:
            raise Http404('No %s matches the given query.' % ct.model_class()._meta.object_name)
        return obj

    def get_stream(self):
        return any_stream

class UserActivityMixin(object):

    def get_object(self, request):
        if request.user.is_authenticated:
            return request.user

    def get_stream(self):
        return user_stream

class CustomStreamMixin(object):
    name = None

    def get_object(self):
        return

    def get_stream(self):
        return getattr(Action.objects, self.name)

    def items(self, *args, **kwargs):
        return self.get_stream()(*args[1:], **kwargs)

class ModelActivityFeed(ModelActivityMixin, ActivityStreamsBaseFeed):

    def title(self, model):
        return 'Activity feed from %s' % model.__name__

    def link(self, model):
        ctype = ContentType.objects.get_for_model(model)
        return reverse('actstream_model', None, (ctype.pk,))

    def description(self, model):
        return 'Public activities of %s' % model.__name__

class ObjectActivityFeed(ObjectActivityMixin, ActivityStreamsBaseFeed):
    def title(self, obj):
        return 'Activity for %s' % obj

    def link(self, obj):
        return self.get_url(obj)

    def description(self, obj):
        return 'Activity for %s' % obj

class UserActivityFeed(UserActivityMixin, ActivityStreamsBaseFeed):

    def title(self, user):
        return 'Activity feed for your followed actors'

    def link(self, user):
        if not user:
            return reverse('actstream')
        if hasattr(user, 'get_absolute_url'):
            return user.get_absolute_url()
        ctype = ContentType.objects.get_for_model(user)
        return reverse('actstream_actor', None, (ctype.pk, user.pk))

    def description(self, user):
        return 'Public activities of actors you follow'

class AtomUserActivityFeed(UserActivityFeed):
    """
    Atom feed of Activity for a given user (where actions are those that the given user follows).
    """
    feed_type = ActivityStreamsAtomFeed
    subtitle = UserActivityFeed.description

class AtomModelActivityFeed(ModelActivityFeed):
    """
    Atom feed of Activity for a given model (where actions involve the given model as any of the entities).
    """
    feed_type = ActivityStreamsAtomFeed
    subtitle = ModelActivityFeed.description

class AtomObjectActivityFeed(ObjectActivityFeed):
    """
    Atom feed of Activity for a given object (where actions involve the given object as any of the entities).
    """
    feed_type = ActivityStreamsAtomFeed
    subtitle = ObjectActivityFeed.description

class UserJSONActivityFeed(UserActivityMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a given user (where actions are those that the given user follows).
    """
    pass

class ModelJSONActivityFeed(ModelActivityMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a given model (where actions involve the given model as any of the entities).
    """
    pass

class ObjectJSONActivityFeed(ObjectActivityMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a given object (where actions involve the given object as any of the entities).
    """
    pass

class CustomJSONActivityFeed(CustomStreamMixin, JSONActivityFeed):
    """
    JSON feed of Activity for a custom stream. self.name should be the name of the custom stream as defined in the Manager
    and arguments may be passed either in the url or when calling as_view(...)
    """
    pass
<|endoftext|>