<commit_before>#!/usr/bin/env python3
# coding: utf-8
__author__ = 'Yee_172'
__data__ = '2017/9/26'
__all__ = ['alphabet', 'terminal_version_old', 'MainWin', 'app', 'sys']

import os
import sys
import pandas as pd
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import Qt, QCoreApplication, QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from GUI.main import Ui_Dialog
from Element import Word, Alphabet

PATH = './Lib/E_alphabet.csv'
app = QtWidgets.QApplication(sys.argv)

def read_in(csvfile):
    return pd.read_csv(csvfile).values

alphabet = Alphabet([Word(x) for x in read_in(PATH)])

def find_word(content):
    if not content:
        return None
    try:
        if isinstance(content, int):
            for each in alphabet.words:
                if each.num == content:
                    return each
        if isinstance(content, str):
            letter = content[0].upper()
            for each in alphabet.families[letter].words:
                if each.word.lower() == content.lower():
                    return each
    except:
        return None
    return None

def clear_screen():
    os.system('clear')

def random_word(letter='all'):
    return alphabet.get_random(letter)

def str_process(string):
    return string.translate(string.maketrans('', '', ' ,;()[]{}')).lower()

def definition_q(word):
    definition = input('Your definition: ')
    print()
    print('Your definition: %s' % definition)
    print('Real definition: %s' % word.definition)
    if str_process(word.definition) == str_process(definition):
        print('Exactly!')
    else:
        print('Not so good!')
    print()
    print('Sample sentence: %s' % word.get_sample())
    print('\n' * 17)

def terminal_version_old():
    MODE = 'SEARCH'
    RANDOM_LETTER = 'all'
    print('Initial mode is SEARCH mode!')
    while 1:
        if MODE.lower() == 'search':
            print()
            content = input('Your word or num: ')
            if content.lower() in ['q', 'quit', 'exit']:
                break
            if content.lower() in ['r', 'rand', 'random']:
                clear_screen()
                print('You are in RANDOM mode now!')
                MODE = 'RANDOM'
                continue
            try:
                content = int(content)
            except:
                pass
            word = find_word(content)
            if word is None:
                continue
            print('\nYour word:       %s' % word.word)
            definition_q(word)
        if MODE.lower() == 'random':
            print()
            content = input('Your random letter: ')
            if content.lower() in ['q', 'quit', 'exit']:
                break
            if content.lower() in ['s', 'sear', 'search']:
                clear_screen()
                print('You are in SEARCH mode now!')
                MODE = 'SEARCH'
                continue
            try:
                word = random_word(content)
                if word is None:
                    print('Word not available! Rolling back!')
                    raise
                RANDOM_LETTER = content
            except:
                word = random_word(RANDOM_LETTER)
            print('        #      : %d' % word.num)
            print('Your word      : %s' % word.word)
            definition_q(word)

class MainWin(QtWidgets.QWidget, Ui_Dialog):
    MODE = 'SEARCH'
    WORD = None
    CODE = 0
    MORE = 0
    LENGTH = 60
    CONTAIN = 0
    COMMANDING = 1
    WORDLIST_NUM = 0
    HISTORY_NUM = 0
    SEARCH_CONTENT = ''
    EMPTY_MODEL = QtGui.QStandardItemModel()

    def __init__(self):
        super(MainWin, self).__init__()
        self.setupUi(self)
        self.initializing()
        self.wordlist_show()

        self.web_viewer = QWebEngineView()
        self.web_viewer.setObjectName('web_viewer')
        # self.web_viewer.setGeometry(QtCore.QRect(800, 20, 360, 450))
        self.web_viewer.load(QUrl("http://www.baidu.com"))
        # self.web_viewer.setUrl(QUrl("http://www.baidu.com"))
        # self.web_viewer.show()

        self.button_show_wordlist.clicked.connect(self.wordlist_click)
        self.button_help.clicked.connect(self.show_help)
        self.button_clear.clicked.connect(self.clear)
        self.console.returnPressed.connect(self.console_operate)
        self.check_code.stateChanged.connect(self.code_update)
        self.check_more.stateChanged.connect(self.more_info)
        self.combo_box_mode.currentIndexChanged.connect(self.mode_update)
        self.search_box.textChanged.connect(self.search)
        self.show()

    def code_update(self):
        self.CODE = self.check_code.checkState()

    def mode_update(self):
        self.MODE = self.combo_box_mode.currentText()
        self.console_show_history.append('MODE changed into %s' % self.MODE)

    def more_info(self):
        self.MORE = self.check_more.checkState()
        if self.MORE:
            # self.resize(1200, 562)
            self.web_viewer.show()
        else:
            # self.resize(770, 562)
            pass

    def initializing(self):
        self.console_show_history.append('Initial mode is SEARCH MODE!')
        self.console_show_history.append('You can input word or num!')
        self.console_show_history.append('Input `help` for more commands available!')

    def search_words(self, content):
        result = []
        try:
            temp = int(content)
            if self.CONTAIN:
                for each in alphabet.words:
                    if content in '%03d' % each.num:
                        result.append(each)
                return result
            else:
                for each in alphabet.words:
                    if content == ('%03d' % each.num)[:len(content)]:
                        result.append(each)
                return result
        except:
            content = content.lower()
            if self.CONTAIN:
                for each in alphabet.words:
                    if content in each.word.lower():
                        result.append(each)
                return result
            else:
                for each in alphabet.words:
                    if content == each.word[:len(content)].lower():
                        result.append(each)
                return result

    def search(self):
        self.SEARCH_CONTENT = self.search_box.text()
        if self.SEARCH_CONTENT:
            if self.button_show_wordlist.text() == 'HIDE':
                self.wordlist_show(self.search_words(self.SEARCH_CONTENT))
        else:
            if self.button_show_wordlist.text() == 'HIDE':
                self.wordlist_show()

    def wordlist_click(self):
        content = self.button_show_wordlist.text()
        if content == 'SHOW':
            if self.SEARCH_CONTENT:
                self.wordlist_show(self.search_words(self.SEARCH_CONTENT))
            else:
                self.wordlist_show()
        if content == 'HIDE':
            self.wordlist_hide()

    def wordlist_show(self, words=alphabet.words):
        wordlist_model = QtGui.QStandardItemModel(0, 2, self)
        wordlist_model.setHeaderData(0, Qt.Horizontal, '#')
        wordlist_model.setHeaderData(1, Qt.Horizontal, 'WORD')
        self.wordlist.setModel(wordlist_model)
        self.wordlist.setColumnWidth(0, 40)
        self.wordlist.setColumnWidth(1, 30)
        self.WORDLIST_NUM = 0
        if words:
            for each in words:
                self.add_data(wordlist_model, '%03d' % each.num, each.word)
        _translate = QCoreApplication.translate
        self.button_show_wordlist.setText(_translate("Dialog", "HIDE"))

    def wordlist_hide(self):
        self.wordlist.setModel(self.EMPTY_MODEL)
        _translate = QCoreApplication.translate
        self.button_show_wordlist.setText(_translate("Dialog", "SHOW"))

    def add_data(self, model, num, word):
        model.insertRow(self.WORDLIST_NUM)
        model.setData(model.index(self.WORDLIST_NUM, 0), num)
        model.setData(model.index(self.WORDLIST_NUM, 1), word)
        self.WORDLIST_NUM += 1

    def show_help(self):
        self.console_show_history.append(''.center(self.LENGTH, '-'))
        self.console_show_history.append('help'.ljust(7) + '\t->\t' + 'Help information')
        self.console_show_history.append('clear'.ljust(7) + '\t->\t' + 'Clear all the history')
        self.console_show_history.append('mode'.ljust(7) + '\t->\t' + 'Show or change the mode')
        self.console_show_history.append(''.ljust(7) + '\t\t      Example: ' + 'mode random')
        self.console_show_history.append('show'.ljust(7) + '\t->\t' + 'Show the word list')
        self.console_show_history.append('hide'.ljust(7) + '\t->\t' + 'Hide the word list')
        self.console_show_history.append('code'.ljust(7) + '\t->\t' + 'Show more info')
        self.console_show_history.append('quit'.ljust(7) + '\t->\t' + 'Exit the program')
        self.console_show_history.append(''.center(self.LENGTH, '-'))

    def clear(self):
        self.HISTORY_NUM = 0
        self.WORD = None
        self.console_show_history.clear()
        self.info_clear()
        self.label_info.setText('')

    def console_operate(self):
        def read(content):
            content = content.lower()
            if self.WORD is None:
                if content == 'help':
                    self.show_help()
                elif content == 'clear':
                    self.clear()
                elif content[:4] == 'mode':
                    mode = str_process(content[4:])
                    if not mode:
                        mode_change()
                    elif mode in ['s', 'sear', 'search']:
                        mode_change('SEARCH')
                    elif mode in ['r', 'rand', 'random']:
                        mode_change('RANDOM')
                elif content == 'show':
                    self.wordlist_show()
                    self.console_show_history.append('Word list showed')
                elif content == 'hide':
                    self.wordlist_hide()
                    self.console_show_history.append('word list hid')
                elif content == 'quit':
                    self.close()
                elif self.MODE == 'SEARCH' and ' ' not in content:
                    try:
                        content = int(content)
                    except:
                        pass
                    self.WORD = find_word(content)
                    if self.WORD is None:
                        self.console_show_history.append('Undefined')
                    else:
                        self.info_clear()
                        self.label_word_show.setText(self.WORD.word)
                        self.label_info.setText('Definition of [%s] required' % self.WORD.word)
                elif self.MODE == 'RANDOM':  # TODO
                    self.WORD = alphabet.get_random()
                    self.info_clear()
                    self.label_word_show.setText(self.WORD.word)
                    self.label_info.setText('Definition of [%s] required' % self.WORD.word)
                else:
                    self.console_show_history.append('Undefined')
            else:
                search_q(self.WORD, content)
                self.WORD = None
                self.label_info.setText('')

        def mode_change(mode=''):
            if mode:
                self.MODE = mode
                self.combo_box_mode.setCurrentIndex({'SEARCH': 0, 'RANDOM': 1}[mode])
                self.console_show_history.append('MODE changed into %s' % self.MODE)
            else:
                self.console_show_history.append('MODE now is %s' % self.MODE)

        def search_q(word, definition):
            self.console_show_history.append(''.center(self.LENGTH, '-'))
            if str_process(word.definition) == str_process(definition):
                self.console_show_history.append(''
                                                 ''
                                                 '√'
                                                 '')
            else:
                self.console_show_history.append(''
                                                 ''
                                                 '×'
                                                 '')
            self.console_show_history.append('↓\tYour definition\t↓\n%s' % definition)
            self.console_show_history.append('%s\n↑\tReal definition\t↑' % word.definition)
            self.console_show_history.append(''.center(self.LENGTH, '-'))
            self.info_show(word)

        self.HISTORY_NUM += 1
        text = self.console.text()
        self.console.setText('')
        if self.CODE:
            self.console_show_history.append('[%d]>>> ' % self.HISTORY_NUM + text)
        read(text)

    def keyPressEvent(self, QKeyEvent):
        if QKeyEvent.key() == Qt.Key_Escape:
            self.close()

    def info_show(self, word):
        self.label_word_show.setText(word.word)
        self.label_def_show.setText(word.definition)
        self.label_samp_show.setText(word.html_sample())

    def info_clear(self):
        self.label_word_show.setText('')
        self.label_def_show.setText('')
        self.label_samp_show.setText('')
<commit_msg>update<commit_after>#!/usr/bin/env python3
# coding: utf-8
__author__ = 'Yee_172'
__data__ = '2017/9/26'
__all__ = ['alphabet', 'terminal_version_old', 'MainWin', 'app', 'sys']

import os
import sys
import pandas as pd
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtCore import Qt, QCoreApplication, QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWebChannel import QWebChannel
from GUI.main import Ui_Dialog
from Element import Word, Alphabet

PATH = './Lib/E_alphabet.csv'
app = QtWidgets.QApplication(sys.argv)

def read_in(csvfile):
    return pd.read_csv(csvfile).values

alphabet = Alphabet([Word(x) for x in read_in(PATH)])

def find_word(content):
    if not content:
        return None
    try:
        if isinstance(content, int):
            for each in alphabet.words:
                if each.num == content:
                    return each
        if isinstance(content, str):
            letter = content[0].upper()
            for each in alphabet.families[letter].words:
                if each.word.lower() == content.lower():
                    return each
    except:
        return None
    return None

def clear_screen():
    os.system('clear')

def random_word(letter='all'):
    return alphabet.get_random(letter)

def str_process(string):
    return string.translate(string.maketrans('', '', ' ,;()[]{}')).lower()

def definition_q(word):
    definition = input('Your definition: ')
    print()
    print('Your definition: %s' % definition)
    print('Real definition: %s' % word.definition)
    if str_process(word.definition) == str_process(definition):
        print('Exactly!')
    else:
        print('Not so good!')
    print()
    print('Sample sentence: %s' % word.get_sample())
    print('\n' * 17)

def terminal_version_old():
    MODE = 'SEARCH'
    RANDOM_LETTER = 'all'
    print('Initial mode is SEARCH mode!')
    while 1:
        if MODE.lower() == 'search':
            print()
            content = input('Your word or num: ')
            if content.lower() in ['q', 'quit', 'exit']:
                break
            if content.lower() in ['r', 'rand', 'random']:
                clear_screen()
                print('You are in RANDOM mode now!')
                MODE = 'RANDOM'
                continue
            try:
                content = int(content)
            except:
                pass
            word = find_word(content)
            if word is None:
                continue
            print('\nYour word:       %s' % word.word)
            definition_q(word)
        if MODE.lower() == 'random':
            print()
            content = input('Your random letter: ')
            if content.lower() in ['q', 'quit', 'exit']:
                break
            if content.lower() in ['s', 'sear', 'search']:
                clear_screen()
                print('You are in SEARCH mode now!')
                MODE = 'SEARCH'
                continue
            try:
                word = random_word(content)
                if word is None:
                    print('Word not available! Rolling back!')
                    raise
                RANDOM_LETTER = content
            except:
                word = random_word(RANDOM_LETTER)
            print('        #      : %d' % word.num)
            print('Your word      : %s' % word.word)
            definition_q(word)

class MainWin(QtWidgets.QWidget, Ui_Dialog):
    URL = ''
    MODE = 'SEARCH'
    WORD = None
    CODE = 0
    MORE = 0
    LENGTH = 60
    CONTAIN = 0
    COMMANDING = 1
    WORDLIST_NUM = 0
    HISTORY_NUM = 0
    SEARCH_CONTENT = ''
    EMPTY_MODEL = QtGui.QStandardItemModel()

    def __init__(self):
        super(MainWin, self).__init__()
        self.setupUi(self)
        self.initializing()
        self.wordlist_show()

        self.web_viewer = QWebEngineView()
        self.web_viewer.setObjectName('web_viewer')
        # self.channel = QWebChannel(self.web_viewer)
        # self.web_viewer.setGeometry(QtCore.QRect(800, 20, 360, 450))

        self.button_show_wordlist.clicked.connect(self.wordlist_click)
        self.button_help.clicked.connect(self.show_help)
        self.button_clear.clicked.connect(self.clear)
        self.console.returnPressed.connect(self.console_operate)
        self.check_code.stateChanged.connect(self.code_update)
        self.check_more.stateChanged.connect(self.more_info)
        self.combo_box_mode.currentIndexChanged.connect(self.mode_update)
        self.search_box.textChanged.connect(self.search)
        self.show()

    def code_update(self):
        self.CODE = self.check_code.checkState()

    def mode_update(self):
        self.MODE = self.combo_box_mode.currentText()
        self.console_show_history.append('MODE changed into %s' % self.MODE)

    def more_info(self):
        self.MORE = self.check_more.checkState()
        if self.MORE:
            # self.resize(1200, 562)
            if self.WORD is not None:
                self.URL = 'http://www.youdao.com/w/eng/%s' % self.WORD.word.lower()
            if self.URL:
                self.web_viewer.setUrl(QUrl(self.URL))
                self.web_viewer.show()
        else:
            # self.resize(770, 562)
            self.web_viewer.close()
            pass

    def initializing(self):
        self.console_show_history.append('Initial mode is SEARCH MODE!')
        self.console_show_history.append('You can input word or num!')
        self.console_show_history.append('Input `help` for more commands available!')

    def search_words(self, content):
        result = []
        try:
            temp = int(content)
            if self.CONTAIN:
                for each in alphabet.words:
                    if content in '%03d' % each.num:
                        result.append(each)
                return result
            else:
                for each in alphabet.words:
                    if content == ('%03d' % each.num)[:len(content)]:
                        result.append(each)
                return result
        except:
            content = content.lower()
            if self.CONTAIN:
                for each in alphabet.words:
                    if content in each.word.lower():
                        result.append(each)
                return result
            else:
                for each in alphabet.words:
                    if content == each.word[:len(content)].lower():
                        result.append(each)
                return result

    def search(self):
        self.SEARCH_CONTENT = self.search_box.text()
        if self.SEARCH_CONTENT:
            if self.button_show_wordlist.text() == 'HIDE':
                self.wordlist_show(self.search_words(self.SEARCH_CONTENT))
        else:
            if self.button_show_wordlist.text() == 'HIDE':
                self.wordlist_show()

    def wordlist_click(self):
        content = self.button_show_wordlist.text()
        if content == 'SHOW':
            if self.SEARCH_CONTENT:
                self.wordlist_show(self.search_words(self.SEARCH_CONTENT))
            else:
                self.wordlist_show()
        if content == 'HIDE':
            self.wordlist_hide()

    def wordlist_show(self, words=alphabet.words):
        wordlist_model = QtGui.QStandardItemModel(0, 2, self)
        wordlist_model.setHeaderData(0, Qt.Horizontal, '#')
        wordlist_model.setHeaderData(1, Qt.Horizontal, 'WORD')
        self.wordlist.setModel(wordlist_model)
        self.wordlist.setColumnWidth(0, 40)
        self.wordlist.setColumnWidth(1, 30)
        self.WORDLIST_NUM = 0
        if words:
            for each in words:
                self.add_data(wordlist_model, '%03d' % each.num, each.word)
        _translate = QCoreApplication.translate
        self.button_show_wordlist.setText(_translate("Dialog", "HIDE"))

    def wordlist_hide(self):
        self.wordlist.setModel(self.EMPTY_MODEL)
        _translate = QCoreApplication.translate
        self.button_show_wordlist.setText(_translate("Dialog", "SHOW"))

    def add_data(self, model, num, word):
        model.insertRow(self.WORDLIST_NUM)
        model.setData(model.index(self.WORDLIST_NUM, 0), num)
        model.setData(model.index(self.WORDLIST_NUM, 1), word)
        self.WORDLIST_NUM += 1

    def show_help(self):
        self.console_show_history.append(''.center(self.LENGTH, '-'))
        self.console_show_history.append('help'.ljust(7) + '\t->\t' + 'Help information')
        self.console_show_history.append('clear'.ljust(7) + '\t->\t' + 'Clear all the history')
        self.console_show_history.append('mode'.ljust(7) + '\t->\t' + 'Show or change the mode')
        self.console_show_history.append(''.ljust(7) + '\t\t      Example: ' + 'mode random')
        self.console_show_history.append('show'.ljust(7) + '\t->\t' + 'Show the word list')
        self.console_show_history.append('hide'.ljust(7) + '\t->\t' + 'Hide the word list')
        self.console_show_history.append('code'.ljust(7) + '\t->\t' + 'Show more info')
        self.console_show_history.append('quit'.ljust(7) + '\t->\t' + 'Exit the program')
        self.console_show_history.append(''.center(self.LENGTH, '-'))

    def clear(self):
        self.HISTORY_NUM = 0
        self.WORD = None
        self.console_show_history.clear()
        self.info_clear()
        self.label_info.setText('')

    def console_operate(self):
        def read(content):
            content = content.lower()
            if self.WORD is None:
                if content == 'help':
                    self.show_help()
                elif content == 'clear':
                    self.clear()
                elif content[:4] == 'mode':
                    mode = str_process(content[4:])
                    if not mode:
                        mode_change()
                    elif mode in ['s', 'sear', 'search']:
                        mode_change('SEARCH')
                    elif mode in ['r', 'rand', 'random']:
                        mode_change('RANDOM')
                elif content == 'show':
                    self.wordlist_show()
                    self.console_show_history.append('Word list showed')
                elif content == 'hide':
                    self.wordlist_hide()
                    self.console_show_history.append('word list hid')
                elif content == 'quit':
                    self.close()
                elif self.MODE == 'SEARCH' and ' ' not in content:
                    try:
                        content = int(content)
                    except:
                        pass
                    self.WORD = find_word(content)
                    if self.WORD is None:
                        self.console_show_history.append('Undefined')
                    else:
                        self.info_clear()
                        self.label_word_show.setText(self.WORD.word)
                        self.label_info.setText('Definition of [%s] required' % self.WORD.word)
                elif self.MODE == 'RANDOM':  # TODO
                    self.WORD = alphabet.get_random()
                    self.info_clear()
                    self.label_word_show.setText(self.WORD.word)
                    self.label_info.setText('Definition of [%s] required' % self.WORD.word)
                else:
                    self.console_show_history.append('Undefined')
            else:
                search_q(self.WORD, content)
                self.WORD = None
                self.label_info.setText('')

        def mode_change(mode=''):
            if mode:
                self.MODE = mode
                self.combo_box_mode.setCurrentIndex({'SEARCH': 0, 'RANDOM': 1}[mode])
                self.console_show_history.append('MODE changed into %s' % self.MODE)
            else:
                self.console_show_history.append('MODE now is %s' % self.MODE)

        def search_q(word, definition):
            self.console_show_history.append(''.center(self.LENGTH, '-'))
            if str_process(word.definition) == str_process(definition):
                self.console_show_history.append(''
                                                 ''
                                                 '√'
                                                 '')
            else:
                self.console_show_history.append(''
                                                 ''
                                                 '×'
                                                 '')
            self.console_show_history.append('↓\tYour definition\t↓\n%s' % definition)
            self.console_show_history.append('%s\n↑\tReal definition\t↑' % word.definition)
            self.console_show_history.append(''.center(self.LENGTH, '-'))
            self.info_show(word)

        self.HISTORY_NUM += 1
        text = self.console.text()
        self.console.setText('')
        if self.CODE:
            self.console_show_history.append('[%d]>>> ' % self.HISTORY_NUM + text)
        read(text)

    def keyPressEvent(self, QKeyEvent):
        if QKeyEvent.key() == Qt.Key_Escape:
            self.close()

    def info_show(self, word):
        self.label_word_show.setText(word.word)
        self.label_def_show.setText(word.definition)
        self.label_samp_show.setText(word.html_sample())

    def info_clear(self):
        self.label_word_show.setText('')
        self.label_def_show.setText('')
        self.label_samp_show.setText('')
<|endoftext|>


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

# Copyright (c) 2015-2016:
#   Matthieu Estrada, ttamalfor@gmail.com
#
# This file is part of (AlignakApp).
#
# (AlignakApp) 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.
#
# (AlignakApp) 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 (AlignakApp).  If not, see <http://www.gnu.org/licenses/>.

"""
    App Widget manage creation of a QWidget to make a tempalte for all QWidgets of Alignak-app
"""

import sys

from logging import getLogger
from alignak_app.core.utils import get_image_path, init_config, get_css

try:
    __import__('PyQt5')
    from PyQt5.QtWidgets import QApplication  # pylint: disable=no-name-in-module
    from PyQt5.QtWidgets import QWidget, QStyle, QVBoxLayout  # pylint: disable=no-name-in-module
    from PyQt5.QtWidgets import QLabel, QStyleOption  # pylint: disable=no-name-in-module
    from PyQt5.QtWidgets import QHBoxLayout, QPushButton  # pylint: disable=no-name-in-module
    from PyQt5.Qt import Qt, QIcon, QPixmap, QFrame  # pylint: disable=no-name-in-module
except ImportError:  # pragma: no cover
    from PyQt4.Qt import QApplication  # pylint: disable=import-error
    from PyQt4.Qt import QWidget, QStyle, QVBoxLayout  # pylint: disable=import-error
    from PyQt4.Qt import QLabel, QStyleOption  # pylint: disable=import-error
    from PyQt4.Qt import QHBoxLayout, QPushButton  # pylint: disable=import-error
    from PyQt4.Qt import Qt, QIcon, QPixmap, QFrame  # pylint: disable=import-error

logger = getLogger(__name__)

class AppQWidget(QFrame):
    """
        Class who create a QWidget template.
    """

    def __init__(self, parent=None):
        super(AppQWidget, self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setWindowIcon(QIcon(get_image_path('icon')))
        self.setStyleSheet(get_css())
        self.offset = None

    def initialize(self, title):
        """
        Initialize the QWidget, with its "title"

        :param title: title of the QWidget
        :type title: str
        """

        self.setWindowTitle(title)
        self.setObjectName('app_widget')

        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(main_layout)

        main_layout.addWidget(self.get_logo_widget(title))

        self.setAttribute(Qt.WA_TransparentForMouseEvents)

    def get_logo_widget(self, title):
        """
        Return the logo QWidget

        :return: logo QWidget
        :rtype: QWidget
        """

        logo_widget = QWidget()
        logo_widget.setFixedHeight(45)
        logo_widget.setObjectName('logo')
        logo_layout = QHBoxLayout()
        logo_widget.setLayout(logo_layout)
        logo_widget.setAttribute(Qt.WA_TransparentForMouseEvents)

        logo_label = QLabel()
        logo_label.setPixmap(QPixmap(get_image_path('alignak')))
        logo_label.setFixedSize(121, 35)
        logo_label.setScaledContents(True)

        logo_layout.addWidget(logo_label, 0)

        title_label = QLabel('
%s
' % title)
        title_label.setObjectName('title')

        logo_layout.addWidget(title_label, 1)
        logo_layout.setAlignment(title_label, Qt.AlignHCenter)

        minimize_btn = QPushButton()
        minimize_btn.setIcon(QIcon(get_image_path('minimize')))
        minimize_btn.setFixedSize(22, 22)
        minimize_btn.clicked.connect(self.minimize)
        if 'Notification' in self.windowTitle():
            minimize_btn.setEnabled(False)
        logo_layout.addWidget(minimize_btn, 2)

        maximize_btn = QPushButton()
        maximize_btn.setIcon(QIcon(get_image_path('maximize')))
        maximize_btn.setFixedSize(22, 22)
        maximize_btn.clicked.connect(self.minimize_maximize)
        if 'Notification' in self.windowTitle():
            maximize_btn.setEnabled(False)
        logo_layout.addWidget(maximize_btn, 3)

        close_btn = QPushButton()
        close_btn.setIcon(QIcon(get_image_path('exit')))
        close_btn.setFixedSize(22, 22)
        close_btn.clicked.connect(self.close)
        logo_layout.addWidget(close_btn, 4)

        return logo_widget

    def minimize(self):
        """
        Minimize QWidget

        """

        if self.windowState() == Qt.WindowMinimized:
            self.setWindowState(Qt.WindowNoState)
        else:
            self.setWindowState(Qt.WindowMinimized)

    def minimize_maximize(self):
        """
        Minimize / Maximize QWidget

        """

        if self.windowState() == Qt.WindowMaximized:
            self.setWindowState(Qt.WindowNoState)
        else:
            self.setWindowState(Qt.WindowMaximized)

    def center(self):
        """
        Center QWidget

        """

        screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
        center = QApplication.desktop().screenGeometry(screen).center()
        self.move(center.x() - (self.width() / 2), center.y() - (self.height() / 2))

    def show_widget(self):
        """
        Show and center AppQWidget

        """

        self.center()
        self.show()

    def add_widget(self, widget):
        """
        Add the main QWidget of AppQWidget

        :param widget: QWidget to add
        :type widget: QWidget
        """

        self.setMinimumSize(widget.size())
        self.layout().addWidget(widget, 2)

    def mousePressEvent(self, event):
        """ QWidget.mousePressEvent(QMouseEvent) """

        if 'Notification' not in self.windowTitle():
            self.offset = event.pos()

    def mouseMoveEvent(self, event):
        """ QWidget.mousePressEvent(QMouseEvent) """

        if 'Notification' not in self.windowTitle():
            try:
                x = event.globalX()
                y = event.globalY()
                x_w = self.offset.x()
                y_w = self.offset.y()
                self.move(x - x_w, y - y_w)
            except AttributeError as e:
                logger.warning('Move Event %s: %s', self.objectName(), str(e))

if __name__ == '__main__':
    init_config()

    app = QApplication(sys.argv)

    app_widget = AppQWidget()
    app_widget.initialize('Alignak Status')

    widget_test = QWidget()
    widget_test.setMinimumSize(800, 600)
    layout_test = QVBoxLayout()
    widget_test.setLayout(layout_test)

    label_text = QLabel('This is a text')
    layout_test.addWidget(label_text)

    app_widget.add_widget(widget_test)

    app_widget.show_widget()

    sys.exit(app.exec_())
<commit_msg>Move TransparentEvent to title, add ObjectNames<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2015-2016:
#   Matthieu Estrada, ttamalfor@gmail.com
#
# This file is part of (AlignakApp).
#
# (AlignakApp) 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.
#
# (AlignakApp) 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 (AlignakApp).  If not, see <http://www.gnu.org/licenses/>.

"""
    App Widget manage creation of a QWidget to make a tempalte for all QWidgets of Alignak-app
"""

import sys

from logging import getLogger
from alignak_app.core.utils import get_image_path, init_config, get_css

try:
    __import__('PyQt5')
    from PyQt5.QtWidgets import QApplication  # pylint: disable=no-name-in-module
    from PyQt5.QtWidgets import QWidget, QStyle, QVBoxLayout  # pylint: disable=no-name-in-module
    from PyQt5.QtWidgets import QLabel, QStyleOption  # pylint: disable=no-name-in-module
    from PyQt5.QtWidgets import QHBoxLayout, QPushButton  # pylint: disable=no-name-in-module
    from PyQt5.Qt import Qt, QIcon, QPixmap, QFrame  # pylint: disable=no-name-in-module
except ImportError:  # pragma: no cover
    from PyQt4.Qt import QApplication  # pylint: disable=import-error
    from PyQt4.Qt import QWidget, QStyle, QVBoxLayout  # pylint: disable=import-error
    from PyQt4.Qt import QLabel, QStyleOption  # pylint: disable=import-error
    from PyQt4.Qt import QHBoxLayout, QPushButton  # pylint: disable=import-error
    from PyQt4.Qt import Qt, QIcon, QPixmap, QFrame  # pylint: disable=import-error

logger = getLogger(__name__)

class AppQWidget(QFrame):
    """
        Class who create a QWidget template.
    """

    def __init__(self, parent=None):
        super(AppQWidget, self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.setWindowIcon(QIcon(get_image_path('icon')))
        self.setStyleSheet(get_css())
        self.offset = None

    def initialize(self, title):
        """
        Initialize the QWidget, with its "title"

        :param title: title of the QWidget
        :type title: str
        """

        self.setWindowTitle(title)
        self.setObjectName('app_widget')

        main_layout = QVBoxLayout()
        main_layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(main_layout)

        main_layout.addWidget(self.get_logo_widget(title))

        self.setAttribute(Qt.WA_TransparentForMouseEvents)

    def get_logo_widget(self, title):
        """
        Return the logo QWidget

        :return: logo QWidget
        :rtype: QWidget
        """

        logo_widget = QWidget()
        logo_widget.setFixedHeight(45)
        logo_widget.setObjectName('logo')
        logo_layout = QHBoxLayout()
        logo_widget.setLayout(logo_layout)

        logo_label = QLabel()
        logo_label.setPixmap(QPixmap(get_image_path('alignak')))
        logo_label.setFixedSize(121, 35)
        logo_label.setScaledContents(True)

        logo_layout.addWidget(logo_label, 0)

        title_label = QLabel('
%s
' % title)
        title_label.setObjectName('title')
        title_label.setAttribute(Qt.WA_TransparentForMouseEvents)

        logo_layout.addWidget(title_label, 1)
        logo_layout.setAlignment(title_label, Qt.AlignHCenter)

        minimize_btn = QPushButton()
        minimize_btn.setIcon(QIcon(get_image_path('minimize')))
        minimize_btn.setFixedSize(22, 22)
        minimize_btn.setObjectName('app_widget')
        minimize_btn.clicked.connect(self.minimize)
        if 'Notification' in self.windowTitle():
            minimize_btn.setEnabled(False)
        logo_layout.addWidget(minimize_btn, 2)

        maximize_btn = QPushButton()
        maximize_btn.setIcon(QIcon(get_image_path('maximize')))
        maximize_btn.setFixedSize(22, 22)
        maximize_btn.setObjectName('app_widget')
        maximize_btn.clicked.connect(self.minimize_maximize)
        if 'Notification' in self.windowTitle():
            maximize_btn.setEnabled(False)
        logo_layout.addWidget(maximize_btn, 3)

        close_btn = QPushButton()
        close_btn.setIcon(QIcon(get_image_path('exit')))
        close_btn.setFixedSize(22, 22)
        close_btn.setObjectName('app_widget')
        close_btn.clicked.connect(self.close)
        logo_layout.addWidget(close_btn, 4)

        return logo_widget

    def minimize(self):
        """
        Minimize QWidget

        """

        if self.windowState() == Qt.WindowMinimized:
            self.setWindowState(Qt.WindowNoState)
        else:
            self.setWindowState(Qt.WindowMinimized)

    def minimize_maximize(self):
        """
        Minimize / Maximize QWidget

        """

        if self.windowState() == Qt.WindowMaximized:
            self.setWindowState(Qt.WindowNoState)
        else:
            self.setWindowState(Qt.WindowMaximized)

    def center(self):
        """
        Center QWidget

        """

        screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
        center = QApplication.desktop().screenGeometry(screen).center()
        self.move(center.x() - (self.width() / 2), center.y() - (self.height() / 2))

    def show_widget(self):
        """
        Show and center AppQWidget

        """

        self.center()
        self.show()

    def add_widget(self, widget):
        """
        Add the main QWidget of AppQWidget

        :param widget: QWidget to add
        :type widget: QWidget
        """

        self.setMinimumSize(widget.size())
        self.layout().addWidget(widget, 2)

    def mousePressEvent(self, event):
        """ QWidget.mousePressEvent(QMouseEvent) """

        if 'Notification' not in self.windowTitle():
            self.offset = event.pos()

    def mouseMoveEvent(self, event):
        """ QWidget.mousePressEvent(QMouseEvent) """

        if 'Notification' not in self.windowTitle():
            try:
                x = event.globalX()
                y = event.globalY()
                x_w = self.offset.x()
                y_w = self.offset.y()
                self.move(x - x_w, y - y_w)
            except AttributeError as e:
                logger.warning('Move Event %s: %s', self.objectName(), str(e))

if __name__ == '__main__':
    init_config()

    app = QApplication(sys.argv)

    app_widget = AppQWidget()
    app_widget.initialize('Alignak Status')

    widget_test = QWidget()
    widget_test.setMinimumSize(800, 600)
    layout_test = QVBoxLayout()
    widget_test.setLayout(layout_test)

    label_text = QLabel('This is a text')
    layout_test.addWidget(label_text)

    app_widget.add_widget(widget_test)

    app_widget.show_widget()

    sys.exit(app.exec_())
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Resource information of command
"""

def get_name():
    """
    Get name of this resource

    :return: name of this resource
    :rtype: str
    """
    return 'command'

def get_schema():
    """
    Schema structure of this resource

    :return: schema dictionary
    :rtype: dict
    """
    return {
        'schema': {
            'name': {
                'type': 'string',
                'ui': {
                    'title': 'Name',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'required': True,
                'unique': True,
            },
            'definition_order': {
                'type': 'integer',
                'ui': {
                    'title': 'Definition order',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 100
            },
            'command_line': {
                'type': 'string',
                'ui': {
                    'title': 'Command line',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
            },
            'poller_tag': {
                'type': 'string',
                'ui': {
                    'title': 'Poller tag',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 'None'
            },
            'reactionner_tag': {
                'type': 'string',
                'ui': {
                    'title': 'Reactionner tag',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 'None'
            },
            'module_type': {
                'type': 'string',
                'ui': {
                    'title': 'Module type',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 'fork'
            },
            'timeout': {
                'type': 'integer',
                'ui': {
                    'title': 'Timeout',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': -1
            },
            'enable_environment_macros': {
                'type': 'boolean',
                'default': False
            },
            '_realm': {
                'type': 'objectid',
                'data_relation': {
                    'resource': 'realm',
                    'embeddable': True
                },
                'required': True,
            },
            '_sub_realm': {
                'type': 'boolean',
                'default': False
            },
            '_users_read': {
                'type': 'list',
                'schema': {
                    'type': 'objectid',
                    'data_relation': {
                        'resource': 'contact',
                        'embeddable': True,
                    }
                },
                'default': [],
            },
            '_users_update': {
                'type': 'list',
                'schema': {
                    'type': 'objectid',
                    'data_relation': {
                        'resource': 'contact',
                        'embeddable': True,
                    }
                },
                'default': [],
            },
            '_users_delete': {
                'type': 'list',
                'schema': {
                    'type': 'objectid',
                    'data_relation': {
                        'resource': 'contact',
                        'embeddable': True,
                    }
                },
                'default': [],
            },
            # This to define if the object in this model are to be used in the UI
            'ui': {
                'type': 'boolean',
                'default': True,
                'required': False,

                # UI parameters for the objects
                'ui': {
                    'list_title': 'Commands list (%d items)',
                    'page_title': 'Command: %s',
                    'uid': 'command_name',
                    'visible': True,
                    'orderable': True,
                    'searchable': True
                }
            }
        }
    }
<commit_msg>Update ui information on command model<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Resource information of command
"""

def get_name():
    """
    Get name of this resource

    :return: name of this resource
    :rtype: str
    """
    return 'command'

def get_schema():
    """
    Schema structure of this resource

    :return: schema dictionary
    :rtype: dict
    """
    return {
        'schema': {
            'name': {
                'type': 'string',
                'ui': {
                    'title': 'Name',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'required': True,
                'unique': True,
            },
            'definition_order': {
                'type': 'integer',
                'ui': {
                    'title': 'Definition order',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 100
            },
            'command_line': {
                'type': 'string',
                'ui': {
                    'title': 'Command line',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
            },
            'poller_tag': {
                'type': 'string',
                'ui': {
                    'title': 'Poller tag',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 'None'
            },
            'reactionner_tag': {
                'type': 'string',
                'ui': {
                    'title': 'Reactionner tag',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 'None'
            },
            'module_type': {
                'type': 'string',
                'ui': {
                    'title': 'Module type',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': 'fork'
            },
            'timeout': {
                'type': 'integer',
                'ui': {
                    'title': 'Timeout',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': -1
            },
            'enable_environment_macros': {
                'type': 'boolean',
                'ui': {
                    'title': 'Environment macros',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': False
            },
            '_realm': {
                'type': 'objectid',
                'ui': {
                    'title': 'Realm',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'data_relation': {
                    'resource': 'realm',
                    'embeddable': True
                },
                'required': True,
            },
            '_sub_realm': {
                'type': 'boolean',
                'ui': {
                    'title': 'Readable on sub realms',
                    'visible': True,
                    'orderable': True,
                    'searchable': True,
                    "format": None
                },
                'default': False
            },
            '_users_read': {
                'type': 'list',
                'schema': {
                    'type': 'objectid',
                    'data_relation': {
                        'resource': 'contact',
                        'embeddable': True,
                    }
                },
                'default': [],
            },
            '_users_update': {
                'type': 'list',
                'schema': {
                    'type': 'objectid',
                    'data_relation': {
                        'resource': 'contact',
                        'embeddable': True,
                    }
                },
                'default': [],
            },
            '_users_delete': {
                'type': 'list',
                'schema': {
                    'type': 'objectid',
                    'data_relation': {
                        'resource': 'contact',
                        'embeddable': True,
                    }
                },
                'default': [],
            },
            # This to define if the object in this model are to be used in the UI
            'ui': {
                'type': 'boolean',
                'default': True,
                'required': False,

                # UI parameters for the objects
                'ui': {
                    'list_title': 'Commands list (%d items)',
                    'page_title': 'Command: %s',
                    'uid': 'command_name',
                    'visible': True,
                    'orderable': True,
                    'searchable': True
                }
            }
        }
    }
<|endoftext|>


<commit_before># Copyright 2008 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.

"""Release tag string for display in templates (and possibly other uses).

Steps (currently done by hand, but too be scripted in the future) to make
a release:

1) set RELEASE_TAG in this file to a "release candidate" release string that
   ends in "rc"

2) commit this file *by itself* in its own commit

3) use 'svn cp' to create a release branch in /branches/ with exactly the
   same name as the contents of the RELEASE_TAG string

4) set RELEASE_TAG back to None in /trunk/

To finalize a release candidate in a release branch for a push to the live
web site:

1) in the release branch, change RELEASE_TAG to remove the trailing "rc"

2) commit this file in the release branch *by itself* in its own commit

3) use 'svn cp' to create a tag in /tags/ with exactly the same name as the
   contents of the RELEASE_TAG string

4) put the release branch in a state where it is ready for additional patches
   after the tag by setting the end of the RELEASE_TAG string to "p0"

To re-release a previously-tagged release branch after a patch for a push to
the live web site:

1) increment the "patch suffix" of the RELEASE_TAG string to the next integer
   (for example, "p0" becomes "p1", so the first tagged patch release will
   always be "p1", not "p0", which is just a placeholder)

2) (same as #2 for a release candidate)

3) (same as #3 for a release candidate)

4) (there is no step 4)
"""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  ]

RELEASE_TAG = None

<commit_msg>Set RELEASE_TAG to 0.2-20090209rc for release candidate.<commit_after># Copyright 2008 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.

"""Release tag string for display in templates (and possibly other uses).

Steps (currently done by hand, but too be scripted in the future) to make
a release:

1) set RELEASE_TAG in this file to a "release candidate" release string that
   ends in "rc"

2) commit this file *by itself* in its own commit

3) use 'svn cp' to create a release branch in /branches/ with exactly the
   same name as the contents of the RELEASE_TAG string

4) set RELEASE_TAG back to None in /trunk/

To finalize a release candidate in a release branch for a push to the live
web site:

1) in the release branch, change RELEASE_TAG to remove the trailing "rc"

2) commit this file in the release branch *by itself* in its own commit

3) use 'svn cp' to create a tag in /tags/ with exactly the same name as the
   contents of the RELEASE_TAG string

4) put the release branch in a state where it is ready for additional patches
   after the tag by setting the end of the RELEASE_TAG string to "p0"

To re-release a previously-tagged release branch after a patch for a push to
the live web site:

1) increment the "patch suffix" of the RELEASE_TAG string to the next integer
   (for example, "p0" becomes "p1", so the first tagged patch release will
   always be "p1", not "p0", which is just a placeholder)

2) (same as #2 for a release candidate)

3) (same as #3 for a release candidate)

4) (there is no step 4)
"""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  ]

RELEASE_TAG = '0.2-20090209rc'

<|endoftext|>


<commit_before>import warnings

__all__ = ["deprecated", ]

class deprecated(object):
    """Decorator to mark a function or class as deprecated.

    Issue a warning when the function is called/the class is instantiated and
    adds a warning to the docstring.

    The optional extra argument will be appended to the deprecation message
    and the docstring. Note: to use this with the default value for extra, put
    in an empty of parentheses:

    >>> from sklearn.utils import deprecated
    >>> deprecated() # doctest: +ELLIPSIS
    <sklearn.utils.deprecation.deprecated object at ...>

    >>> @deprecated()
    ... def some_function(): pass
    """

    # Adapted from http://wiki.python.org/moin/PythonDecoratorLibrary,
    # but with many changes.

    def __init__(self, extra=''):
        """
        Parameters
        ----------
        extra: string
          to be added to the deprecation messages

        """
        self.extra = extra

    def __call__(self, obj):
        if isinstance(obj, type):
            return self._decorate_class(obj)
        else:
            return self._decorate_fun(obj)

    def _decorate_class(self, cls):
        msg = "Class %s is deprecated" % cls.__name__
        if self.extra:
            msg += "; %s" % self.extra

        # FIXME: we should probably reset __new__ for full generality
        init = cls.__init__

        def wrapped(*args, **kwargs):
            warnings.warn(msg, category=DeprecationWarning)
            return init(*args, **kwargs)
        cls.__init__ = wrapped

        wrapped.__name__ = '__init__'
        wrapped.__doc__ = self._update_doc(init.__doc__)
        wrapped.deprecated_original = init

        return cls

    def _decorate_fun(self, fun):
        """Decorate function fun"""

        msg = "Function %s is deprecated" % fun.__name__
        if self.extra:
            msg += "; %s" % self.extra

        def wrapped(*args, **kwargs):
            warnings.warn(msg, category=DeprecationWarning)
            return fun(*args, **kwargs)

        wrapped.__name__ = fun.__name__
        wrapped.__dict__ = fun.__dict__
        wrapped.__doc__ = self._update_doc(fun.__doc__)

        return wrapped

    def _update_doc(self, olddoc):
        newdoc = "DEPRECATED"
        if self.extra:
            newdoc = "%s: %s" % (newdoc, self.extra)
        if olddoc:
            newdoc = "%s\n\n%s" % (newdoc, olddoc)
        return newdoc
<commit_msg>Distinguish instances from functions in deprecated<commit_after>from inspect import isfunction
import warnings

__all__ = ["deprecated", ]

class deprecated(object):
    """Decorator to mark a function or class as deprecated.

    Issue a warning when the function is called/the class is instantiated and
    adds a warning to the docstring.

    The optional extra argument will be appended to the deprecation message
    and the docstring. Note: to use this with the default value for extra, put
    in an empty of parentheses:

    >>> from sklearn.utils import deprecated
    >>> deprecated() # doctest: +ELLIPSIS
    <sklearn.utils.deprecation.deprecated object at ...>

    >>> @deprecated()
    ... def some_function(): pass
    """

    # Adapted from http://wiki.python.org/moin/PythonDecoratorLibrary,
    # but with many changes.

    def __init__(self, extra=''):
        """
        Parameters
        ----------
        extra: string
          to be added to the deprecation messages

        """
        self.extra = extra

    def __call__(self, obj):
        if isinstance(obj, type):
            return self._decorate_class(obj)
        elif isfunction(obj):
            return self._decorate_fun(obj)
        else: # it is an instance that is callable
            return self._decorate_instance(obj)

    def _decorate_class(self, cls):
        msg = "Class %s is deprecated" % cls.__name__
        if self.extra:
            msg += "; %s" % self.extra

        # FIXME: we should probably reset __new__ for full generality
        init = cls.__init__

        def wrapped(*args, **kwargs):
            warnings.warn(msg, category=DeprecationWarning)
            return init(*args, **kwargs)
        cls.__init__ = wrapped

        wrapped.__name__ = '__init__'
        wrapped.__doc__ = self._update_doc(init.__doc__)
        wrapped.deprecated_original = init

        return cls

    def _decorate_fun(self, fun):
        """Decorate function fun"""

        msg = "Function %s is deprecated" % fun.__name__
        if self.extra:
            msg += "; %s" % self.extra

        def wrapped(*args, **kwargs):
            warnings.warn(msg, category=DeprecationWarning)
            return fun(*args, **kwargs)

        wrapped.__name__ = fun.__name__
        wrapped.__dict__ = fun.__dict__
        wrapped.__doc__ = self._update_doc(fun.__doc__)

        return wrapped

    def _decorate_instance(self, instance):
        cls = instance.__class__
        msg = "Thing %s is deprecated" % cls.__name__
        if self.extra:
            msg += "; %s" % self.extra

        def wrapped(*args, **kwargs):
            warnings.warn(msg, category=DeprecationWarning)
            return instance(*args, **kwargs)

        wrapped.__name__ = cls.__name__
        wrapped.__dict__ = instance.__dict__
        wrapped.__doc__ = self._update_doc(instance.__doc__)

        return wrapped

    def _update_doc(self, olddoc):
        newdoc = "DEPRECATED"
        if self.extra:
            newdoc = "%s: %s" % (newdoc, self.extra)
        if olddoc:
            newdoc = "%s\n\n%s" % (newdoc, olddoc)
        return newdoc
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
======================================================================
Core data structures for math (:mod:`sknano.core.math`)
======================================================================

.. currentmodule:: sknano.core.math

Contents
========

Abstract object representations for points and vectors
-------------------------------------------------------
.. autosummary::
   :toctree: generated/

   Point
   Vector

Linear algebra transforms
----------------------------
.. autosummary::
   :toctree: generated/

   rotation_matrix
   transformation_matrix
   rotation_transform

Number theory
---------------
.. autosummary::
   :toctree: generated/

   totient_func

"""
from __future__ import absolute_import, division, print_function
__docformat__ = 'restructuredtext en'

from ._funcs import *
from ._transforms import *

from ._point import *
from ._vector import *

__all__ = [s for s in dir() if not s.startswith('_')]

from . import _point as point
from . import _vector as vector

__all__ += ['point', 'vector']
<commit_msg>updating docstring<commit_after># -*- coding: utf-8 -*-
"""
======================================================================
Core data structures for math (:mod:`sknano.core.math`)
======================================================================

.. currentmodule:: sknano.core.math

Contents
========

Abstract object representations for points and vectors
-------------------------------------------------------
.. autosummary::
   :toctree: generated/

   Point
   Vector

Linear algebra transforms
----------------------------
.. autosummary::
   :toctree: generated/

   rotation_matrix
   transformation_matrix
   rotate_point

Number theory
---------------
.. autosummary::
   :toctree: generated/

   totient_func

"""
from __future__ import absolute_import, division, print_function
__docformat__ = 'restructuredtext en'

from ._funcs import *
from ._transforms import *

from ._point import *
from ._vector import *

__all__ = [s for s in dir() if not s.startswith('_')]

from . import _point as point
from . import _vector as vector

__all__ += ['point', 'vector']
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding field 'StateLog.description'
        db.add_column(u'django_fsm_log_statelog', 'description',
                      self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True),
                      keep_default=False)

    def backwards(self, orm):
        # Deleting field 'StateLog.description'
        db.delete_column(u'django_fsm_log_statelog', 'description')

    models = {
        u'contenttypes.contenttype': {
            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
        },
        u'django_fsm_log.statelog': {
            'Meta': {'object_name': 'StateLog'},
            'by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.Usuario']", 'null': 'True', 'blank': 'True'}),
            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
            'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
            'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
            'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
            'transition': ('django.db.models.fields.CharField', [], {'max_length': '255'})
        }
    }

    complete_apps = ['django_fsm_log']
<commit_msg>Added a description field<commit_after># -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

class Migration(SchemaMigration):

    def forwards(self, orm):
        # Adding field 'StateLog.description'
        db.add_column(u'django_fsm_log_statelog', 'description',
                      self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True),
                      keep_default=False)

    def backwards(self, orm):
        # Deleting field 'StateLog.description'
        db.delete_column(u'django_fsm_log_statelog', 'description')

    models = {
        u'contenttypes.contenttype': {
            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
        },
        u'django_fsm_log.statelog': {
            'Meta': {'object_name': 'StateLog'},
            'by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s.%s']" % (User._meta.app_label, User._meta.object_name), 'null': 'True', 'blank': 'True'}),
            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
            'description': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {'db_index': 'True'}),
            'state': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
            'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
            'transition': ('django.db.models.fields.CharField', [], {'max_length': '255'})
        }
    }

    complete_apps = ['django_fsm_log']
<|endoftext|>


<commit_before>#########
# Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
#
# 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.

__author__ = 'elip'

import time
import os
import jinja2

from cloudify.decorators import operation
from cloudify.exceptions import NonRecoverableError
from cloudify.celery import celery as celery_client
from cloudify import manager
from cloudify import utils

from worker_installer import init_worker_installer
from worker_installer.utils import is_on_management_worker

PLUGIN_INSTALLER_PLUGIN_PATH = 'plugin_installer.tasks'
AGENT_INSTALLER_PLUGIN_PATH = 'worker_installer.tasks'
WINDOWS_AGENT_INSTALLER_PLUGIN_PATH = 'windows_agent_installer.tasks'
WINDOWS_PLUGIN_INSTALLER_PLUGIN_PATH = 'windows_plugin_installer.tasks'
DEFAULT_WORKFLOWS_PLUGIN_PATH = 'cloudify.plugins.workflows'
CELERY_INCLUDES_LIST = [
    AGENT_INSTALLER_PLUGIN_PATH, PLUGIN_INSTALLER_PLUGIN_PATH,
    WINDOWS_AGENT_INSTALLER_PLUGIN_PATH, WINDOWS_PLUGIN_INSTALLER_PLUGIN_PATH,
    DEFAULT_WORKFLOWS_PLUGIN_PATH
]

CELERY_CONFIG_PATH = '/packages/templates/{0}-celeryd-cloudify.conf.template'
CELERY_INIT_PATH = '/packages/templates/{0}-celeryd-cloudify.init.template'
AGENT_PACKAGE_PATH = '/packages/agents/{0}-agent.tar.gz'
DISABLE_REQUIRETTY_SCRIPT_PATH = \
    '/packages/scripts/{0}-agent-disable-requiretty.sh'

def get_agent_resource_url(ctx, agent_config, resource):
    """returns an agent's resource url
    """
    if agent_config.get(resource):
        return '{0}/{1}/{2}'.format(
            utils.get_manager_file_server_blueprints_root_url(),
            ctx.blueprint.id, agent_config[resource])
    else:
        resource_path = locals()[resource.upper()]
        return '{0}/{1}'.format(
            utils.get_manager_file_server_url(),
            resource_path.format(agent_config['distro']))

def get_celery_includes_list():
    return CELERY_INCLUDES_LIST

def download_resource_on_host(logger, runner, url, destination_path):
    """downloads a resource from the fileserver on the agent's host
    """
    logger.debug('attempting to download {0} to {1}'.format(
        url, destination_path))
    logger.debug('checking if wget exists on the host machine')
    r = runner.run('which wget')
    if r.succeeded:
        logger.debug('wget-ing {0} to {1}'.format(url, destination_path))
        return runner.run('wget -T 30 {0} -O {1}'.format(
            url, destination_path))
    logger.debug('checking if curl exists on the host machine')
    r = runner.run('which curl')
    if r.succeeded:
        logger.debug('curl-ing {0} to {1}'.format(url, destination_path))
        return runner.run('curl {0} -O {1}'.format(
            url, destination_path))
    logger.warn('could not download resource')
    return r.succeeded

@operation
@init_worker_installer
def install(ctx, runner, agent_config, **kwargs):
    try:
        agent_package_url = get_agent_resource_url(
            ctx, agent_config, 'agent_package_path')
    except:
        raise NonRecoverableError('failed to retrieve agent package url')

    ctx.logger.debug("Pinging agent installer target")
    runner.ping()

    ctx.logger.info(
        "installing celery worker {0}".format(agent_config['name']))
    if worker_exists(runner, agent_config):
        ctx.logger.info("Worker for deployment {0} is already installed. "
                        "nothing to do.".format(ctx.deployment_id))
        return

    ctx.logger.info(
        'Installing celery worker [cloudify_agent={0}]'.format(agent_config))
    runner.run('mkdir -p {0}'.format(agent_config['base_dir']))

    ctx.logger.debug(
        'Downloading agent package from: {0}'.format(agent_package_url))
    r = download_resource_on_host(
        ctx.logger, runner, agent_package_url, '{0}/{1}'.format(
            agent_config['base_dir'], 'agent.tar.gz'))
    if not r:
        raise NonRecoverableError('failed to download agent package')

    ctx.logger.debug('extracting agent package on host')
    runner.run(
        'tar xzvf {0}/agent.tar.gz --strip=2 -C {2}'.format(
            agent_config['base_dir'], agent_config['base_dir']))

    ctx.logger.debug('configuring virtualenv')
    for link in ['archives', 'bin', 'include', 'lib']:
        link_path = '{0}/env/local/{1}'.format(agent_config['base_dir'], link)
        try:
            runner.run('unlink {0}'.format(link_path))
            runner.run('ln -s {0}/env/{1} {2}'.format(
                agent_config['base_dir'], link, link_path))
        except Exception as e:
            ctx.logger.warn('Error processing link: {0} [error={1}] - '
                            'ignoring..'.format(link_path, str(e)))

    create_celery_configuration(
        ctx, runner, agent_config, manager.get_resource)

    runner.run('sudo chmod +x {0}'.format(agent_config['init_file']))

    # This is for fixing virtualenv included in package paths
    runner.run("sed -i '1 s|.*/bin/python.*$|#!{0}/env/bin/python|g' "
               "{0}/env/bin/*".format(agent_config['base_dir']))

    # Remove downloaded agent package
    runner.run('rm {0}/agent.tar.gz'.format(agent_config['base_dir']))

    # Disable requiretty
    if agent_config['disable_requiretty']:
        try:
            disable_requiretty_script_url = get_agent_resource_url(
                ctx, agent_config, 'disable_requiretty_script')
        except:
            raise NonRecoverableError(
                'failed to retrieve disable-requiretty script url')
        ctx.logger.debug("Removing requiretty in sudoers file")
        disable_requiretty_script = '{0}/disable-requiretty.sh'.format(
            agent_config['base_dir'])

        r = download_resource_on_host(
            ctx.logger, runner, disable_requiretty_script_url,
            disable_requiretty_script)
        if not r:
            raise NonRecoverableError(
                'failed to download disable-requiretty script')

        runner.run('chmod +x {0}'.format(disable_requiretty_script))

        runner.run('sudo {0}'.format(disable_requiretty_script))

@operation
@init_worker_installer
def uninstall(ctx, runner, agent_config, **kwargs):

    ctx.logger.info(
        'Uninstalling celery worker [cloudify_agent={0}]'.format(agent_config))

    files_to_delete = [
        agent_config['init_file'], agent_config['config_file']
    ]
    folders_to_delete = [agent_config['base_dir']]
    delete_files_if_exist(ctx, agent_config, runner, files_to_delete)
    delete_folders_if_exist(ctx, agent_config, runner, folders_to_delete)

def delete_files_if_exist(ctx, agent_config, runner, files):
    missing_files = []
    for file_to_delete in files:
        if runner.exists(file_to_delete):
            runner.run("sudo rm {0}".format(file_to_delete))
        else:
            missing_files.append(file_to_delete)
    if missing_files:
        ctx.logger.debug(
            "Could not find files {0} while trying to uninstall worker {1}"
            .format(missing_files, agent_config['name']))

def delete_folders_if_exist(ctx, agent_config, runner, folders):
    missing_folders = []
    for folder_to_delete in folders:
        if runner.exists(folder_to_delete):
            runner.run('sudo rm -rf {0}'.format(folder_to_delete))
        else:
            missing_folders.append(folder_to_delete)
    if missing_folders:
        ctx.logger.debug(
            'Could not find folders {0} while trying to uninstall worker {1}'
            .format(missing_folders, agent_config['name']))

@operation
@init_worker_installer
def stop(ctx, runner, agent_config, **kwargs):

    ctx.logger.info("stopping celery worker {0}".format(agent_config['name']))

    if runner.exists(agent_config['init_file']):
        runner.run(
            "sudo service celeryd-{0} stop".format(agent_config["name"]))
    else:
        ctx.logger.debug(
            "Could not find any workers with name {0}. nothing to do."
            .format(agent_config["name"]))

@operation
@init_worker_installer
def start(ctx, runner, agent_config, **kwargs):

    ctx.logger.info("starting celery worker {0}".format(agent_config['name']))

    runner.run("sudo service celeryd-{0} start".format(agent_config["name"]))

    _wait_for_started(runner, agent_config)

@operation
@init_worker_installer
def restart(ctx, runner, agent_config, **kwargs):

    ctx.logger.info(
        "restarting celery worker {0}".format(agent_config['name']))

    restart_celery_worker(runner, agent_config)

def get_agent_ip(ctx, agent_config):
    if is_on_management_worker(ctx):
        return utils.get_manager_ip()
    return agent_config['host']

def create_celery_configuration(ctx, runner, agent_config, resource_loader):
    create_celery_includes_file(ctx, runner, agent_config)
    loader = jinja2.FunctionLoader(resource_loader)
    env = jinja2.Environment(loader=loader)
    config_template = env.get_template(CELERY_CONFIG_PATH.format(
        agent_config['distro']))
    config_template_values = {
        'includes_file_path': agent_config['includes_file'],
        'celery_base_dir': agent_config['celery_base_dir'],
        'worker_modifier': agent_config['name'],
        'management_ip': utils.get_manager_ip(),
        'broker_ip': '127.0.0.1' if is_on_management_worker(ctx)
        else utils.get_manager_ip(),
        'agent_ip': get_agent_ip(ctx, agent_config),
        'celery_user': agent_config['user'],
        'celery_group': agent_config['user'],
        'worker_autoscale': '{0},{1}'.format(agent_config['max_workers'],
                                             agent_config['min_workers'])
    }

    ctx.logger.debug(
        'Populating celery config jinja2 template with the following '
        'values: {0}'.format(config_template_values))

    config = config_template.render(config_template_values)
    init_template = env.get_template(CELERY_INIT_PATH.format(
        agent_config['distro']))
    init_template_values = {
        'celery_base_dir': agent_config['celery_base_dir'],
        'worker_modifier': agent_config['name']
    }

    ctx.logger.debug(
        'Populating celery init.d jinja2 template with the following '
        'values: {0}'.format(init_template_values))

    init = init_template.render(init_template_values)

    ctx.logger.debug(
        'Creating celery config and init files [cloudify_agent={0}]'.format(
            agent_config))

    # runner.put(agent_config['config_file'], config, use_sudo=True)
    # runner.put(agent_config['init_file'], init, use_sudo=True)
    celery_config_url = get_agent_resource_url(
        ctx, agent_config, 'celery_config_path')
    celery_init_url = get_agent_resource_url(
        ctx, agent_config, 'celery_init_path')

    r = download_resource_on_host(
        ctx.logger, runner, celery_config_url, config)
    if not r:
        raise NonRecoverableError('failed to download celery config file')
    r = download_resource_on_host(ctx.logger, runner, celery_init_url, init)
    if not r:
        raise NonRecoverableError('failed to download celery init file')

def create_celery_includes_file(ctx, runner, agent_config):
    # build initial includes
    includes_list = get_celery_includes_list()

    runner.put(agent_config['includes_file'],
               'INCLUDES={0}\n'.format(','.join(includes_list)))

    ctx.logger.debug('Created celery includes file [file=%s, content=%s]',
                     agent_config['includes_file'],
                     includes_list)

def worker_exists(runner, agent_config):
    return runner.exists(agent_config['base_dir'])

def restart_celery_worker(runner, agent_config):
    runner.run("sudo service celeryd-{0} restart".format(
        agent_config['name']))
    _wait_for_started(runner, agent_config)

def _verify_no_celery_error(runner, agent_config):
    celery_error_out = os.path.join(
        agent_config['base_dir'], 'work/celery_error.out')

    # this means the celery worker had an uncaught
    #  exception and it wrote its content
    # to the file above because of our custom exception handler (see celery.py)
    if runner.exists(celery_error_out):
        output = runner.get(celery_error_out)
        runner.run('rm {0}'.format(celery_error_out))
        raise NonRecoverableError(
            'Celery worker failed to start:\n{0}'.format(output))

def _wait_for_started(runner, agent_config):
    _verify_no_celery_error(runner, agent_config)
    worker_name = 'celery.{}'.format(agent_config['name'])
    inspect = celery_client.control.inspect(destination=[worker_name])
    wait_started_timeout = agent_config['wait_started_timeout']
    timeout = time.time() + wait_started_timeout
    interval = agent_config['wait_started_interval']
    while time.time() < timeout:
        stats = (inspect.stats() or {}).get(worker_name)
        if stats:
            return
        time.sleep(interval)
    _verify_no_celery_error(runner, agent_config)
    raise NonRecoverableError('Failed starting agent. waited for {} seconds.'
                              .format(wait_started_timeout))
<commit_msg>now printing exception when retrieving agent url<commit_after>#########
# Copyright (c) 2013 GigaSpaces Technologies Ltd. All rights reserved
#
# 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.

__author__ = 'elip'

import time
import os
import jinja2

from cloudify.decorators import operation
from cloudify.exceptions import NonRecoverableError
from cloudify.celery import celery as celery_client
from cloudify import manager
from cloudify import utils

from worker_installer import init_worker_installer
from worker_installer.utils import is_on_management_worker

PLUGIN_INSTALLER_PLUGIN_PATH = 'plugin_installer.tasks'
AGENT_INSTALLER_PLUGIN_PATH = 'worker_installer.tasks'
WINDOWS_AGENT_INSTALLER_PLUGIN_PATH = 'windows_agent_installer.tasks'
WINDOWS_PLUGIN_INSTALLER_PLUGIN_PATH = 'windows_plugin_installer.tasks'
DEFAULT_WORKFLOWS_PLUGIN_PATH = 'cloudify.plugins.workflows'
CELERY_INCLUDES_LIST = [
    AGENT_INSTALLER_PLUGIN_PATH, PLUGIN_INSTALLER_PLUGIN_PATH,
    WINDOWS_AGENT_INSTALLER_PLUGIN_PATH, WINDOWS_PLUGIN_INSTALLER_PLUGIN_PATH,
    DEFAULT_WORKFLOWS_PLUGIN_PATH
]

CELERY_CONFIG_PATH = '/packages/templates/{0}-celeryd-cloudify.conf.template'
CELERY_INIT_PATH = '/packages/templates/{0}-celeryd-cloudify.init.template'
AGENT_PACKAGE_PATH = '/packages/agents/{0}-agent.tar.gz'
DISABLE_REQUIRETTY_SCRIPT_PATH = \
    '/packages/scripts/{0}-agent-disable-requiretty.sh'

def get_agent_resource_url(ctx, agent_config, resource):
    """returns an agent's resource url
    """
    if agent_config.get(resource):
        return '{0}/{1}/{2}'.format(
            utils.get_manager_file_server_blueprints_root_url(),
            ctx.blueprint.id, agent_config[resource])
    else:
        resource_path = locals()[resource.upper()]
        return '{0}/{1}'.format(
            utils.get_manager_file_server_url(),
            resource_path.format(agent_config['distro']))

def get_celery_includes_list():
    return CELERY_INCLUDES_LIST

def download_resource_on_host(logger, runner, url, destination_path):
    """downloads a resource from the fileserver on the agent's host
    """
    logger.debug('attempting to download {0} to {1}'.format(
        url, destination_path))
    logger.debug('checking if wget exists on the host machine')
    r = runner.run('which wget')
    if r.succeeded:
        logger.debug('wget-ing {0} to {1}'.format(url, destination_path))
        return runner.run('wget -T 30 {0} -O {1}'.format(
            url, destination_path))
    logger.debug('checking if curl exists on the host machine')
    r = runner.run('which curl')
    if r.succeeded:
        logger.debug('curl-ing {0} to {1}'.format(url, destination_path))
        return runner.run('curl {0} -O {1}'.format(
            url, destination_path))
    logger.warn('could not download resource')
    return r.succeeded

@operation
@init_worker_installer
def install(ctx, runner, agent_config, **kwargs):
    try:
        agent_package_url = get_agent_resource_url(
            ctx, agent_config, 'agent_package_path')
    except Exception as ex:
        raise NonRecoverableError(
            'failed to retrieve agent package url ({0})'.format(ex))

    ctx.logger.debug("Pinging agent installer target")
    runner.ping()

    ctx.logger.info(
        "installing celery worker {0}".format(agent_config['name']))
    if worker_exists(runner, agent_config):
        ctx.logger.info("Worker for deployment {0} is already installed. "
                        "nothing to do.".format(ctx.deployment_id))
        return

    ctx.logger.info(
        'Installing celery worker [cloudify_agent={0}]'.format(agent_config))
    runner.run('mkdir -p {0}'.format(agent_config['base_dir']))

    ctx.logger.debug(
        'Downloading agent package from: {0}'.format(agent_package_url))
    r = download_resource_on_host(
        ctx.logger, runner, agent_package_url, '{0}/{1}'.format(
            agent_config['base_dir'], 'agent.tar.gz'))
    if not r:
        raise NonRecoverableError('failed to download agent package')

    ctx.logger.debug('extracting agent package on host')
    runner.run(
        'tar xzvf {0}/agent.tar.gz --strip=2 -C {2}'.format(
            agent_config['base_dir'], agent_config['base_dir']))

    ctx.logger.debug('configuring virtualenv')
    for link in ['archives', 'bin', 'include', 'lib']:
        link_path = '{0}/env/local/{1}'.format(agent_config['base_dir'], link)
        try:
            runner.run('unlink {0}'.format(link_path))
            runner.run('ln -s {0}/env/{1} {2}'.format(
                agent_config['base_dir'], link, link_path))
        except Exception as e:
            ctx.logger.warn('Error processing link: {0} [error={1}] - '
                            'ignoring..'.format(link_path, str(e)))

    create_celery_configuration(
        ctx, runner, agent_config, manager.get_resource)

    runner.run('sudo chmod +x {0}'.format(agent_config['init_file']))

    # This is for fixing virtualenv included in package paths
    runner.run("sed -i '1 s|.*/bin/python.*$|#!{0}/env/bin/python|g' "
               "{0}/env/bin/*".format(agent_config['base_dir']))

    # Remove downloaded agent package
    runner.run('rm {0}/agent.tar.gz'.format(agent_config['base_dir']))

    # Disable requiretty
    if agent_config['disable_requiretty']:
        try:
            disable_requiretty_script_url = get_agent_resource_url(
                ctx, agent_config, 'disable_requiretty_script')
        except:
            raise NonRecoverableError(
                'failed to retrieve disable-requiretty script url')
        ctx.logger.debug("Removing requiretty in sudoers file")
        disable_requiretty_script = '{0}/disable-requiretty.sh'.format(
            agent_config['base_dir'])

        r = download_resource_on_host(
            ctx.logger, runner, disable_requiretty_script_url,
            disable_requiretty_script)
        if not r:
            raise NonRecoverableError(
                'failed to download disable-requiretty script')

        runner.run('chmod +x {0}'.format(disable_requiretty_script))

        runner.run('sudo {0}'.format(disable_requiretty_script))

@operation
@init_worker_installer
def uninstall(ctx, runner, agent_config, **kwargs):

    ctx.logger.info(
        'Uninstalling celery worker [cloudify_agent={0}]'.format(agent_config))

    files_to_delete = [
        agent_config['init_file'], agent_config['config_file']
    ]
    folders_to_delete = [agent_config['base_dir']]
    delete_files_if_exist(ctx, agent_config, runner, files_to_delete)
    delete_folders_if_exist(ctx, agent_config, runner, folders_to_delete)

def delete_files_if_exist(ctx, agent_config, runner, files):
    missing_files = []
    for file_to_delete in files:
        if runner.exists(file_to_delete):
            runner.run("sudo rm {0}".format(file_to_delete))
        else:
            missing_files.append(file_to_delete)
    if missing_files:
        ctx.logger.debug(
            "Could not find files {0} while trying to uninstall worker {1}"
            .format(missing_files, agent_config['name']))

def delete_folders_if_exist(ctx, agent_config, runner, folders):
    missing_folders = []
    for folder_to_delete in folders:
        if runner.exists(folder_to_delete):
            runner.run('sudo rm -rf {0}'.format(folder_to_delete))
        else:
            missing_folders.append(folder_to_delete)
    if missing_folders:
        ctx.logger.debug(
            'Could not find folders {0} while trying to uninstall worker {1}'
            .format(missing_folders, agent_config['name']))

@operation
@init_worker_installer
def stop(ctx, runner, agent_config, **kwargs):

    ctx.logger.info("stopping celery worker {0}".format(agent_config['name']))

    if runner.exists(agent_config['init_file']):
        runner.run(
            "sudo service celeryd-{0} stop".format(agent_config["name"]))
    else:
        ctx.logger.debug(
            "Could not find any workers with name {0}. nothing to do."
            .format(agent_config["name"]))

@operation
@init_worker_installer
def start(ctx, runner, agent_config, **kwargs):

    ctx.logger.info("starting celery worker {0}".format(agent_config['name']))

    runner.run("sudo service celeryd-{0} start".format(agent_config["name"]))

    _wait_for_started(runner, agent_config)

@operation
@init_worker_installer
def restart(ctx, runner, agent_config, **kwargs):

    ctx.logger.info(
        "restarting celery worker {0}".format(agent_config['name']))

    restart_celery_worker(runner, agent_config)

def get_agent_ip(ctx, agent_config):
    if is_on_management_worker(ctx):
        return utils.get_manager_ip()
    return agent_config['host']

def create_celery_configuration(ctx, runner, agent_config, resource_loader):
    create_celery_includes_file(ctx, runner, agent_config)
    loader = jinja2.FunctionLoader(resource_loader)
    env = jinja2.Environment(loader=loader)
    config_template = env.get_template(CELERY_CONFIG_PATH.format(
        agent_config['distro']))
    config_template_values = {
        'includes_file_path': agent_config['includes_file'],
        'celery_base_dir': agent_config['celery_base_dir'],
        'worker_modifier': agent_config['name'],
        'management_ip': utils.get_manager_ip(),
        'broker_ip': '127.0.0.1' if is_on_management_worker(ctx)
        else utils.get_manager_ip(),
        'agent_ip': get_agent_ip(ctx, agent_config),
        'celery_user': agent_config['user'],
        'celery_group': agent_config['user'],
        'worker_autoscale': '{0},{1}'.format(agent_config['max_workers'],
                                             agent_config['min_workers'])
    }

    ctx.logger.debug(
        'Populating celery config jinja2 template with the following '
        'values: {0}'.format(config_template_values))

    config = config_template.render(config_template_values)
    init_template = env.get_template(CELERY_INIT_PATH.format(
        agent_config['distro']))
    init_template_values = {
        'celery_base_dir': agent_config['celery_base_dir'],
        'worker_modifier': agent_config['name']
    }

    ctx.logger.debug(
        'Populating celery init.d jinja2 template with the following '
        'values: {0}'.format(init_template_values))

    init = init_template.render(init_template_values)

    ctx.logger.debug(
        'Creating celery config and init files [cloudify_agent={0}]'.format(
            agent_config))

    # runner.put(agent_config['config_file'], config, use_sudo=True)
    # runner.put(agent_config['init_file'], init, use_sudo=True)
    celery_config_url = get_agent_resource_url(
        ctx, agent_config, 'celery_config_path')
    celery_init_url = get_agent_resource_url(
        ctx, agent_config, 'celery_init_path')

    r = download_resource_on_host(
        ctx.logger, runner, celery_config_url, config)
    if not r:
        raise NonRecoverableError('failed to download celery config file')
    r = download_resource_on_host(ctx.logger, runner, celery_init_url, init)
    if not r:
        raise NonRecoverableError('failed to download celery init file')

def create_celery_includes_file(ctx, runner, agent_config):
    # build initial includes
    includes_list = get_celery_includes_list()

    runner.put(agent_config['includes_file'],
               'INCLUDES={0}\n'.format(','.join(includes_list)))

    ctx.logger.debug('Created celery includes file [file=%s, content=%s]',
                     agent_config['includes_file'],
                     includes_list)

def worker_exists(runner, agent_config):
    return runner.exists(agent_config['base_dir'])

def restart_celery_worker(runner, agent_config):
    runner.run("sudo service celeryd-{0} restart".format(
        agent_config['name']))
    _wait_for_started(runner, agent_config)

def _verify_no_celery_error(runner, agent_config):
    celery_error_out = os.path.join(
        agent_config['base_dir'], 'work/celery_error.out')

    # this means the celery worker had an uncaught
    #  exception and it wrote its content
    # to the file above because of our custom exception handler (see celery.py)
    if runner.exists(celery_error_out):
        output = runner.get(celery_error_out)
        runner.run('rm {0}'.format(celery_error_out))
        raise NonRecoverableError(
            'Celery worker failed to start:\n{0}'.format(output))

def _wait_for_started(runner, agent_config):
    _verify_no_celery_error(runner, agent_config)
    worker_name = 'celery.{}'.format(agent_config['name'])
    inspect = celery_client.control.inspect(destination=[worker_name])
    wait_started_timeout = agent_config['wait_started_timeout']
    timeout = time.time() + wait_started_timeout
    interval = agent_config['wait_started_interval']
    while time.time() < timeout:
        stats = (inspect.stats() or {}).get(worker_name)
        if stats:
            return
        time.sleep(interval)
    _verify_no_celery_error(runner, agent_config)
    raise NonRecoverableError('Failed starting agent. waited for {} seconds.'
                              .format(wait_started_timeout))
<|endoftext|>