<commit_before>import time
import os, subprocess
import tempfile

from webassets.filter import Filter

__all__ = ('LessFilter',)

class LessFilter(Filter):
    """Converts `Less <http://lesscss.org/>`_ markup to real CSS.

    If you want to combine it with other CSS filters, make sure this
    one runs first.

    **Note**: Currently, this needs to be the very first filter
    applied. Changes by filters that ran before will be lost.
    """
    """XXX: This currently needs to be the very first filter applied. This is
    because it uses the "source filter" mechanism to support "@includes"
    in less, i.e. it let's the less compiler work directly with the source
    file, and ignores the input stream. Filters previously already applied
    will be lost. Ways to solve this:
        - Let filters specify that they need to be first (and auto do so,
          or raise an exception).
        - Rewrite the less filter:
             - It could properly use the input stream, and just create the
               temp file in the same directory as the input path.
             - It could rewrite @includes via regex, as the cssrewrite filter
               does, before passing the tempfile on to lessc.

    XXX: Depending on how less is actually used in practice, it might actually
    be a valid use case to NOT have this be a source filter, so that one can
    split the css files into various less files, referencing variables in other
    files' - without using @include, instead having them merged together by
    django-assets. This will currently not work because we compile each
    file separately, and the compiler would fail at undefined variables.
    """

    name = 'less'

    def __init__(self):
        self.less = self.get_config('LESS_PATH', what='less binary')

    def input(self, _in, out, source_path, output_path):
        """Less currently doesn't take data from stdin, and doesn't allow
        us from stdout either. Neither does it return a proper non-0 error
        code when an error occurs, or even write to stderr (stdout instead)!

        Hopefully this will improve in the future:

        http://groups.google.com/group/lesscss/browse_thread/thread/3aed033a44c51b4c/b713148afde87e81
        """
        # TODO: Use NamedTemporaryFile.
        outtemp_name = os.path.join(tempfile.gettempdir(),
                                    'assets_temp_%d.css' % int(time.time()))

        proc = subprocess.Popen([self.less, source_path, outtemp_name],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                # shell: necessary on windows to execute
                                # ruby files, but doesn't work on linux.
                                shell=(os.name == 'nt'))
        stdout, stderr = proc.communicate()

        # less only writes to stdout, as noted in the method doc, but
        # check everything anyway.
        if stdout or stderr or proc.returncode != 0:
            if os.path.exists(outtemp_name):
                os.unlink(outtemp_name)
            raise Exception(('less: subprocess had error: stderr=%s, '+
                            'stdout=%s, returncode=%s') % (
                                            stderr, stdout, proc.returncode))

        outtemp = open(outtemp_name)
        try:
            out.write(outtemp.read())
        finally:
            outtemp.close()

            os.unlink(outtemp_name)<commit_msg>Less filter was doing setup within __init__, rather than the dedicated setup() method.<commit_after>import time
import os, subprocess
import tempfile

from webassets.filter import Filter

__all__ = ('LessFilter',)

class LessFilter(Filter):
    """Converts `Less <http://lesscss.org/>`_ markup to real CSS.

    If you want to combine it with other CSS filters, make sure this
    one runs first.

    **Note**: Currently, this needs to be the very first filter
    applied. Changes by filters that ran before will be lost.
    """
    """XXX: This currently needs to be the very first filter applied. This is
    because it uses the "source filter" mechanism to support "@includes"
    in less, i.e. it let's the less compiler work directly with the source
    file, and ignores the input stream. Filters previously already applied
    will be lost. Ways to solve this:
        - Let filters specify that they need to be first (and auto do so,
          or raise an exception).
        - Rewrite the less filter:
             - It could properly use the input stream, and just create the
               temp file in the same directory as the input path.
             - It could rewrite @includes via regex, as the cssrewrite filter
               does, before passing the tempfile on to lessc.

    XXX: Depending on how less is actually used in practice, it might actually
    be a valid use case to NOT have this be a source filter, so that one can
    split the css files into various less files, referencing variables in other
    files' - without using @include, instead having them merged together by
    django-assets. This will currently not work because we compile each
    file separately, and the compiler would fail at undefined variables.
    """

    name = 'less'

    def setup(self):
        self.less = self.get_config('LESS_PATH', what='less binary')

    def input(self, _in, out, source_path, output_path):
        """Less currently doesn't take data from stdin, and doesn't allow
        us from stdout either. Neither does it return a proper non-0 error
        code when an error occurs, or even write to stderr (stdout instead)!

        Hopefully this will improve in the future:

        http://groups.google.com/group/lesscss/browse_thread/thread/3aed033a44c51b4c/b713148afde87e81
        """
        # TODO: Use NamedTemporaryFile.
        outtemp_name = os.path.join(tempfile.gettempdir(),
                                    'assets_temp_%d.css' % int(time.time()))

        proc = subprocess.Popen([self.less, source_path, outtemp_name],
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                # shell: necessary on windows to execute
                                # ruby files, but doesn't work on linux.
                                shell=(os.name == 'nt'))
        stdout, stderr = proc.communicate()

        # less only writes to stdout, as noted in the method doc, but
        # check everything anyway.
        if stdout or stderr or proc.returncode != 0:
            if os.path.exists(outtemp_name):
                os.unlink(outtemp_name)
            raise Exception(('less: subprocess had error: stderr=%s, '+
                            'stdout=%s, returncode=%s') % (
                                            stderr, stdout, proc.returncode))

        outtemp = open(outtemp_name)
        try:
            out.write(outtemp.read())
        finally:
            outtemp.close()

            os.unlink(outtemp_name)<|endoftext|>


<commit_before>import time

from wirecloudcommons.test import widget_operation, WirecloudSeleniumTestCase

class BasicSeleniumTests(WirecloudSeleniumTestCase):

    tags = ('fiware-ut-5',)

    def check_popup_menu(self, must_be, must_be_absent):

        time.sleep(0.1)

        for item in must_be:
            menu_item = self.get_popup_menu_item(item)
            self.assertIsNotNone(menu_item)

        for item in must_be_absent:
            menu_item = self.get_popup_menu_item(item)
            self.assertIsNone(menu_item)

    def test_basic_workspace_operations(self):

        self.login()

        # We need atleast one Workspace, so we cannot delete current workspace
        self.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level > .icon-menu').click()
        self.check_popup_menu(('Rename', 'Settings', 'New workspace', 'Publish'), ('Remove',))
        self.driver.find_element_by_class_name('disable-layer').click()

        self.create_workspace('Test')

        # Now we have two workspaces so we can remove any of them
        self.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level > .icon-menu').click()
        self.check_popup_menu(('Rename', 'Settings', 'New workspace', 'Publish', 'Remove'), ())
        self.driver.find_element_by_class_name('disable-layer').click()

        self.rename_workspace('test2')
        tab = self.get_workspace_tab_by_name('Tab')

        # Only one tab => we cannot remove it
        tab_menu_button = tab.find_element_by_css_selector('.icon-tab-menu')
        tab_menu_button.click()
        self.check_popup_menu(('Rename',), ('Remove',))
        self.driver.find_element_by_class_name('disable-layer').click()

        new_tab = self.add_tab()

        # Now we have two tabs so we can remove any of them
        tab_menu_button = tab.find_element_by_css_selector('.icon-tab-menu')
        tab_menu_button.click()
        self.check_popup_menu(('Rename', 'Remove'), ())
        self.driver.find_element_by_class_name('disable-layer').click()

        new_tab.click()
        tab_menu_button = new_tab.find_element_by_css_selector('.icon-tab-menu')
        tab_menu_button.click()
        self.check_popup_menu(('Rename', 'Remove'), ())

        # Remove the recently created one
        self.popup_menu_click('Remove')
        self.wait_wirecloud_ready()
        self.assertEqual(len(self.driver.find_elements_by_css_selector('#workspace .tab_wrapper .tab')), 1)

        self.remove_workspace()

        # Now we have only one workspace, so we cannot remove it
        self.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level > .icon-menu').click()
        self.check_popup_menu(('Rename', 'Settings', 'New workspace'), ('Remove',))
        self.driver.find_element_by_class_name('disable-layer').click()

    def test_add_widget_from_catalogue(self):

        self.login()
        self.assertEqual(self.count_iwidgets(), 0)
        self.add_widget_to_mashup('Test')
        self.assertEqual(self.count_iwidgets(), 1)

    def test_basic_widget_functionalities(self):

        self.login()
        self.add_widget_to_mashup('Test')

        with widget_operation(self.driver, 1):
            self.assertEqual(self.driver.find_element_by_id('listPref').text, 'default')
            self.assertEqual(self.driver.find_element_by_id('textPref').text, 'initial text')
            self.assertEqual(self.driver.find_element_by_id('booleanPref').text, 'false')
            self.assertEqual(self.driver.find_element_by_id('passwordPref').text, 'default')

        # Change widget settings
        self.driver.find_element_by_css_selector('.iwidget .settingsbutton').click()
        self.popup_menu_click('Settings')

        list_input = self.driver.find_element_by_css_selector('.window_menu [name="list"]')
        self.fill_form_input(list_input, '1')  # value1
        text_input = self.driver.find_element_by_css_selector('.window_menu [name="text"]')
        self.fill_form_input(text_input, 'test')
        boolean_input = self.driver.find_element_by_css_selector('.window_menu [name="boolean"]')
        boolean_input.click()
        password_input = self.driver.find_element_by_css_selector('.window_menu [name="password"]')
        self.fill_form_input(password_input, 'password')

        self.driver.find_element_by_xpath("//*[contains(@class, 'window_menu')]//*[text()='Accept']").click()

        with widget_operation(self.driver, 1):
            self.assertEqual(self.driver.find_element_by_id('listPref').text, '1')
            self.assertEqual(self.driver.find_element_by_id('textPref').text, 'test')
            self.assertEqual(self.driver.find_element_by_id('booleanPref').text, 'true')
            self.assertEqual(self.driver.find_element_by_id('passwordPref').text, 'password')

    test_basic_widget_functionalities.tags=('current',)
<commit_msg>Remove current tag in wirecloud.tests.selenium_tests<commit_after>import time

from wirecloudcommons.test import widget_operation, WirecloudSeleniumTestCase

class BasicSeleniumTests(WirecloudSeleniumTestCase):

    tags = ('fiware-ut-5',)

    def check_popup_menu(self, must_be, must_be_absent):

        time.sleep(0.1)

        for item in must_be:
            menu_item = self.get_popup_menu_item(item)
            self.assertIsNotNone(menu_item)

        for item in must_be_absent:
            menu_item = self.get_popup_menu_item(item)
            self.assertIsNone(menu_item)

    def test_basic_workspace_operations(self):

        self.login()

        # We need atleast one Workspace, so we cannot delete current workspace
        self.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level > .icon-menu').click()
        self.check_popup_menu(('Rename', 'Settings', 'New workspace', 'Publish'), ('Remove',))
        self.driver.find_element_by_class_name('disable-layer').click()

        self.create_workspace('Test')

        # Now we have two workspaces so we can remove any of them
        self.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level > .icon-menu').click()
        self.check_popup_menu(('Rename', 'Settings', 'New workspace', 'Publish', 'Remove'), ())
        self.driver.find_element_by_class_name('disable-layer').click()

        self.rename_workspace('test2')
        tab = self.get_workspace_tab_by_name('Tab')

        # Only one tab => we cannot remove it
        tab_menu_button = tab.find_element_by_css_selector('.icon-tab-menu')
        tab_menu_button.click()
        self.check_popup_menu(('Rename',), ('Remove',))
        self.driver.find_element_by_class_name('disable-layer').click()

        new_tab = self.add_tab()

        # Now we have two tabs so we can remove any of them
        tab_menu_button = tab.find_element_by_css_selector('.icon-tab-menu')
        tab_menu_button.click()
        self.check_popup_menu(('Rename', 'Remove'), ())
        self.driver.find_element_by_class_name('disable-layer').click()

        new_tab.click()
        tab_menu_button = new_tab.find_element_by_css_selector('.icon-tab-menu')
        tab_menu_button.click()
        self.check_popup_menu(('Rename', 'Remove'), ())

        # Remove the recently created one
        self.popup_menu_click('Remove')
        self.wait_wirecloud_ready()
        self.assertEqual(len(self.driver.find_elements_by_css_selector('#workspace .tab_wrapper .tab')), 1)

        self.remove_workspace()

        # Now we have only one workspace, so we cannot remove it
        self.driver.find_element_by_css_selector('#wirecloud_breadcrum .second_level > .icon-menu').click()
        self.check_popup_menu(('Rename', 'Settings', 'New workspace'), ('Remove',))
        self.driver.find_element_by_class_name('disable-layer').click()

    def test_add_widget_from_catalogue(self):

        self.login()
        self.assertEqual(self.count_iwidgets(), 0)
        self.add_widget_to_mashup('Test')
        self.assertEqual(self.count_iwidgets(), 1)

    def test_basic_widget_functionalities(self):

        self.login()
        self.add_widget_to_mashup('Test')

        with widget_operation(self.driver, 1):
            self.assertEqual(self.driver.find_element_by_id('listPref').text, 'default')
            self.assertEqual(self.driver.find_element_by_id('textPref').text, 'initial text')
            self.assertEqual(self.driver.find_element_by_id('booleanPref').text, 'false')
            self.assertEqual(self.driver.find_element_by_id('passwordPref').text, 'default')

        # Change widget settings
        self.driver.find_element_by_css_selector('.iwidget .settingsbutton').click()
        self.popup_menu_click('Settings')

        list_input = self.driver.find_element_by_css_selector('.window_menu [name="list"]')
        self.fill_form_input(list_input, '1')  # value1
        text_input = self.driver.find_element_by_css_selector('.window_menu [name="text"]')
        self.fill_form_input(text_input, 'test')
        boolean_input = self.driver.find_element_by_css_selector('.window_menu [name="boolean"]')
        boolean_input.click()
        password_input = self.driver.find_element_by_css_selector('.window_menu [name="password"]')
        self.fill_form_input(password_input, 'password')

        self.driver.find_element_by_xpath("//*[contains(@class, 'window_menu')]//*[text()='Accept']").click()

        with widget_operation(self.driver, 1):
            self.assertEqual(self.driver.find_element_by_id('listPref').text, '1')
            self.assertEqual(self.driver.find_element_by_id('textPref').text, 'test')
            self.assertEqual(self.driver.find_element_by_id('booleanPref').text, 'true')
            self.assertEqual(self.driver.find_element_by_id('passwordPref').text, 'password')
<|endoftext|>


<commit_before>import abc
import copy

import pecan
from pecan import rest
import six
from six.moves import http_client

from st2common.models.base import jsexpose
from st2common import log as logging

LOG = logging.getLogger(__name__)

RESERVED_QUERY_PARAMS = {
    'id': 'id',
    'name': 'name',
    'sort': 'order_by',
    'offset': 'offset',
    'limit': 'limit'
}

@six.add_metaclass(abc.ABCMeta)
class ResourceController(rest.RestController):
    model = abc.abstractproperty
    access = abc.abstractproperty
    supported_filters = abc.abstractproperty
    options = {
        'sort': []
    }

    def __init__(self):
        self.supported_filters = copy.deepcopy(self.__class__.supported_filters)
        self.supported_filters.update(RESERVED_QUERY_PARAMS)

    @jsexpose()
    def get_all(self, **kwargs):
        sort = kwargs.get('sort').split(',') if kwargs.get('sort') else []
        for i in range(len(sort)):
            sort.pop(i)
            direction = '-' if sort[i].startswith('-') else ''
            sort.insert(i, direction + self.supported_filters[sort[i]])
        kwargs['sort'] = sort if sort else copy.copy(self.options.get('sort'))
        filters = {v: kwargs[k] for k, v in six.iteritems(self.supported_filters) if kwargs.get(k)}
        instances = self.access.query(**filters)
        return [self.model.from_model(instance) for instance in instances]

    @jsexpose(str)
    def get_one(self, id):
        instance = self.access.get(id=id)
        if not instance:
            msg = 'Unable to identify resource with id "%s".' % id
            pecan.abort(http_client.NOT_FOUND, msg)
        return self.model.from_model(instance)
<commit_msg>Handle case when someone supplies a mongo non-conformant id.<commit_after>import abc
import copy

from mongoengine import ValidationError
import pecan
from pecan import rest
import six
from six.moves import http_client

from st2common.models.base import jsexpose
from st2common import log as logging

LOG = logging.getLogger(__name__)

RESERVED_QUERY_PARAMS = {
    'id': 'id',
    'name': 'name',
    'sort': 'order_by',
    'offset': 'offset',
    'limit': 'limit'
}

@six.add_metaclass(abc.ABCMeta)
class ResourceController(rest.RestController):
    model = abc.abstractproperty
    access = abc.abstractproperty
    supported_filters = abc.abstractproperty
    options = {
        'sort': []
    }

    def __init__(self):
        self.supported_filters = copy.deepcopy(self.__class__.supported_filters)
        self.supported_filters.update(RESERVED_QUERY_PARAMS)

    @jsexpose()
    def get_all(self, **kwargs):
        sort = kwargs.get('sort').split(',') if kwargs.get('sort') else []
        for i in range(len(sort)):
            sort.pop(i)
            direction = '-' if sort[i].startswith('-') else ''
            sort.insert(i, direction + self.supported_filters[sort[i]])
        kwargs['sort'] = sort if sort else copy.copy(self.options.get('sort'))
        filters = {v: kwargs[k] for k, v in six.iteritems(self.supported_filters) if kwargs.get(k)}
        instances = self.access.query(**filters)
        return [self.model.from_model(instance) for instance in instances]

    @jsexpose(str)
    def get_one(self, id):
        instance = None
        try:
            instance = self.access.get(id=id)
        except ValidationError:
            instance = None  # Someone supplied a mongo non-comformant id.

        if not instance:
            msg = 'Unable to identify resource with id "%s".' % id
            pecan.abort(http_client.NOT_FOUND, msg)
        return self.model.from_model(instance)
<|endoftext|>


<commit_before>class Info:
    '''Holds information of Elements and Compounds'''

    def __init__(self):
        self.data = {}
        self.data = self.data.fromkeys(
            ['number','name','symbol','mass','amount'])
        self.data = self.data.fromkeys(self.data.iterkeys(), 0)

    def change(self, key, value):
        '''Changes one of the data values'''
        for i in self.data:
            if i == key:
                self.data[key] = value
                return self.data[key]

    def number(self):
        return int(self.data['number'])
    def name(self):
        return int(self.data['name'])
    def symbol(self):
        return int(self.data['symbol'])
    def mass(self):
        return int(self.data['mass'])
    def amount(self):
        return int(self.data['amount'])

class Element:
    '''A class to hold element information'''

    def __init__(self, symbol):
        self.stat  = Info()
        self.stat.symbol = symbol

    def elementFind(self):
        '''Finds element in periodictable.txt'''
        f = open('periodictable.txt', 'r')

        for line in f:
            for word in line.split():
                if word == self.stat.symbol:
                    print hi,
                    #continue to find specific things

        f.close()

class Compound():
    '''A class to hold compounds, which hold class(Element)'''

    def __init__(self, symbol):
        self.stat  = Info()
        self.stat.symbol = symbol

    def amount(self):
        currentChar = [ ]
        amount = 0
        j = 0

        for i in range(0, len(self.stat.symbol)):

            currentChar = self.stat.symbol[i + j]

            if currentChar.isdigit():
                j += 1
            else:
                i = j
                break

        if not self.stat.symbol[0].isdigit():
            self.stat.change('amount', 1)
        else:
            self.stat.change('amount', self.stat.symbol[ 0 : j+1 ])

    def symbol(self):
        print self.stat.symbol

if __name__ == '__main__':
    j = 0
    compoundList = [ ]

    while True:

        print 'Input your BALANCED chemical equation (type \'help\' for help):'
        userInput = raw_input(">>> ")

        if userInput == 'help':
            print '-----------------------------------<HELP>-------------------------------------'
            print 'The expected input for this program is as follows:'
            print '\tR + R... -> P + P...'
            print '* R: Reactants (any order, seperated by the syntax, \' + \'(space plus space)'
            print '* ->: yields symbol, please put a space before and after it'
            print '* P: Products (any order, separated by the syntax, \' +  \'(space plus space)'
            print 'Any bugs, issues, requests? Put them in the GitHub repo.'
            print '------------------------------------------------------------------------------\n'

        else:
            break

    for i in userInput.split():

        if i[0].isalnum():
            compoundList.append( Compound(i) )
            compoundList[j].amount()
        else:

            pass

        j += 1

    #debug
    for i in compoundList:

        print i.stat.amount() + 10

    exit
<commit_msg>Changed Info.data type, Element.find() works<commit_after>class Info:
    '''Holds information of Elements and Compounds'''

    def __init__(self):
        #Real names (in order): symbol, number, mass, name, amount
        self.data = ['', 0, 0.0, '', 0]

    def index(self, value):
        '''Returns index value of corresponding real name'''
        try:
            value.isalpha()
        except:
            return value

        types = ['symbol', 'number', 'mass', 'name', 'amount']
        j = 0
        for i in types:
            if i == value:
                return j
            j += 1

    def change(self, index, value):
        '''Changes one of the data values'''
        index = self.index(index)
        self.data[index] = value
        print self.data

    def symbol(self):
        return self.data[0]
    def number(self):
        return self.data[1]
    def mass(self):
        return self.data[2]
    def name(self):
        return self.data[3]
    def amount(self):
        return self.data[4]

class Element:
    '''A class to hold element information'''

    def __init__(self, symbol):
        self.stat  = Info()
        self.stat.change('symbol', symbol)

    def find(self, value):
        '''Finds element in periodictable.txt, returns element mass'''
        f = open('periodictable.txt', 'r')

        value = self.stat.index(value)
        maxSearch = self.stat.index(value)
        print 'maxSearch: %d' % maxSearch
        j = 0
        for line in f:
            j += 1
            for i in range( maxSearch + 1 ):
                if line.split()[i] == self.stat.symbol():
                    f.close()
                    return line.split()[maxSearch]
        else:
            print 'Could not find element %s! Exiting program' % self.stat.symbol()
            f.close()
            exit(1)

class Compound():
    '''A class to hold compounds, which hold class(Element)'''

    def __init__(self, symbol):
        self.stat  = Info()
        self.stat.symbol = symbol

    def amount(self):
        currentChar = [ ]
        amount = 0
        j = 0

        for i in range(0, len(self.stat.symbol)):

            currentChar = self.stat.symbol[i + j]

            if currentChar.isdigit():
                j += 1
            else:
                i = j
                break

        if not self.stat.symbol[0].isdigit():
            self.stat.change('amount', 1)
        else:
            self.stat.change('amount', self.stat.symbol[ 0 : j+1 ])

if __name__ == '__main__':
    j = 0
    compoundList = [ ]

    while True:

        print 'Input your BALANCED chemical equation (type \'help\' for help)'
        userInput = raw_input(">>> ")

        if userInput == 'help':
            print '\nWelcome to the stoichiometry.py help page!\n'
            print 'The expected input for this program is as follows:'
            print '- R + R... -> P + P...'
            print '* R: Reactants (any order, seperated by the syntax, \' + \'(space plus space)'
            print '* ->: yields symbol, please put a space before and after it'
            print '* P: Products (any order, separated by the syntax, \' +  \'(space plus space)'
            print '\nAny bugs, issues, requests? Put them in the GitHub repo.\n'
        elif userInput == 'quit':
            exit(1)
        else:
            break

    for i in userInput.split():

        if i.isalnum():
            compoundList.append( Compound(i) )
            compoundList[compoundList.index(i)].amount()
        else:
            #Exception case ' ', '+', '->'
            pass

        j += 1

    #debug
    for i in compoundList:

        print i.stat.amount() + 10
<|endoftext|>


<commit_before># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import re

from collections import defaultdict

import pecan
from pecan.rest import RestController
import six

import st2common
from st2common import log as logging
from st2common.bootstrap.triggersregistrar import TriggersRegistrar
from st2common.bootstrap.sensorsregistrar import SensorsRegistrar
from st2common.bootstrap.actionsregistrar import ActionsRegistrar
from st2common.bootstrap.aliasesregistrar import AliasesRegistrar
from st2common.bootstrap.policiesregistrar import PolicyRegistrar
import st2common.bootstrap.policiesregistrar as policies_registrar
import st2common.bootstrap.runnersregistrar as runners_registrar
from st2common.bootstrap.rulesregistrar import RulesRegistrar
import st2common.bootstrap.ruletypesregistrar as rule_types_registrar
from st2common.bootstrap.configsregistrar import ConfigsRegistrar
import st2common.content.utils as content_utils
from st2common.models.api.base import jsexpose
from st2api.controllers.resource import ResourceController
from st2api.controllers.v1.actionexecutions import ActionExecutionsControllerMixin
from st2common.models.api.action import LiveActionCreateAPI
from st2common.models.api.pack import PackAPI
from st2common.models.api.pack import PackInstallRequestAPI
from st2common.models.api.pack import PackRegisterRequestAPI
from st2common.models.api.pack import PackSearchRequestAPI
from st2common.models.api.pack import PackAsyncAPI
from st2common.persistence.pack import Pack
from st2common.rbac.types import PermissionType
from st2common.rbac.decorators import request_user_has_permission
from st2common.rbac.decorators import request_user_has_resource_db_permission
from st2common.services import packs as packs_service

http_client = six.moves.http_client

__all__ = [
    'PacksController',
    'BasePacksController'
]

LOG = logging.getLogger(__name__)

ENTITIES = {
    'action': (ActionsRegistrar, 'actions'),
    'trigger': (TriggersRegistrar, 'triggers'),
    'sensor': (SensorsRegistrar, 'sensors'),
    'rule': (RulesRegistrar, 'rules'),
    'alias': (AliasesRegistrar, 'aliases'),
    'policy': (PolicyRegistrar, 'policies'),
    'config': (ConfigsRegistrar, 'configs')
}

class PackInstallController(ActionExecutionsControllerMixin, RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_INSTALL)
    @jsexpose(body_cls=PackInstallRequestAPI, status_code=http_client.ACCEPTED)
    def post(self, pack_install_request):
        parameters = {
            'packs': pack_install_request.packs,
        }

        if pack_install_request.force:
            parameters['force'] = True

        new_liveaction_api = LiveActionCreateAPI(action='packs.install',
                                                 parameters=parameters,
                                                 user=None)

        execution = self._handle_schedule_execution(liveaction_api=new_liveaction_api)

        return PackAsyncAPI(execution_id=execution.id)

class PackUninstallController(ActionExecutionsControllerMixin, RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_UNINSTALL)
    @jsexpose(body_cls=PackInstallRequestAPI, arg_types=[str], status_code=http_client.ACCEPTED)
    def post(self, pack_uninstall_request, ref_or_id=None):
        if ref_or_id:
            parameters = {
                'packs': [ref_or_id]
            }
        else:
            parameters = {
                'packs': pack_uninstall_request.packs
            }

        new_liveaction_api = LiveActionCreateAPI(action='packs.uninstall',
                                                 parameters=parameters,
                                                 user=None)

        execution = self._handle_schedule_execution(liveaction_api=new_liveaction_api)

        return PackAsyncAPI(execution_id=execution.id)

class PackRegisterController(RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_REGISTER)
    @jsexpose(body_cls=PackRegisterRequestAPI)
    def post(self, pack_register_request):
        if pack_register_request and hasattr(pack_register_request, 'types'):
            types = pack_register_request.types
        else:
            types = ['runner', 'action', 'trigger', 'sensor', 'rule', 'rule_type', 'alias',
                     'policy_type', 'policy', 'config']

        if pack_register_request and hasattr(pack_register_request, 'packs'):
            packs = list(set(pack_register_request.packs))
        else:
            packs = None

        result = defaultdict(int)

        # Register depended resources (actions depend on runners, rules depend on rule types, etc)
        if ('runner' in types or 'runners' in types) or ('action' in types or 'actions' in types):
            result['runners'] = runners_registrar.register_runners(experimental=True)
        if ('rule_type' in types or 'rule_types' in types) or \
           ('rule' in types or 'rules' in types):
            result['rule_types'] = rule_types_registrar.register_rule_types()
        if ('policy_type' in types or 'policy_types' in types) or \
           ('policy' in types or 'policies' in types):
            result['policy_types'] = policies_registrar.register_policy_types(st2common)

        use_pack_cache = False

        fail_on_failure = getattr(pack_register_request, 'fail_on_failure', True)
        for type, (Registrar, name) in six.iteritems(ENTITIES):
            if type in types or name in types:
                registrar = Registrar(use_pack_cache=use_pack_cache,
                                      fail_on_failure=fail_on_failure)
                if packs:
                    for pack in packs:
                        pack_path = content_utils.get_pack_base_path(pack)

                        try:
                            registered_count = registrar.register_from_pack(pack_dir=pack_path)
                            result[name] += registered_count
                        except ValueError as e:
                            # Throw more user-friendly exception if requsted pack doesn't exist
                            if re.match('Directory ".*?" doesn\'t exist', str(e)):
                                msg = 'Pack "%s" not found on disk: %s' % (pack, str(e))
                                raise ValueError(msg)

                            raise e
                else:
                    packs_base_paths = content_utils.get_packs_base_paths()
                    registered_count = registrar.register_from_packs(base_dirs=packs_base_paths)
                    result[name] += registered_count

        return result

class PackSearchController(RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_SEARCH)
    @jsexpose(body_cls=PackSearchRequestAPI)
    def post(self, pack_search_request):
        if hasattr(pack_search_request, 'query'):
            packs = packs_service.search_pack_index(pack_search_request.query,
                                                    case_sensitive=False)
            return [PackAPI(**pack) for pack in packs]
        else:
            pack = packs_service.get_pack_from_index(pack_search_request.pack)
            return PackAPI(**pack) if pack else None

class IndexHealthController(RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_VIEW_INDEX_HEALTH)
    @jsexpose()
    def get(self):
        """
        Check if all listed indexes are healthy: they should be reachable,
        return valid JSON objects, and yield more than one result.
        """
        _, status = packs_service.fetch_pack_index(allow_empty=True)

        health = {
            "indexes": {
                "count": len(status),
                "valid": 0,
                "invalid": 0,
                "errors": {},
                "status": status,
            },
            "packs": {
                "count": 0,
            },
        }

        for index in status:
            if index['error']:
                error_count = health['indexes']['errors'].get(index['error'], 0) + 1
                health['indexes']['invalid'] += 1
                health['indexes']['errors'][index['error']] = error_count
            else:
                health['indexes']['valid'] += 1
            health['packs']['count'] += index['packs']

        return health

class BasePacksController(ResourceController):
    model = PackAPI
    access = Pack

    def _get_one_by_ref_or_id(self, ref_or_id, exclude_fields=None):
        LOG.info('GET %s with ref_or_id=%s', pecan.request.path, ref_or_id)

        instance = self._get_by_ref_or_id(ref_or_id=ref_or_id, exclude_fields=exclude_fields)

        if not instance:
            msg = 'Unable to identify resource with ref_or_id "%s".' % (ref_or_id)
            pecan.abort(http_client.NOT_FOUND, msg)
            return

        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)
        result = self.model.from_model(instance, **from_model_kwargs)
        LOG.debug('GET %s with ref_or_id=%s, client_result=%s', pecan.request.path, ref_or_id,
                  result)

        return result

    def _get_by_ref_or_id(self, ref_or_id, exclude_fields=None):
        resource_db = self._get_by_id(resource_id=ref_or_id, exclude_fields=exclude_fields)

        if not resource_db:
            # Try ref
            resource_db = self._get_by_ref(ref=ref_or_id, exclude_fields=exclude_fields)

        return resource_db

    def _get_by_ref(self, ref, exclude_fields=None):
        """
        Note: In this case "ref" is pack name and not StackStorm's ResourceReference.
        """
        resource_db = self.access.query(ref=ref, exclude_fields=exclude_fields).first()
        return resource_db

class PacksIndexController(RestController):
    search = PackSearchController()
    health = IndexHealthController()

class PacksController(BasePacksController):
    from st2api.controllers.v1.packviews import PackViewsController

    model = PackAPI
    access = Pack
    supported_filters = {
        'name': 'name',
        'ref': 'ref'
    }

    query_options = {
        'sort': ['ref']
    }

    # Nested controllers
    install = PackInstallController()
    uninstall = PackUninstallController()
    register = PackRegisterController()
    views = PackViewsController()
    index = PacksIndexController()

    def __init__(self):
        super(PacksController, self).__init__()
        self.get_one_db_method = self._get_by_ref_or_id

    @request_user_has_permission(permission_type=PermissionType.PACK_LIST)
    @jsexpose()
    def get_all(self, **kwargs):
        return super(PacksController, self)._get_all(**kwargs)

    @request_user_has_resource_db_permission(permission_type=PermissionType.PACK_VIEW)
    @jsexpose(arg_types=[str])
    def get_one(self, ref_or_id):
        return self._get_one_by_ref_or_id(ref_or_id=ref_or_id)
<commit_msg>Fix "get_by_ref_or_id" to throw if model is not found.<commit_after># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import re

from collections import defaultdict

import pecan
from pecan.rest import RestController
import six

import st2common
from st2common import log as logging
from st2common.bootstrap.triggersregistrar import TriggersRegistrar
from st2common.bootstrap.sensorsregistrar import SensorsRegistrar
from st2common.bootstrap.actionsregistrar import ActionsRegistrar
from st2common.bootstrap.aliasesregistrar import AliasesRegistrar
from st2common.bootstrap.policiesregistrar import PolicyRegistrar
import st2common.bootstrap.policiesregistrar as policies_registrar
import st2common.bootstrap.runnersregistrar as runners_registrar
from st2common.bootstrap.rulesregistrar import RulesRegistrar
import st2common.bootstrap.ruletypesregistrar as rule_types_registrar
from st2common.bootstrap.configsregistrar import ConfigsRegistrar
import st2common.content.utils as content_utils
from st2common.models.api.base import jsexpose
from st2api.controllers.resource import ResourceController
from st2api.controllers.v1.actionexecutions import ActionExecutionsControllerMixin
from st2common.models.api.action import LiveActionCreateAPI
from st2common.models.api.pack import PackAPI
from st2common.models.api.pack import PackInstallRequestAPI
from st2common.models.api.pack import PackRegisterRequestAPI
from st2common.models.api.pack import PackSearchRequestAPI
from st2common.models.api.pack import PackAsyncAPI
from st2common.exceptions.db import StackStormDBObjectNotFoundError
from st2common.persistence.pack import Pack
from st2common.rbac.types import PermissionType
from st2common.rbac.decorators import request_user_has_permission
from st2common.rbac.decorators import request_user_has_resource_db_permission
from st2common.services import packs as packs_service

http_client = six.moves.http_client

__all__ = [
    'PacksController',
    'BasePacksController'
]

LOG = logging.getLogger(__name__)

ENTITIES = {
    'action': (ActionsRegistrar, 'actions'),
    'trigger': (TriggersRegistrar, 'triggers'),
    'sensor': (SensorsRegistrar, 'sensors'),
    'rule': (RulesRegistrar, 'rules'),
    'alias': (AliasesRegistrar, 'aliases'),
    'policy': (PolicyRegistrar, 'policies'),
    'config': (ConfigsRegistrar, 'configs')
}

class PackInstallController(ActionExecutionsControllerMixin, RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_INSTALL)
    @jsexpose(body_cls=PackInstallRequestAPI, status_code=http_client.ACCEPTED)
    def post(self, pack_install_request):
        parameters = {
            'packs': pack_install_request.packs,
        }

        if pack_install_request.force:
            parameters['force'] = True

        new_liveaction_api = LiveActionCreateAPI(action='packs.install',
                                                 parameters=parameters,
                                                 user=None)

        execution = self._handle_schedule_execution(liveaction_api=new_liveaction_api)

        return PackAsyncAPI(execution_id=execution.id)

class PackUninstallController(ActionExecutionsControllerMixin, RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_UNINSTALL)
    @jsexpose(body_cls=PackInstallRequestAPI, arg_types=[str], status_code=http_client.ACCEPTED)
    def post(self, pack_uninstall_request, ref_or_id=None):
        if ref_or_id:
            parameters = {
                'packs': [ref_or_id]
            }
        else:
            parameters = {
                'packs': pack_uninstall_request.packs
            }

        new_liveaction_api = LiveActionCreateAPI(action='packs.uninstall',
                                                 parameters=parameters,
                                                 user=None)

        execution = self._handle_schedule_execution(liveaction_api=new_liveaction_api)

        return PackAsyncAPI(execution_id=execution.id)

class PackRegisterController(RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_REGISTER)
    @jsexpose(body_cls=PackRegisterRequestAPI)
    def post(self, pack_register_request):
        if pack_register_request and hasattr(pack_register_request, 'types'):
            types = pack_register_request.types
        else:
            types = ['runner', 'action', 'trigger', 'sensor', 'rule', 'rule_type', 'alias',
                     'policy_type', 'policy', 'config']

        if pack_register_request and hasattr(pack_register_request, 'packs'):
            packs = list(set(pack_register_request.packs))
        else:
            packs = None

        result = defaultdict(int)

        # Register depended resources (actions depend on runners, rules depend on rule types, etc)
        if ('runner' in types or 'runners' in types) or ('action' in types or 'actions' in types):
            result['runners'] = runners_registrar.register_runners(experimental=True)
        if ('rule_type' in types or 'rule_types' in types) or \
           ('rule' in types or 'rules' in types):
            result['rule_types'] = rule_types_registrar.register_rule_types()
        if ('policy_type' in types or 'policy_types' in types) or \
           ('policy' in types or 'policies' in types):
            result['policy_types'] = policies_registrar.register_policy_types(st2common)

        use_pack_cache = False

        fail_on_failure = getattr(pack_register_request, 'fail_on_failure', True)
        for type, (Registrar, name) in six.iteritems(ENTITIES):
            if type in types or name in types:
                registrar = Registrar(use_pack_cache=use_pack_cache,
                                      fail_on_failure=fail_on_failure)
                if packs:
                    for pack in packs:
                        pack_path = content_utils.get_pack_base_path(pack)

                        try:
                            registered_count = registrar.register_from_pack(pack_dir=pack_path)
                            result[name] += registered_count
                        except ValueError as e:
                            # Throw more user-friendly exception if requsted pack doesn't exist
                            if re.match('Directory ".*?" doesn\'t exist', str(e)):
                                msg = 'Pack "%s" not found on disk: %s' % (pack, str(e))
                                raise ValueError(msg)

                            raise e
                else:
                    packs_base_paths = content_utils.get_packs_base_paths()
                    registered_count = registrar.register_from_packs(base_dirs=packs_base_paths)
                    result[name] += registered_count

        return result

class PackSearchController(RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_SEARCH)
    @jsexpose(body_cls=PackSearchRequestAPI)
    def post(self, pack_search_request):
        if hasattr(pack_search_request, 'query'):
            packs = packs_service.search_pack_index(pack_search_request.query,
                                                    case_sensitive=False)
            return [PackAPI(**pack) for pack in packs]
        else:
            pack = packs_service.get_pack_from_index(pack_search_request.pack)
            return PackAPI(**pack) if pack else None

class IndexHealthController(RestController):

    @request_user_has_permission(permission_type=PermissionType.PACK_VIEW_INDEX_HEALTH)
    @jsexpose()
    def get(self):
        """
        Check if all listed indexes are healthy: they should be reachable,
        return valid JSON objects, and yield more than one result.
        """
        _, status = packs_service.fetch_pack_index(allow_empty=True)

        health = {
            "indexes": {
                "count": len(status),
                "valid": 0,
                "invalid": 0,
                "errors": {},
                "status": status,
            },
            "packs": {
                "count": 0,
            },
        }

        for index in status:
            if index['error']:
                error_count = health['indexes']['errors'].get(index['error'], 0) + 1
                health['indexes']['invalid'] += 1
                health['indexes']['errors'][index['error']] = error_count
            else:
                health['indexes']['valid'] += 1
            health['packs']['count'] += index['packs']

        return health

class BasePacksController(ResourceController):
    model = PackAPI
    access = Pack

    def _get_one_by_ref_or_id(self, ref_or_id, exclude_fields=None):
        LOG.info('GET %s with ref_or_id=%s', pecan.request.path, ref_or_id)

        instance = self._get_by_ref_or_id(ref_or_id=ref_or_id, exclude_fields=exclude_fields)

        if not instance:
            msg = 'Unable to identify resource with ref_or_id "%s".' % (ref_or_id)
            pecan.abort(http_client.NOT_FOUND, msg)
            return

        from_model_kwargs = self._get_from_model_kwargs_for_request(request=pecan.request)
        result = self.model.from_model(instance, **from_model_kwargs)
        LOG.debug('GET %s with ref_or_id=%s, client_result=%s', pecan.request.path, ref_or_id,
                  result)

        return result

    def _get_by_ref_or_id(self, ref_or_id, exclude_fields=None):
        resource_db = self._get_by_id(resource_id=ref_or_id, exclude_fields=exclude_fields)

        if not resource_db:
            # Try ref
            resource_db = self._get_by_ref(ref=ref_or_id, exclude_fields=exclude_fields)

        if not resource_db:
            msg = 'Resource with a ref or id "%s" not found' % (ref_or_id)
            raise StackStormDBObjectNotFoundError(msg)

        return resource_db

    def _get_by_ref(self, ref, exclude_fields=None):
        """
        Note: In this case "ref" is pack name and not StackStorm's ResourceReference.
        """
        resource_db = self.access.query(ref=ref, exclude_fields=exclude_fields).first()
        return resource_db

class PacksIndexController(RestController):
    search = PackSearchController()
    health = IndexHealthController()

class PacksController(BasePacksController):
    from st2api.controllers.v1.packviews import PackViewsController

    model = PackAPI
    access = Pack
    supported_filters = {
        'name': 'name',
        'ref': 'ref'
    }

    query_options = {
        'sort': ['ref']
    }

    # Nested controllers
    install = PackInstallController()
    uninstall = PackUninstallController()
    register = PackRegisterController()
    views = PackViewsController()
    index = PacksIndexController()

    def __init__(self):
        super(PacksController, self).__init__()
        self.get_one_db_method = self._get_by_ref_or_id

    @request_user_has_permission(permission_type=PermissionType.PACK_LIST)
    @jsexpose()
    def get_all(self, **kwargs):
        return super(PacksController, self)._get_all(**kwargs)

    @request_user_has_resource_db_permission(permission_type=PermissionType.PACK_VIEW)
    @jsexpose(arg_types=[str])
    def get_one(self, ref_or_id):
        return self._get_one_by_ref_or_id(ref_or_id=ref_or_id)
<|endoftext|>


<commit_before># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

from __future__ import absolute_import
import argparse
import json
import logging
import mock
import os
import requests
import tempfile
import yaml

from tests import base
from st2client import shell

LOG = logging.getLogger(__name__)

KEYVALUE = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system'
}

KEYVALUE_USER = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'user': 'stanley'
}

KEYVALUE_SECRET = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'secret': True
}

KEYVALUE_TTL = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'ttl': 100
}

KEYVALUE_OBJECT = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': {'obj': [1, True, 23.4, 'abc']},
    'scope': 'system',
}

KEYVALUE_ALL = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'user': 'stanley',
    'secret': True,
    'ttl': 100
}

KEYVALUE_MISSING_NAME = {
    'id': 'kv_name',
    'value': 'super cool value'
}

KEYVALUE_MISSING_VALUE = {
    'id': 'kv_name',
    'name': 'kv_name.'
}

class TestKeyValueBase(base.BaseCLITestCase):
    """Base class for "key" CLI tests
    """

    capture_output = True

    def __init__(self, *args, **kwargs):
        super(TestKeyValueBase, self).__init__(*args, **kwargs)

        self.parser = argparse.ArgumentParser()
        self.parser.add_argument('-t', '--token', dest='token')
        self.parser.add_argument('--api-key', dest='api_key')
        self.shell = shell.Shell()

    def setUp(self):
        super(TestKeyValueBase, self).setUp()

    def tearDown(self):
        super(TestKeyValueBase, self).tearDown()

class TestKeyValueLoad(TestKeyValueBase):

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE), 200, 'OK')))
    def test_load_keyvalue_json(self):
        """Test loading of key/value pair in JSON format
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE), 200, 'OK')))
    def test_load_keyvalue_yaml(self):
        """Test loading of key/value pair in YAML format
        """
        fd, path = tempfile.mkstemp(suffix='.yaml')
        try:
            with open(path, 'a') as f:
                f.write(yaml.safe_dump(KEYVALUE))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_USER), 200, 'OK')))
    def test_load_keyvalue_user(self):
        """Test loading of key/value pair with the optional user field
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_USER, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_SECRET), 200, 'OK')))
    def test_load_keyvalue_secret(self):
        """Test loading of key/value pair with the optional secret field
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_SECRET, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_TTL), 200, 'OK')))
    def test_load_keyvalue_ttl(self):
        """Test loading of key/value pair with the optional ttl field
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_TTL, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_OBJECT), 200, 'OK')))
    def test_load_keyvalue_object(self):
        """Test loading of key/value pair where the value is an object
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_OBJECT, indent=4))

            # test converting with short option
            args = ['key', 'load', '-c', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)

            # test converting with long option
            args = ['key', 'load', '--convert', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_OBJECT), 200, 'OK')))
    def test_load_keyvalue_object_fail(self):
        """Test failure to load key/value pair where the value is an object
           and the -c/--convert option is not passed
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_OBJECT, indent=4))

            # test converting with short option
            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertNotEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_ALL), 200, 'OK')))
    def test_load_keyvalue_all(self):
        """Test loading of key/value pair with all optional fields
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_ALL, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_ALL),
                                                      200, 'OK')))
    def test_load_keyvalue_array(self):
        """Test loading an array of key/value pairs
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            array = [KEYVALUE, KEYVALUE_ALL]
            json_str = json.dumps(array, indent=4)
            LOG.info(json_str)
            with open(path, 'a') as f:
                f.write(json_str)

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_missing_name(self):
        """Test loading of a key/value pair with the required field 'name' missing
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_MISSING_NAME, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 1)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_missing_value(self):
        """Test loading of a key/value pair with the required field 'value' missing
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_MISSING_VALUE, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 1)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_missing_file(self):
        """Test loading of a key/value pair with a missing file
        """
        path = '/some/file/that/doesnt/exist.json'
        args = ['key', 'load', path]
        retcode = self.shell.run(args)
        self.assertEqual(retcode, 1)

    def test_load_keyvalue_bad_file_extension(self):
        """Test loading of a key/value pair with a bad file extension
        """
        fd, path = tempfile.mkstemp(suffix='.badext')
        try:
            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 1)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_empty_file(self):
        """
        Loading K/V from an empty file shouldn't throw an error
        """
        fd, path = tempfile.mkstemp(suffix='.yaml')
        try:
            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)
<commit_msg>Improve 'st2 key load' test case by checking stdout output<commit_after># Licensed to the StackStorm, Inc ('StackStorm') under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

from __future__ import absolute_import
import argparse
import json
import logging
import mock
import os
import requests
import tempfile
import yaml

from tests import base
from st2client import shell

LOG = logging.getLogger(__name__)

KEYVALUE = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system'
}

KEYVALUE_USER = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'user': 'stanley'
}

KEYVALUE_SECRET = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'secret': True
}

KEYVALUE_TTL = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'ttl': 100
}

KEYVALUE_OBJECT = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': {'obj': [1, True, 23.4, 'abc']},
    'scope': 'system',
}

KEYVALUE_ALL = {
    'id': 'kv_name',
    'name': 'kv_name.',
    'value': 'super cool value',
    'scope': 'system',
    'user': 'stanley',
    'secret': True,
    'ttl': 100
}

KEYVALUE_MISSING_NAME = {
    'id': 'kv_name',
    'value': 'super cool value'
}

KEYVALUE_MISSING_VALUE = {
    'id': 'kv_name',
    'name': 'kv_name.'
}

class TestKeyValueBase(base.BaseCLITestCase):
    """Base class for "key" CLI tests
    """

    capture_output = True

    def __init__(self, *args, **kwargs):
        super(TestKeyValueBase, self).__init__(*args, **kwargs)

        self.parser = argparse.ArgumentParser()
        self.parser.add_argument('-t', '--token', dest='token')
        self.parser.add_argument('--api-key', dest='api_key')
        self.shell = shell.Shell()

    def setUp(self):
        super(TestKeyValueBase, self).setUp()

    def tearDown(self):
        super(TestKeyValueBase, self).tearDown()

class TestKeyValueLoad(TestKeyValueBase):

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE), 200, 'OK')))
    def test_load_keyvalue_json(self):
        """Test loading of key/value pair in JSON format
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE), 200, 'OK')))
    def test_load_keyvalue_yaml(self):
        """Test loading of key/value pair in YAML format
        """
        fd, path = tempfile.mkstemp(suffix='.yaml')
        try:
            with open(path, 'a') as f:
                f.write(yaml.safe_dump(KEYVALUE))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_USER), 200, 'OK')))
    def test_load_keyvalue_user(self):
        """Test loading of key/value pair with the optional user field
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_USER, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_SECRET), 200, 'OK')))
    def test_load_keyvalue_secret(self):
        """Test loading of key/value pair with the optional secret field
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_SECRET, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_TTL), 200, 'OK')))
    def test_load_keyvalue_ttl(self):
        """Test loading of key/value pair with the optional ttl field
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_TTL, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_OBJECT), 200, 'OK')))
    def test_load_keyvalue_object(self):
        """Test loading of key/value pair where the value is an object
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_OBJECT, indent=4))

            # test converting with short option
            args = ['key', 'load', '-c', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)

            # test converting with long option
            args = ['key', 'load', '--convert', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_OBJECT), 200, 'OK')))
    def test_load_keyvalue_object_fail(self):
        """Test failure to load key/value pair where the value is an object
           and the -c/--convert option is not passed
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_OBJECT, indent=4))

            # test converting with short option
            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertNotEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_ALL), 200, 'OK')))
    def test_load_keyvalue_all(self):
        """Test loading of key/value pair with all optional fields
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_ALL, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    @mock.patch.object(
        requests, 'put',
        mock.MagicMock(return_value=base.FakeResponse(json.dumps(KEYVALUE_ALL),
                                                      200, 'OK')))
    def test_load_keyvalue_array(self):
        """Test loading an array of key/value pairs
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            array = [KEYVALUE, KEYVALUE_ALL]
            json_str = json.dumps(array, indent=4)
            LOG.info(json_str)
            with open(path, 'a') as f:
                f.write(json_str)

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_missing_name(self):
        """Test loading of a key/value pair with the required field 'name' missing
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_MISSING_NAME, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 1)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_missing_value(self):
        """Test loading of a key/value pair with the required field 'value' missing
        """
        fd, path = tempfile.mkstemp(suffix='.json')
        try:
            with open(path, 'a') as f:
                f.write(json.dumps(KEYVALUE_MISSING_VALUE, indent=4))

            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 1)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_missing_file(self):
        """Test loading of a key/value pair with a missing file
        """
        path = '/some/file/that/doesnt/exist.json'
        args = ['key', 'load', path]
        retcode = self.shell.run(args)
        self.assertEqual(retcode, 1)

    def test_load_keyvalue_bad_file_extension(self):
        """Test loading of a key/value pair with a bad file extension
        """
        fd, path = tempfile.mkstemp(suffix='.badext')
        try:
            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertEqual(retcode, 1)
        finally:
            os.close(fd)
            os.unlink(path)

    def test_load_keyvalue_empty_file(self):
        """
        Loading K/V from an empty file shouldn't throw an error
        """
        fd, path = tempfile.mkstemp(suffix='.yaml')
        try:
            args = ['key', 'load', path]
            retcode = self.shell.run(args)
            self.assertTrue('No matching items found' in self.stdout.getvalue())
            self.assertEqual(retcode, 0)
        finally:
            os.close(fd)
            os.unlink(path)
<|endoftext|>


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

from twisted.internet import ssl
import traceback

from twisted.internet import reactor
from twisted.web import server

from jsonrpc.server import ServerEvents, JSON_RPC

import tabular_predDB.jsonrpc_http.Engine as E
Engine_methods = E.get_method_names()

from tabular_predDB.jsonrpc_http.Engine import Engine
engine = Engine()

class ExampleServer(ServerEvents):
	# inherited hooks
	def log(self, responses, txrequest, error):
		print(txrequest.code, end=' ')
		if isinstance(responses, list):
			for response in responses:
				msg = self._get_msg(response)
				print(txrequest, msg)
		else:
			msg = self._get_msg(responses)
			print(txrequest, msg)

	def findmethod(self, method, args=None, kwargs=None):
		if method in self.methods:
			return getattr(engine, method)
		else:
			return None

	# helper methods
	methods = set(Engine_methods)
	def _get_msg(self, response):
		print('response', repr(response))
		return ' '.join(str(x) for x in [response.id, response.result or response.error])

root = JSON_RPC().customize(ExampleServer)
site = server.Site(root)

# 8007 is the port you want to run under. Choose something >1024
PORT = 8007
print('Listening on port %d...' % PORT)
reactor.listenTCP(PORT, site)
reactor.run()
<commit_msg>fix "no id attr" issue<commit_after>from __future__ import print_function
#
#  Copyright (c) 2011 Edward Langley
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#  Redistributions of source code must retain the above copyright notice,
#  this list of conditions and the following disclaimer.
#
#  Redistributions in binary form must reproduce the above copyright
#  notice, this list of conditions and the following disclaimer in the
#  documentation and/or other materials provided with the distribution.
#
#  Neither the name of the project's author nor the names of its
#  contributors may be used to endorse or promote products derived from
#  this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
#  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
#  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#

from twisted.internet import ssl
import traceback

from twisted.internet import reactor
from twisted.web import server

from jsonrpc.server import ServerEvents, JSON_RPC

import tabular_predDB.jsonrpc_http.Engine as E
Engine_methods = E.get_method_names()

from tabular_predDB.jsonrpc_http.Engine import Engine
engine = Engine()

class ExampleServer(ServerEvents):
	# inherited hooks
	def log(self, responses, txrequest, error):
		print(txrequest.code, end=' ')
		if isinstance(responses, list):
			for response in responses:
				msg = self._get_msg(response)
				print(txrequest, msg)
		else:
			msg = self._get_msg(responses)
			print(txrequest, msg)

	def findmethod(self, method, args=None, kwargs=None):
		if method in self.methods:
			return getattr(engine, method)
		else:
			return None

	# helper methods
	methods = set(Engine_methods)
	def _get_msg(self, response):
		print('response', repr(response))
		ret_str = str(response)
		if hasattr(response, 'id'):
			to_strify = [response.id,
				     response.result or response.error]
			ret_str = ' '.join(map(str, to_strify))
		return ret_str

root = JSON_RPC().customize(ExampleServer)
site = server.Site(root)

# 8007 is the port you want to run under. Choose something >1024
PORT = 8007
print('Listening on port %d...' % PORT)
reactor.listenTCP(PORT, site)
reactor.run()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from openerp import models, fields, api

class TreeNode(models.AbstractModel):
    _name = 'suvit.tree.node.mixin'
    _description = u'Узел дерева'
    _order = 'parent_id,sequence,id'
    _use_full_ids = False
    _root_domain = [('parent_id', '=', False)]

    parent_id = fields.Many2one(string=u'Принадлежность',
                                comodel_name=_name)

    child_ids = fields.One2many(string=u'Состав',
                                comodel_name=_name,
                                inverse_name='parent_id')

    sequence = fields.Integer(string=u'Порядок',
                              default=99)

    object_id = fields.Reference(string=u'Связь',
                                 selection=[],
                                 )

    # Link
    shortcut_id = fields.Many2one(string="Дубль к",
                                  comodel_name=_name)
    duplicate_ids = fields.One2many(string=u'Дубли',
                                    comodel_name=_name,
                                    inverse_name='shortcut_id')
    self_id = fields.Many2one(string="Связь",
                              comodel_name=_name,
                              compute='compute_self')

    name = fields.Char(string=u'Наименование',
                       compute='compute_name',
                       store=True,
                       readonly=False)

    title = fields.Char(string=u'Подсказка',
                        compute='compute_title')

    @api.model
    def create(self, vals):
        print 'TreeNode.create', vals
        new_obj = super(TreeNode, self).create(vals)

        # XXX ugly hack to fixed depends override
        if not new_obj.name and 'name' in vals:
            new_obj.name = vals['name']

        return new_obj

    @api.multi
    def write(self, vals):
        print 'TreeNode.write', vals

        return super(TreeNode, self).write(vals)

    @api.multi
    @api.onchange('shortcut_id', 'object_id')
    @api.depends('shortcut_id', 'object_id')
    def compute_name(self):
        for rec in self:
            if rec.shortcut_id:
                rec.name = u'[Я] %s' % rec.shortcut_id.name
            elif rec.object_id:
                rec.name = getattr(rec.object_id, rec.object_id._rec_name or 'title', '-')

    @api.multi
    def compute_title(self):
        for rec in self:
            tooltip = getattr(rec.object_id, 'tooltip', None)
            if not tooltip:
                tooltip = getattr(rec.object_id, 'title', rec.name)
            rec.title = tooltip

    @api.multi
    def compute_self(self):
        for rec in self:
            self_id = rec
            if rec.shortcut_id:
                while self_id.shortcut_id:
                    self_id = self_id.shortcut_id

            rec.self_id = self_id

    @api.multi
    def action_remove(self):
        self.write({'parent_id': False})

    @api.multi
    def action_change_parent(self, new_parent_id):

        if new_parent_id:
            new_parent = self.browse(new_parent_id).self_id
            #new_parent_obj = new_parent.tree_obj_id
        else:
            new_parent = new_parent_obj = self

        old_parent_id = self.env.context.get('old_parent_id')
        if old_parent_id:
            old_parent = self.browse(old_parent_id).self_id
            #old_parent_obj = old_parent.tree_obj_id
        else:
            old_parent = old_parent_obj = self

        sequence = self.env.context.get('new_position')

        # print 'TreeNode.change_parent', old_parent, new_parent, sequence
        if old_parent != new_parent:
            self.write({'parent_id': new_parent.id})

        self.action_change_sequence(new_parent, sequence)

    @api.multi
    def action_change_sequence(self, new_parent, sequence):
        if sequence is None:
            return

        if new_parent:
            child_ids = new_parent.child_ids
        else:
            # Tree root objects
            child_ids = self.search(self._root_domain)

        # print 'change_sequence', [(c.id, c.sequence) for c in child_ids], sequence
        i = 0
        for child in child_ids:
            if child == self:
                continue

            # print 'change', obj, child, i, sequence
            if i < sequence:
                child.sequence = i
            else:
                child.sequence = i + 1
            i += 1

        self.sequence = sequence
        # print 'change_sequence_after', [(c.id, c.sequence) for c in child_ids]

    # API for full ids
    @api.multi
    def evaluate_ids(self):
        if not any(isinstance(id, basestring) for id in self.ids):
            return

        new_ids = []
        for id in self.ids:
            new_ids.append(int(str(id).split('-')[-1]))

        # XXX This is needed to clear cache string ids
        self.invalidate_cache()
        self._ids = new_ids

    @api.multi
    def read(self, fields=None, *args, **kwargs):
        if not self._use_full_ids:
            return super(TreeNode, self).read(fields, *args, **kwargs)

        self.evaluate_ids()

        res = super(TreeNode, self).read(fields, *args, **kwargs)

        parents = self.env.context.get('tree_parent_ids')
        if parents:
            parent_prefix = '-'.join(str(x) for x in parents)
        else:
            parent_prefix = None

        for row in res:
            if parent_prefix:
                row['real_id'] = row['id']
                row['id'] = '%s-%s' % (parent_prefix, row['id'])

            if 'tree_child_ids' in row:
                new_children = []
                for child in row['tree_child_ids']:
                    new_children.append('%s-%s' % (row['id'], child if isinstance(child, int) else child.id))
                row['tree_child_ids'] = new_children
        return res

    @api.multi
    def get_formview_action(self):
        self.ensure_one()

        obj = self.self_id
        if 'node_settings_form' not in self.env.context:
            obj = obj.object_id or obj

        if isinstance(obj, TreeNode):
            obj = super(TreeNode, obj)

        act = obj.get_formview_action()
        return act[0] if type(act) == list else act
<commit_msg>comment prints<commit_after># -*- coding: utf-8 -*-
from openerp import models, fields, api

class TreeNode(models.AbstractModel):
    _name = 'suvit.tree.node.mixin'
    _description = u'Узел дерева'
    _order = 'parent_id,sequence,id'
    _use_full_ids = False
    _root_domain = [('parent_id', '=', False)]

    parent_id = fields.Many2one(string=u'Принадлежность',
                                comodel_name=_name)

    child_ids = fields.One2many(string=u'Состав',
                                comodel_name=_name,
                                inverse_name='parent_id')

    sequence = fields.Integer(string=u'Порядок',
                              default=99)

    object_id = fields.Reference(string=u'Связь',
                                 selection=[],
                                 )

    # Link
    shortcut_id = fields.Many2one(string="Дубль к",
                                  comodel_name=_name)
    duplicate_ids = fields.One2many(string=u'Дубли',
                                    comodel_name=_name,
                                    inverse_name='shortcut_id')
    self_id = fields.Many2one(string="Связь",
                              comodel_name=_name,
                              compute='compute_self')

    name = fields.Char(string=u'Наименование',
                       compute='compute_name',
                       store=True,
                       readonly=False)

    title = fields.Char(string=u'Подсказка',
                        compute='compute_title')

    @api.model
    def create(self, vals):
        # print 'TreeNode.create', vals
        new_obj = super(TreeNode, self).create(vals)

        # XXX ugly hack to fixed depends override
        if not new_obj.name and 'name' in vals:
            new_obj.name = vals['name']

        return new_obj

    @api.multi
    def write(self, vals):
        # print 'TreeNode.write', vals
        return super(TreeNode, self).write(vals)

    @api.multi
    @api.onchange('shortcut_id', 'object_id')
    @api.depends('shortcut_id', 'object_id')
    def compute_name(self):
        for rec in self:
            if rec.shortcut_id:
                rec.name = u'[Я] %s' % rec.shortcut_id.name
            elif rec.object_id:
                rec.name = getattr(rec.object_id, rec.object_id._rec_name or 'title', '-')

    @api.multi
    def compute_title(self):
        for rec in self:
            tooltip = getattr(rec.object_id, 'tooltip', None)
            if not tooltip:
                tooltip = getattr(rec.object_id, 'title', rec.name)
            rec.title = tooltip

    @api.multi
    def compute_self(self):
        for rec in self:
            self_id = rec
            if rec.shortcut_id:
                while self_id.shortcut_id:
                    self_id = self_id.shortcut_id

            rec.self_id = self_id

    @api.multi
    def action_remove(self):
        self.write({'parent_id': False})

    @api.multi
    def action_change_parent(self, new_parent_id):

        if new_parent_id:
            new_parent = self.browse(new_parent_id).self_id
            #new_parent_obj = new_parent.tree_obj_id
        else:
            new_parent = new_parent_obj = self

        old_parent_id = self.env.context.get('old_parent_id')
        if old_parent_id:
            old_parent = self.browse(old_parent_id).self_id
            #old_parent_obj = old_parent.tree_obj_id
        else:
            old_parent = old_parent_obj = self

        sequence = self.env.context.get('new_position')

        # print 'TreeNode.change_parent', old_parent, new_parent, sequence
        if old_parent != new_parent:
            self.write({'parent_id': new_parent.id})

        self.action_change_sequence(new_parent, sequence)

    @api.multi
    def action_change_sequence(self, new_parent, sequence):
        if sequence is None:
            return

        if new_parent:
            child_ids = new_parent.child_ids
        else:
            # Tree root objects
            child_ids = self.search(self._root_domain)

        # print 'change_sequence', [(c.id, c.sequence) for c in child_ids], sequence
        i = 0
        for child in child_ids:
            if child == self:
                continue

            # print 'change', obj, child, i, sequence
            if i < sequence:
                child.sequence = i
            else:
                child.sequence = i + 1
            i += 1

        self.sequence = sequence
        # print 'change_sequence_after', [(c.id, c.sequence) for c in child_ids]

    # API for full ids
    @api.multi
    def evaluate_ids(self):
        if not any(isinstance(id, basestring) for id in self.ids):
            return

        new_ids = []
        for id in self.ids:
            new_ids.append(int(str(id).split('-')[-1]))

        # XXX This is needed to clear cache string ids
        self.invalidate_cache()
        self._ids = new_ids

    @api.multi
    def read(self, fields=None, *args, **kwargs):
        if not self._use_full_ids:
            return super(TreeNode, self).read(fields, *args, **kwargs)

        self.evaluate_ids()

        res = super(TreeNode, self).read(fields, *args, **kwargs)

        parents = self.env.context.get('tree_parent_ids')
        if parents:
            parent_prefix = '-'.join(str(x) for x in parents)
        else:
            parent_prefix = None

        for row in res:
            if parent_prefix:
                row['real_id'] = row['id']
                row['id'] = '%s-%s' % (parent_prefix, row['id'])

            if 'tree_child_ids' in row:
                new_children = []
                for child in row['tree_child_ids']:
                    new_children.append('%s-%s' % (row['id'], child if isinstance(child, int) else child.id))
                row['tree_child_ids'] = new_children
        return res

    @api.multi
    def get_formview_action(self):
        self.ensure_one()

        obj = self.self_id
        if 'node_settings_form' not in self.env.context:
            obj = obj.object_id or obj

        if isinstance(obj, TreeNode):
            obj = super(TreeNode, obj)

        act = obj.get_formview_action()
        return act[0] if type(act) == list else act
<|endoftext|>


<commit_before>disabled = False
try:
    # pyglet requires ctypes > 1.0.0
    import ctypes
    ctypes_major = int(ctypes.__version__.split('.')[0])
    if ctypes_major < 1:
        disabled = True
except:
    disabled = True

from sympy import symbols, sin, cos
x,y = symbols('xy')

def test_import():
    from sympy import Plot

def test_plot_2d():
    from sympy import Plot
    p=Plot(x, [x, -5, 5, 4], visible=False)
    p.wait_for_calculations()

def test_plot_2d_discontinuous():
    from sympy import Plot
    p=Plot(1/x, [x, -1, 1, 2], visible=False)
    p.wait_for_calculations()

def test_plot_3d():
    from sympy import Plot
    p=Plot(x*y, [x, -5, 5, 5], [y, -5, 5, 5], visible=False)
    p.wait_for_calculations()

def test_plot_3d_discontinuous():
    from sympy import Plot
    p=Plot(1/x, [x, -3, 3, 6], [y, -1, 1, 1], visible=False)
    p.wait_for_calculations()

def test_plot_2d_polar():
    from sympy import Plot
    p=Plot(1/x, [x,-1,1,4], 'mode=polar', visible=False)
    p.wait_for_calculations()

def test_plot_3d_cylinder():
    from sympy import Plot
    p=Plot(1/y, [x,0,6.282,4], [y,-1,1,4], 'mode=polar;style=solid', visible=False)
    p.wait_for_calculations()

def test_plot_3d_spherical():
    from sympy import Plot
    p=Plot(1, [x,0,6.282,4], [y,0,3.141,4], 'mode=spherical;style=wireframe', visible=False)
    p.wait_for_calculations()

def test_plot_2d_parametric():
    from sympy import Plot
    p=Plot(sin(x), cos(x), [x, 0, 6.282, 4], visible=False)
    p.wait_for_calculations()

def test_plot_3d_parametric():
    from sympy import Plot
    p=Plot(sin(x), cos(x), x/5.0, [x, 0, 6.282, 4], visible=False)
    p.wait_for_calculations()

def _test_plot_log():
    from sympy import Plot
    p=Plot(log(x), [x,0,6.282,4], 'mode=polar', visible=False)
    p.wait_for_calculations()
<commit_msg>Don't run plotting tests if pyglet.gl fails to import<commit_after>disabled = False
try:
    # pyglet requires ctypes > 1.0.0
    import ctypes
    ctypes_major = int(ctypes.__version__.split('.')[0])
    if ctypes_major < 1:
        disabled = True
except:
    disabled = True

try:
    # if pyglet.gl fails to import, e.g. opengl is missing, we disable the tests
    from sympy.thirdparty import import_thirdparty
    pyglet = import_thirdparty("pyglet")

    import pyglet.gl
except:
    disabled = True

from sympy import symbols, sin, cos
x,y = symbols('xy')

def test_import():
    from sympy import Plot

def test_plot_2d():
    from sympy import Plot
    p=Plot(x, [x, -5, 5, 4], visible=False)
    p.wait_for_calculations()

def test_plot_2d_discontinuous():
    from sympy import Plot
    p=Plot(1/x, [x, -1, 1, 2], visible=False)
    p.wait_for_calculations()

def test_plot_3d():
    from sympy import Plot
    p=Plot(x*y, [x, -5, 5, 5], [y, -5, 5, 5], visible=False)
    p.wait_for_calculations()

def test_plot_3d_discontinuous():
    from sympy import Plot
    p=Plot(1/x, [x, -3, 3, 6], [y, -1, 1, 1], visible=False)
    p.wait_for_calculations()

def test_plot_2d_polar():
    from sympy import Plot
    p=Plot(1/x, [x,-1,1,4], 'mode=polar', visible=False)
    p.wait_for_calculations()

def test_plot_3d_cylinder():
    from sympy import Plot
    p=Plot(1/y, [x,0,6.282,4], [y,-1,1,4], 'mode=polar;style=solid', visible=False)
    p.wait_for_calculations()

def test_plot_3d_spherical():
    from sympy import Plot
    p=Plot(1, [x,0,6.282,4], [y,0,3.141,4], 'mode=spherical;style=wireframe', visible=False)
    p.wait_for_calculations()

def test_plot_2d_parametric():
    from sympy import Plot
    p=Plot(sin(x), cos(x), [x, 0, 6.282, 4], visible=False)
    p.wait_for_calculations()

def test_plot_3d_parametric():
    from sympy import Plot
    p=Plot(sin(x), cos(x), x/5.0, [x, 0, 6.282, 4], visible=False)
    p.wait_for_calculations()

def _test_plot_log():
    from sympy import Plot
    p=Plot(log(x), [x,0,6.282,4], 'mode=polar', visible=False)
    p.wait_for_calculations()
<|endoftext|>