<commit_before>import wx
from CommitList import CommitList, EVT_COMMITLIST_SELECT, EVT_COMMITLIST_RIGHTCLICK
from DiffViewer import DiffViewer
from Wizard import *
from git import GitError

# Menu item ids
MENU_CHECKOUT_DETACHED  = 10000
MENU_RESET_BRANCH       = 10001
MENU_CREATE_BRANCH      = 11000
MENU_DELETE_BRANCH      = 12000
MENU_CHECKOUT_BRANCH    = 13000

# This array is used to provide unique ids for menu items
# that refer to a branch
branch_indexes = []

class HistoryTab(wx.Panel):
    def __init__(self, mainWindow, parent, id):
        # Layout
        wx.Panel.__init__(self, parent, id)
        self.mainWindow = mainWindow
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)

        # Splitter
        self.splitter = wx.SplitterWindow(self, -1)
        self.sizer.Add(self.splitter, True, wx.EXPAND, wx.ALL)

        # History graph
        self.commitList = CommitList(self.splitter, -1)
        self.Bind(EVT_COMMITLIST_SELECT, self.OnCommitSelected, self.commitList)
        self.Bind(EVT_COMMITLIST_RIGHTCLICK, self.OnCommitRightClick, self.commitList)

        self.diffViewer = DiffViewer(self.splitter, -1)

        self.splitter.SetMinimumPaneSize(20)
        self.splitter.SplitHorizontally(self.commitList, self.diffViewer, 200)

        # Context menu
        self.contextMenu = wx.Menu()
        wx.EVT_MENU(self, MENU_CREATE_BRANCH, self.OnCreateBranch)
        wx.EVT_MENU(self, MENU_CHECKOUT_DETACHED, self.OnCheckout)
        wx.EVT_MENU(self, MENU_RESET_BRANCH, self.OnResetBranch)

    def SetRepo(self, repo):
        # Branch indexes
        global branch_indexes
        for branch in repo.branches:
            if branch not in branch_indexes:
                branch_indexes.append(branch)

                # Menu events
                index = len(branch_indexes)-1
                wx.EVT_MENU(self, MENU_DELETE_BRANCH + index, self.OnDeleteBranch)
                wx.EVT_MENU(self, MENU_CHECKOUT_BRANCH + index, self.OnCheckout)

        self.repo = repo
        self.commitList.SetRepo(repo)

        difftext = self.repo.run_cmd(['show', 'HEAD^'])
        self.diffViewer.Clear()

    def OnCommitSelected(self, e):
        commit = self.commitList.CommitByRow(e.currentRow)

        # Show in diff viewer
        commit_diff = self.repo.run_cmd(['show', commit.sha1])
        self.diffViewer.SetDiffText(commit_diff, commit_mode=True)

    def OnCommitRightClick(self, e):
        self.contextCommit = self.commitList.CommitByRow(e.currentRow)
        self.SetupContextMenu(self.contextCommit)
        self.commitList.PopupMenu(self.contextMenu, e.coords)

    def OnCreateBranch(self, e):
        dialog = wx.TextEntryDialog(self, "Enter branch name:", "Create branch...")
        if dialog.ShowModal() == wx.ID_OK:
            branch_name = dialog.GetValue()
            self.GitCommand(['branch', branch_name, self.contextCommit.sha1])

    def OnDeleteBranch(self, e):
        branch = branch_indexes[e.GetId() % 1000]
        msg = wx.MessageDialog(
            self.mainWindow,
            "By deleting branch '%s' all commits that are not referenced by another branch will be lost.\n\nDo you really want to continue?" % branch,
            "Warning",
            wx.ICON_EXCLAMATION | wx.YES_NO | wx.YES_DEFAULT
        )
        if msg.ShowModal() == wx.ID_YES:
            self.GitCommand(['branch', '-d', branch])

    def OnCheckout(self, e):
        if e.GetId() == MENU_CHECKOUT_DETACHED:
            checkout_target = self.contextCommit.sha1
            confirmMsg = "Do you really want to checkout this commit as detached HEAD?"
        else:
            branch = branch_indexes[e.GetId() % 1000]
            checkout_target = branch
            confirmMsg = "Do you really want to checkout branch '%s'?" % branch

        msg = wx.MessageDialog(
            self.mainWindow,
            confirmMsg,
            "Confirmation",
            wx.ICON_EXCLAMATION | wx.YES_NO | wx.YES_DEFAULT
        )
        if msg.ShowModal() == wx.ID_YES:
            self.GitCommand(['checkout', checkout_target], True)

    def OnResetBranch(self, e):
        wizard = ResetWizard(self.mainWindow, -1, self.repo)
        if wizard.RunWizard():
            resetTypes = ['--soft', '--mixed', '--hard']
            resetType = resetTypes[wizard.resetType]
            self.GitCommand(['reset', resetType, self.contextCommit.sha1], True)

    def SetupContextMenu(self, commit):
        branches = self.repo.branches_by_sha1.get(commit.sha1, [])

        # Delete old items
        menuItems = self.contextMenu.GetMenuItems()
        for item in menuItems:
            self.contextMenu.Delete(item.GetId())

        # Create branch
        self.contextMenu.Append(MENU_CREATE_BRANCH, "Create branch here...")

        # Delete branch
        if branches:
            self.contextMenu.AppendSeparator()

            for branch in branches:
                menu_id = MENU_DELETE_BRANCH + branch_indexes.index(branch)
                self.contextMenu.Append(menu_id, "Delete branch '%s'" % branch)

        # Checkout
        self.contextMenu.AppendSeparator()
        if branches:
            menu_id = MENU_CHECKOUT_BRANCH + branch_indexes.index(branch)
            self.contextMenu.Append(menu_id, "Checkout branch '%s'" % branch)

        self.contextMenu.Append(MENU_CHECKOUT_DETACHED, "Checkout as detached HEAD")

        # Reset branch
        if self.repo.current_branch:
            self.contextMenu.AppendSeparator()
            self.contextMenu.Append(MENU_RESET_BRANCH, "Reset branch '%s' here" % self.repo.current_branch)

    def GitCommand(self, cmd, check_submodules=False, **opts):
        try:
            retval = self.repo.run_cmd(cmd, raise_error=True, **opts)
            self.mainWindow.ReloadRepo()

            # Check submodules
            if check_submodules and self.repo.submodules:
                for submodule in self.repo.submodules:
                    if submodule.main_ref != submodule.head:
                        wx.MessageBox(
                            "One or more submodule versions differ from the version " +
                            "that is referenced by the current HEAD. If this is not " +
                            "what you want, you need to checkout them to the proper version.",
                            'Warning',
                            style=wx.OK|wx.ICON_WARNING
                        )
                        break

            return retval
        except GitError, msg:
            wx.MessageBox(str(msg), 'Error', style=wx.OK|wx.ICON_ERROR)
            return False

class ResetWizard(Wizard):
    def __init__(self, parent, id, repo):
        Wizard.__init__(self, parent, id)
        self.repo = repo

        # Choose reset type page
        self.typePage = self.CreatePage(
            "Choose reset type",
            [BTN_CANCEL, BTN_CONTINUE]
        )

        font = wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        self.typePageCaption = wx.StaticText(self.typePage, -1, "Choose reset type")
        self.typePageCaption.SetFont(font)
        self.typePage.sizer.Add(self.typePageCaption, 0, wx.EXPAND | wx.ALL, 10)

        self.typeBtns = wx.RadioBox(self.typePage, -1, "",
            style=wx.RA_SPECIFY_ROWS,
            choices=[
                "Soft reset: keep working directory and index untouched",
                "Mixed reset: preserve working directory, reset index",
                "Hard reset: discard ALL changes"
            ]
        )

        self.typePage.sizer.Add(self.typeBtns, 1, wx.EXPAND | wx.ALL, 10)

        # Warning page
        self.warningPage = self.CreateWarningPage(
            "Warning: you may lose commits",

            ("You are about to reset the current branch (%s) to a different version. " +
            "All commits that are not referenced by another branch, tag or " +
            "remote branch will be lost.\n\n" +
            "Do you really want to continue?") % self.repo.current_branch,

            [BTN_CANCEL, BTN_FINISH]
        )

    def OnStart(self):
        self.SetPage(self.typePage)

    def OnButtonClicked(self, button):
        if button == BTN_CONTINUE:
            self.resetType = self.typeBtns.GetSelection()
            self.SetPage(self.warningPage)
        if button == BTN_CANCEL:
            self.EndWizard(0)
        if button == BTN_FINISH:
            self.EndWizard(1)
<commit_msg>fix missing checkout menu items in history browser<commit_after>import wx
from CommitList import CommitList, EVT_COMMITLIST_SELECT, EVT_COMMITLIST_RIGHTCLICK
from DiffViewer import DiffViewer
from Wizard import *
from git import GitError

# Menu item ids
MENU_CHECKOUT_DETACHED  = 10000
MENU_RESET_BRANCH       = 10001
MENU_CREATE_BRANCH      = 11000
MENU_DELETE_BRANCH      = 12000
MENU_CHECKOUT_BRANCH    = 13000

# This array is used to provide unique ids for menu items
# that refer to a branch
branch_indexes = []

class HistoryTab(wx.Panel):
    def __init__(self, mainWindow, parent, id):
        # Layout
        wx.Panel.__init__(self, parent, id)
        self.mainWindow = mainWindow
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)

        # Splitter
        self.splitter = wx.SplitterWindow(self, -1)
        self.sizer.Add(self.splitter, True, wx.EXPAND, wx.ALL)

        # History graph
        self.commitList = CommitList(self.splitter, -1)
        self.Bind(EVT_COMMITLIST_SELECT, self.OnCommitSelected, self.commitList)
        self.Bind(EVT_COMMITLIST_RIGHTCLICK, self.OnCommitRightClick, self.commitList)

        self.diffViewer = DiffViewer(self.splitter, -1)

        self.splitter.SetMinimumPaneSize(20)
        self.splitter.SplitHorizontally(self.commitList, self.diffViewer, 200)

        # Context menu
        self.contextMenu = wx.Menu()
        wx.EVT_MENU(self, MENU_CREATE_BRANCH, self.OnCreateBranch)
        wx.EVT_MENU(self, MENU_CHECKOUT_DETACHED, self.OnCheckout)
        wx.EVT_MENU(self, MENU_RESET_BRANCH, self.OnResetBranch)

    def SetRepo(self, repo):
        # Branch indexes
        global branch_indexes
        for branch in repo.branches:
            if branch not in branch_indexes:
                branch_indexes.append(branch)

                # Menu events
                index = len(branch_indexes)-1
                wx.EVT_MENU(self, MENU_DELETE_BRANCH + index, self.OnDeleteBranch)
                wx.EVT_MENU(self, MENU_CHECKOUT_BRANCH + index, self.OnCheckout)

        self.repo = repo
        self.commitList.SetRepo(repo)

        difftext = self.repo.run_cmd(['show', 'HEAD^'])
        self.diffViewer.Clear()

    def OnCommitSelected(self, e):
        commit = self.commitList.CommitByRow(e.currentRow)

        # Show in diff viewer
        commit_diff = self.repo.run_cmd(['show', commit.sha1])
        self.diffViewer.SetDiffText(commit_diff, commit_mode=True)

    def OnCommitRightClick(self, e):
        self.contextCommit = self.commitList.CommitByRow(e.currentRow)
        self.SetupContextMenu(self.contextCommit)
        self.commitList.PopupMenu(self.contextMenu, e.coords)

    def OnCreateBranch(self, e):
        dialog = wx.TextEntryDialog(self, "Enter branch name:", "Create branch...")
        if dialog.ShowModal() == wx.ID_OK:
            branch_name = dialog.GetValue()
            self.GitCommand(['branch', branch_name, self.contextCommit.sha1])

    def OnDeleteBranch(self, e):
        branch = branch_indexes[e.GetId() % 1000]
        msg = wx.MessageDialog(
            self.mainWindow,
            "By deleting branch '%s' all commits that are not referenced by another branch will be lost.\n\nDo you really want to continue?" % branch,
            "Warning",
            wx.ICON_EXCLAMATION | wx.YES_NO | wx.YES_DEFAULT
        )
        if msg.ShowModal() == wx.ID_YES:
            self.GitCommand(['branch', '-d', branch])

    def OnCheckout(self, e):
        if e.GetId() == MENU_CHECKOUT_DETACHED:
            checkout_target = self.contextCommit.sha1
            confirmMsg = "Do you really want to checkout this commit as detached HEAD?"
        else:
            branch = branch_indexes[e.GetId() % 1000]
            checkout_target = branch
            confirmMsg = "Do you really want to checkout branch '%s'?" % branch

        msg = wx.MessageDialog(
            self.mainWindow,
            confirmMsg,
            "Confirmation",
            wx.ICON_EXCLAMATION | wx.YES_NO | wx.YES_DEFAULT
        )
        if msg.ShowModal() == wx.ID_YES:
            self.GitCommand(['checkout', checkout_target], True)

    def OnResetBranch(self, e):
        wizard = ResetWizard(self.mainWindow, -1, self.repo)
        if wizard.RunWizard():
            resetTypes = ['--soft', '--mixed', '--hard']
            resetType = resetTypes[wizard.resetType]
            self.GitCommand(['reset', resetType, self.contextCommit.sha1], True)

    def SetupContextMenu(self, commit):
        branches = self.repo.branches_by_sha1.get(commit.sha1, [])

        # Delete old items
        menuItems = self.contextMenu.GetMenuItems()
        for item in menuItems:
            self.contextMenu.Delete(item.GetId())

        # Create branch
        self.contextMenu.Append(MENU_CREATE_BRANCH, "Create branch here...")

        # Delete branch
        if branches:
            self.contextMenu.AppendSeparator()

            for branch in branches:
                menu_id = MENU_DELETE_BRANCH + branch_indexes.index(branch)
                self.contextMenu.Append(menu_id, "Delete branch '%s'" % branch)

        # Checkout
        self.contextMenu.AppendSeparator()
        if branches:
            for branch in branches:
                menu_id = MENU_CHECKOUT_BRANCH + branch_indexes.index(branch)
                self.contextMenu.Append(menu_id, "Checkout branch '%s'" % branch)

        self.contextMenu.Append(MENU_CHECKOUT_DETACHED, "Checkout as detached HEAD")

        # Reset branch
        if self.repo.current_branch:
            self.contextMenu.AppendSeparator()
            self.contextMenu.Append(MENU_RESET_BRANCH, "Reset branch '%s' here" % self.repo.current_branch)

    def GitCommand(self, cmd, check_submodules=False, **opts):
        try:
            retval = self.repo.run_cmd(cmd, raise_error=True, **opts)
            self.mainWindow.ReloadRepo()

            # Check submodules
            if check_submodules and self.repo.submodules:
                for submodule in self.repo.submodules:
                    if submodule.main_ref != submodule.head:
                        wx.MessageBox(
                            "One or more submodule versions differ from the version " +
                            "that is referenced by the current HEAD. If this is not " +
                            "what you want, you need to checkout them to the proper version.",
                            'Warning',
                            style=wx.OK|wx.ICON_WARNING
                        )
                        break

            return retval
        except GitError, msg:
            wx.MessageBox(str(msg), 'Error', style=wx.OK|wx.ICON_ERROR)
            return False

class ResetWizard(Wizard):
    def __init__(self, parent, id, repo):
        Wizard.__init__(self, parent, id)
        self.repo = repo

        # Choose reset type page
        self.typePage = self.CreatePage(
            "Choose reset type",
            [BTN_CANCEL, BTN_CONTINUE]
        )

        font = wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        self.typePageCaption = wx.StaticText(self.typePage, -1, "Choose reset type")
        self.typePageCaption.SetFont(font)
        self.typePage.sizer.Add(self.typePageCaption, 0, wx.EXPAND | wx.ALL, 10)

        self.typeBtns = wx.RadioBox(self.typePage, -1, "",
            style=wx.RA_SPECIFY_ROWS,
            choices=[
                "Soft reset: keep working directory and index untouched",
                "Mixed reset: preserve working directory, reset index",
                "Hard reset: discard ALL changes"
            ]
        )

        self.typePage.sizer.Add(self.typeBtns, 1, wx.EXPAND | wx.ALL, 10)

        # Warning page
        self.warningPage = self.CreateWarningPage(
            "Warning: you may lose commits",

            ("You are about to reset the current branch (%s) to a different version. " +
            "All commits that are not referenced by another branch, tag or " +
            "remote branch will be lost.\n\n" +
            "Do you really want to continue?") % self.repo.current_branch,

            [BTN_CANCEL, BTN_FINISH]
        )

    def OnStart(self):
        self.SetPage(self.typePage)

    def OnButtonClicked(self, button):
        if button == BTN_CONTINUE:
            self.resetType = self.typeBtns.GetSelection()
            self.SetPage(self.warningPage)
        if button == BTN_CANCEL:
            self.EndWizard(0)
        if button == BTN_FINISH:
            self.EndWizard(1)
<|endoftext|>


<commit_before>"""
This is SONATA's service lifecycle management plugin
"""

import logging
import yaml
import time
from sonmanobase.plugin import ManoBasePlugin

logging.basicConfig(level=logging.INFO)
LOG = logging.getLogger("plugin:slm")
LOG.setLevel(logging.DEBUG)

#
# Configurations
#
# The topic to which service instantiation requests of the GK are published
GK_INSTANCE_CREATE_TOPIC = "service.instances.create"

# The topic to which service instance deploy replies of the Infrastructure Adaptor are published
INFRA_ADAPTOR_INSTANCE_DEPLOY_REPLY_TOPIC = "infrastructure.service.deploy"

class ServiceLifecycleManager(ManoBasePlugin):
    """
    This class implements the service lifecycle manager.

    see: https://github.com/sonata-nfv/son-mano-framework/issues/23
    """

    def __init__(self):
        """
        Initialize class and son-mano-base.plugin.BasePlugin class.
        This will automatically connect to the broker, contact the
        plugin manager, and self-register this plugin to the plugin
        manager.

        After the connection and registration procedures are done, the
        'on_lifecycle_start' method is called.
        :return:
        """
        # call super class (will automatically connect to broker and register the SLM to the plugin manger)
        super(self.__class__, self).__init__(version="0.1-dev",description="This is the SLM plugin")

    def __del__(self):
        """
        Destroy SLM instance. De-register. Disconnect.
        :return:
        """
        super(self.__class__, self).__del__()

    def declare_subscriptions(self):
        """
        Declare topics to subscribe to.
        """
        # We have to call our super class here
        super(self.__class__, self).declare_subscriptions()
        #
        # GK <-> SLM interface
        #
        # We want to subscribe to GK_INSTANCE_CREATE_TOPIC to react on GK messages
        self.manoconn.register_async_endpoint(
            self.on_gk_service_instance_create,  # function called when message received
            GK_INSTANCE_CREATE_TOPIC)  # topic to listen to
        #
        # SLM <-> infra. adaptor interface
        #
        # TODO implement reply topics for infrastructure adapter

    def on_lifecycle_start(self, ch, method, properties, message):
        """
        This event is called after the plugin has successfully registered itself
        to the plugin manager and received its lifecycle.start event from the
        plugin manager. The plugin is expected to do its work after this event.

        This is a default method each plugin should implement.

        :param ch: RabbitMQ channel
        :param method: RabbitMQ method
        :param properties: RabbitMQ properties
        :param message: RabbitMQ message content
        :return:
        """
        super(self.__class__, self).on_lifecycle_start(ch, method, properties, message)
        LOG.info("Lifecycle start event")
        # TODO does the SLM need to perform any actions after it has been started?

    def on_gk_service_instance_create(self, ch, method, properties, message):
        """
        This is our first SLM specific event method. It is called when the SLM
        receives a message from the GK published to GK_INSTANCE_CREATE_TOPIC.

        Here we should react and trigger the service instantiation.

        :param ch: RabbitMQ channel
        :param method: RabbitMQ method
        :param properties: RabbitMQ properties
        :param message: RabbitMQ message content
        :return:
        """

        LOG.info("GK service.instance.start event")

        """
        TODO: We need to check whether the received message is formatted as expected.
        TODO: We need to define what can go wrong during this method to report back to the gk
        """
        status = 'INSTANTIATING'
        error = None

        """
        The request data is in the message as a yaml file, constructed like:
        ---
        NSD:
                descriptor_version:
                ...
        VNFD1:
                descriptor_version:
                ...
        VNFD2:
                descriptor_version:
                ...
        ...
        """

        service_request_from_gk = yaml.load(message)

        """
        The slm reacts to this service_intance_create message with a call_async() to infrastructure.service.deploy
        The response message is a yaml file, constructed like:
        ---
        forwarding_graph:
                ...
        vnf_images:
                - vnf_id:
                  url:
                - vnf_id:
                  url
                - ...

        """

        #The message for the infrastructure adaptor is a yaml file, built from a dictionary
        service_request_for_infra_adaptor = {}

        #Adding the forwarding graph to the dictionary
        service_request_for_infra_adaptor['forwarding_graph'] = service_request_from_gk['NSD']['forwarding_graphs']

        #vnf_images contains a list of dictionaries
        service_request_for_infra_adaptor['vnf_images'] = []

        #constructing the dictionary for each VNF
        print('######')
        for key in service_request_from_gk.keys():
            if (key[:4] == 'VNFD'):
                #Determine which vnf_id is mapped to vnf_name, vnf_version, vnf_group.
                vnf_descriptor = service_request_from_gk[key]
                for network_function in service_request_from_gk['NSD']['network_functions']:
                    if (network_function['vnf_name'] == vnf_descriptor['vnf_name']) and (network_function['vnf_group'] == vnf_descriptor['vnf_group']) and (network_function['vnf_version'] == vnf_descriptor['vnf_version']):
                        vnf_dict = {'vnf_id': network_function['vnf_id'],'url' : vnf_descriptor['virtual_deployment_units'][0]['vm_image']}
                        service_request_for_infra_adaptor['vnf_images'].append(vnf_dict)

        #Sending the message towards the infrastructure adaptor, with callback pointer
        self.manoconn.call_async(self.on_infra_adaptor_service_deploy_reply, INFRA_ADAPTOR_INSTANCE_DEPLOY_REPLY_TOPIC, yaml.dump(service_request_for_infra_adaptor))

        #Reply for the GK
        return yaml.dump({'status'    : status,        #INSTANTIATING or ERROR
                          'error'     : error,         #NULL or a string describing the ERROR
                          'timestamp' : time.time()})  #time() returns the number of seconds since the epoch in UTC as a float

    def on_infra_adaptor_service_deploy_reply(self, ch, method, properties, message):

        """
        This method is called when the Infrastructure Adaptor replies to a service deploy request from the SLM.
        This response needs to be translated into a message for the GK.
        Based on the content of the reply message, the NSR has to be contacted.

        TODO: translate message before sending GK
        TODO: add NSR interaction
        """

        self.notify(GK_INSTANCE_CREATE_TOPIC, message)

        return

def main():
    """
    Entry point to start plugin.
    :return:
    """
    # reduce messaging log level to have a nicer output for this plugin
    logging.getLogger("son-mano-base:messaging").setLevel(logging.INFO)
    logging.getLogger("son-mano-base:plugin").setLevel(logging.INFO)
    # create our service lifecycle manager
    ServiceLifecycleManager()

if __name__ == '__main__':
    main()
<commit_msg>removing print statement.<commit_after>"""
This is SONATA's service lifecycle management plugin
"""

import logging
import yaml
import time
from sonmanobase.plugin import ManoBasePlugin

logging.basicConfig(level=logging.INFO)
LOG = logging.getLogger("plugin:slm")
LOG.setLevel(logging.DEBUG)

#
# Configurations
#
# The topic to which service instantiation requests of the GK are published
GK_INSTANCE_CREATE_TOPIC = "service.instances.create"

# The topic to which service instance deploy replies of the Infrastructure Adaptor are published
INFRA_ADAPTOR_INSTANCE_DEPLOY_REPLY_TOPIC = "infrastructure.service.deploy"

class ServiceLifecycleManager(ManoBasePlugin):
    """
    This class implements the service lifecycle manager.

    see: https://github.com/sonata-nfv/son-mano-framework/issues/23
    """

    def __init__(self):
        """
        Initialize class and son-mano-base.plugin.BasePlugin class.
        This will automatically connect to the broker, contact the
        plugin manager, and self-register this plugin to the plugin
        manager.

        After the connection and registration procedures are done, the
        'on_lifecycle_start' method is called.
        :return:
        """
        # call super class (will automatically connect to broker and register the SLM to the plugin manger)
        super(self.__class__, self).__init__(version="0.1-dev",description="This is the SLM plugin")

    def __del__(self):
        """
        Destroy SLM instance. De-register. Disconnect.
        :return:
        """
        super(self.__class__, self).__del__()

    def declare_subscriptions(self):
        """
        Declare topics to subscribe to.
        """
        # We have to call our super class here
        super(self.__class__, self).declare_subscriptions()
        #
        # GK <-> SLM interface
        #
        # We want to subscribe to GK_INSTANCE_CREATE_TOPIC to react on GK messages
        self.manoconn.register_async_endpoint(
            self.on_gk_service_instance_create,  # function called when message received
            GK_INSTANCE_CREATE_TOPIC)  # topic to listen to
        #
        # SLM <-> infra. adaptor interface
        #
        # TODO implement reply topics for infrastructure adapter

    def on_lifecycle_start(self, ch, method, properties, message):
        """
        This event is called after the plugin has successfully registered itself
        to the plugin manager and received its lifecycle.start event from the
        plugin manager. The plugin is expected to do its work after this event.

        This is a default method each plugin should implement.

        :param ch: RabbitMQ channel
        :param method: RabbitMQ method
        :param properties: RabbitMQ properties
        :param message: RabbitMQ message content
        :return:
        """
        super(self.__class__, self).on_lifecycle_start(ch, method, properties, message)
        LOG.info("Lifecycle start event")
        # TODO does the SLM need to perform any actions after it has been started?

    def on_gk_service_instance_create(self, ch, method, properties, message):
        """
        This is our first SLM specific event method. It is called when the SLM
        receives a message from the GK published to GK_INSTANCE_CREATE_TOPIC.

        Here we should react and trigger the service instantiation.

        :param ch: RabbitMQ channel
        :param method: RabbitMQ method
        :param properties: RabbitMQ properties
        :param message: RabbitMQ message content
        :return:
        """

        LOG.info("GK service.instance.start event")

        """
        TODO: We need to check whether the received message is formatted as expected.
        TODO: We need to define what can go wrong during this method to report back to the gk
        """
        status = 'INSTANTIATING'
        error = None

        """
        The request data is in the message as a yaml file, constructed like:
        ---
        NSD:
                descriptor_version:
                ...
        VNFD1:
                descriptor_version:
                ...
        VNFD2:
                descriptor_version:
                ...
        ...
        """

        service_request_from_gk = yaml.load(message)

        """
        The slm reacts to this service_intance_create message with a call_async() to infrastructure.service.deploy
        The response message is a yaml file, constructed like:
        ---
        forwarding_graph:
                ...
        vnf_images:
                - vnf_id:
                  url:
                - vnf_id:
                  url
                - ...

        """

        #The message for the infrastructure adaptor is a yaml file, built from a dictionary
        service_request_for_infra_adaptor = {}

        #Adding the forwarding graph to the dictionary
        service_request_for_infra_adaptor['forwarding_graph'] = service_request_from_gk['NSD']['forwarding_graphs']

        #vnf_images contains a list of dictionaries
        service_request_for_infra_adaptor['vnf_images'] = []

        #constructing the dictionary for each VNF
        for key in service_request_from_gk.keys():
            if (key[:4] == 'VNFD'):
                #Determine which vnf_id is mapped to vnf_name, vnf_version, vnf_group.
                vnf_descriptor = service_request_from_gk[key]
                for network_function in service_request_from_gk['NSD']['network_functions']:
                    if (network_function['vnf_name'] == vnf_descriptor['vnf_name']) and (network_function['vnf_group'] == vnf_descriptor['vnf_group']) and (network_function['vnf_version'] == vnf_descriptor['vnf_version']):
                        vnf_dict = {'vnf_id': network_function['vnf_id'],'url' : vnf_descriptor['virtual_deployment_units'][0]['vm_image']}
                        service_request_for_infra_adaptor['vnf_images'].append(vnf_dict)

        #Sending the message towards the infrastructure adaptor, with callback pointer
        self.manoconn.call_async(self.on_infra_adaptor_service_deploy_reply, INFRA_ADAPTOR_INSTANCE_DEPLOY_REPLY_TOPIC, yaml.dump(service_request_for_infra_adaptor))

        #Reply for the GK
        return yaml.dump({'status'    : status,        #INSTANTIATING or ERROR
                          'error'     : error,         #NULL or a string describing the ERROR
                          'timestamp' : time.time()})  #time() returns the number of seconds since the epoch in UTC as a float

    def on_infra_adaptor_service_deploy_reply(self, ch, method, properties, message):

        """
        This method is called when the Infrastructure Adaptor replies to a service deploy request from the SLM.
        This response needs to be translated into a message for the GK.
        Based on the content of the reply message, the NSR has to be contacted.

        TODO: translate message before sending GK
        TODO: add NSR interaction
        """

        self.notify(GK_INSTANCE_CREATE_TOPIC, message)

        return

def main():
    """
    Entry point to start plugin.
    :return:
    """
    # reduce messaging log level to have a nicer output for this plugin
    logging.getLogger("son-mano-base:messaging").setLevel(logging.INFO)
    logging.getLogger("son-mano-base:plugin").setLevel(logging.INFO)
    # create our service lifecycle manager
    ServiceLifecycleManager()

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


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2015 Comunitea Servicios Tecnológicos
#    $Carlos Lombardía Rodríguez <carlos@comunitea.com>$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, fields, api

class stock_picking(models.Model):
    _inherit = "stock.picking"

    internal_notes = fields.Text("Internal Notes", copy=False)
    odoo_management = fields.Boolean("Odoo management", readonly=True,
                                     copy=False)
    not_sync = fields.Boolean("Not sync", help="This picking not will be "
                                               "synced with Vstock",
                              copy=True)

    def action_assign(self, cr, uid, ids, context=None):
        res = super(stock_picking, self).action_assign(cr, uid, ids,
                                                       context=context)
        for obj in self.browse(cr, uid, ids):
            if obj.claim_id and obj.picking_type_code == "incoming":
                obj.force_assign()

        return res

    @api.model
    def do_transfer(self):
        for picking in self:
            if picking.claim_id:
                for move in picking.move_lines:
                    if move.claim_line_id:
                        if picking.picking_type_code == 'incoming':
                            move.claim_line_id.substate_id = self.env.ref(
                                'crm_claim_rma_custom.substate_received')
                        elif picking.picking_type_code == 'outgoing':
                            if move.claim_line_id.equivalent_product_id:
                                move.claim_line_id.substate_id = self.env.ref(
                                    'crm_claim_rma_custom.substate_replaced')
                            elif not move.claim_line_id.repair_id:
                                move.claim_line_id.substate_id = self.env.ref(
                                    'crm_claim_rma_custom.substate_checked')
        return super(stock_picking, self).do_transfer()

class StockLocation(models.Model):

    _inherit = "stock.location"

    odoo_management = fields.Boolean('Management in Odoo',
                                     help="The outputs of this location are "
                                          "managed in Odoo, Vstock only will "
                                          "print shipping labels")
    not_sync = fields.Boolean("Not sync",
                              help="The incomimg pickings to this location "
                                   "not will be synced with vstock")
<commit_msg>[FIX]crm_claim_rma_custom: fix not_sync.<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2015 Comunitea Servicios Tecnológicos
#    $Carlos Lombardía Rodríguez <carlos@comunitea.com>$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, fields, api

class stock_picking(models.Model):
    _inherit = "stock.picking"

    internal_notes = fields.Text("Internal Notes", copy=False)
    odoo_management = fields.Boolean("Odoo management", readonly=True,
                                     copy=False)
    not_sync = fields.Boolean("Not sync", help="This picking not will be "
                                               "synced with Vstock",
                              copy=True)

    @api.multi
    def copy(self, default=None):
        default = default and default or {}
        if self.env.context.get('picking_type', '') == 'picking_input':
            default['not_sync'] = False
        return super(stock_picking, self).copy(default)

    def action_assign(self, cr, uid, ids, context=None):
        res = super(stock_picking, self).action_assign(cr, uid, ids,
                                                       context=context)
        for obj in self.browse(cr, uid, ids):
            if obj.claim_id and obj.picking_type_code == "incoming":
                obj.force_assign()

        return res

    @api.model
    def do_transfer(self):
        for picking in self:
            if picking.claim_id:
                for move in picking.move_lines:
                    if move.claim_line_id:
                        if picking.picking_type_code == 'incoming':
                            move.claim_line_id.substate_id = self.env.ref(
                                'crm_claim_rma_custom.substate_received')
                        elif picking.picking_type_code == 'outgoing':
                            if move.claim_line_id.equivalent_product_id:
                                move.claim_line_id.substate_id = self.env.ref(
                                    'crm_claim_rma_custom.substate_replaced')
                            elif not move.claim_line_id.repair_id:
                                move.claim_line_id.substate_id = self.env.ref(
                                    'crm_claim_rma_custom.substate_checked')
        return super(stock_picking, self).do_transfer()

class StockLocation(models.Model):

    _inherit = "stock.location"

    odoo_management = fields.Boolean('Management in Odoo',
                                     help="The outputs of this location are "
                                          "managed in Odoo, Vstock only will "
                                          "print shipping labels")
    not_sync = fields.Boolean("Not sync",
                              help="The incomimg pickings to this location "
                                   "not will be synced with vstock")
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""Bootstrap virutalenv installation

If you want to use virutalenv in your bootstap script, just include this
file in the same directory with it, and add this to the top::

    from ve_setup import use_virtualenv
    use_virtualenv()

If you want to require a specific version of virtualenv, set a download
mirror, or use an alternate installation directory, you can do so by supplying
the appropriate options to ``use_virtualenv()``.
"""

import os
import shutil
import subprocess
import sys
import tempfile
import urllib

# Defaults
VIRTUALENV_VERSION = '1.5.1'
VIRTUALENV_ARGS = ['python']

#
# Working around error with PYTHONHOME
#
if 'PYTHONHOME' in os.environ:
    del os.environ['PYTHONHOME']
    print "WARNING: ignoring the value of the PYTHONHOME environment " \
          " variable! This value can corrupt the virtual python installation."

def use_virtualenv(argv, version=VIRTUALENV_VERSION, activate=True,
        requirements=None):
    """Install and use virtualenv environment."""

    virtualenv = VirtualEnv(argv, version=version)
    if not virtualenv.is_installed:
        virtualenv.install()
        if requirements:
            pip_exe = os.path.join(virtualenv.scripts_dir, "pip")
            subprocess.Popen([pip_exe, "install", "-r", requirements]).communicate()[0]
    if activate:
        virtualenv.activate()
    return virtualenv

def log(message):
    """Log message"""

    sys.stderr.write(": %s\n" % message)

class VirtualEnv(object):
    """Virtual environment"""

    def __init__(self, argv, version=None):
        self.python_name = os.path.basename(sys.executable)
        self.version = version or VIRTUALENV_VERSION
        self.path = os.path.abspath(argv[-1])
        self.argv = argv

    @property
    def scripts_dir(self):
        """Return path where scripts directory is located."""

        return os.path.join(self.path, 'Scripts' if sys.platform == 'win32'
                else 'bin')

    @property
    def is_installed(self):
        """Check this environment is installed."""

        return os.path.isfile(os.path.join(self.scripts_dir, self.python_name))

    @property
    def is_activated(self):
        """Check this environment is activated."""

        return 'VIRTUAL_ENV' in os.environ and \
                os.environ['VIRTUAL_ENV'] == self.path

    def install(self):
        """Install this environment."""

        tmpdir = tempfile.mkdtemp()
        virtualenv_requirement = 'virtualenv==%s' % self.version
        try:
            log("using virtualenv version %s" % self.version)
            installer = EZSetupInstaller(tmpdir)
            installer.install(virtualenv_requirement)
            virtualenv_py = os.path.join(tmpdir, 'virtualenv', 'virtualenv.py')
            virtualenv_cmd = [sys.executable, virtualenv_py] + self.argv
            log("execute %s" % " ".join(virtualenv_cmd))
            subprocess.call(virtualenv_cmd)
        finally:
            shutil.rmtree(tmpdir)

    def activate(self):
        """Activate this environment."""

        if self.is_activated:
            return # this environment is activated
        activate_this = os.path.join(self.scripts_dir, 'activate_this.py')
        execfile(activate_this, dict(__file__=activate_this))
        os.environ['VIRTUAL_ENV'] = self.path
        if not self.scripts_dir in os.getenv('PATH', ''):
            os.environ['PATH'] = os.pathsep.join(
                    [self.scripts_dir, os.getenv('PATH', '')])

class EZSetupInstaller(object):
    """Installer"""

    EZ_SETUP_PY = 'ez_setup.py'
    EZ_SETUP_URL = 'http://peak.telecommunity.com/dist/ez_setup.py'

    def __init__(self, install_dir, ez_setup_py=None):
        self.install_dir = install_dir
        self.ez_setup_py = ez_setup_py or (
                os.path.join(os.getcwd(), self.EZ_SETUP_PY) if os.path.isfile(
                    os.path.join(os.getcwd(), self.EZ_SETUP_PY)) else
                os.path.join(self.install_dir, self.EZ_SETUP_PY))
        self._fetch_ez_setup_py()

    def install(self, requirement):
        """Install given requirement."""

        env = os.environ.copy()
        env['PYTHONPATH'] = self.install_dir
        ez_setup_cmd = [sys.executable, self.ez_setup_py,
                '-q', '--editable', '--build-directory',  self.install_dir,
                requirement]
        log("download %s with %s" % (requirement, " ".join(ez_setup_cmd)))
        subprocess.call(ez_setup_cmd, env=env)

    def _fetch_ez_setup_py(self):
        """Fetch ez_setup.py."""

        if not os.path.isfile(self.ez_setup_py):
            ez_setup_url = self.EZ_SETUP_URL
            log("download %s to %s" % (ez_setup_url, self.ez_setup_py))
            urllib.urlretrieve(ez_setup_url, self.ez_setup_py)

if __name__ == '__main__':
    import traceback

    def main():
        """Main function."""

        version = VIRTUALENV_VERSION
        args = sys.argv[1:] if len(sys.argv) > 1 else VIRTUALENV_ARGS
        use_virtualenv(args, version)

    try:
        main()
        sys.exit(0)
    except Exception, e: # Catch all exceptions. pylint: disable=W0703
        sys.stderr.write(traceback.format_exc() if __debug__ else str(e))
        sys.exit(1)

<commit_msg>make ve_setup.py executable<commit_after>#!/usr/bin/env python
"""Bootstrap virutalenv installation

If you want to use virutalenv in your bootstap script, just include this
file in the same directory with it, and add this to the top::

    from ve_setup import use_virtualenv
    use_virtualenv()

If you want to require a specific version of virtualenv, set a download
mirror, or use an alternate installation directory, you can do so by supplying
the appropriate options to ``use_virtualenv()``.
"""

import os
import shutil
import subprocess
import sys
import tempfile
import urllib

# Defaults
VIRTUALENV_VERSION = '1.5.1'
VIRTUALENV_ARGS = ['python']

#
# Working around error with PYTHONHOME
#
if 'PYTHONHOME' in os.environ:
    del os.environ['PYTHONHOME']
    print "WARNING: ignoring the value of the PYTHONHOME environment " \
          " variable! This value can corrupt the virtual python installation."

def use_virtualenv(argv, version=VIRTUALENV_VERSION, activate=True,
        requirements=None):
    """Install and use virtualenv environment."""

    virtualenv = VirtualEnv(argv, version=version)
    if not virtualenv.is_installed:
        virtualenv.install()
        if requirements:
            pip_exe = os.path.join(virtualenv.scripts_dir, "pip")
            subprocess.Popen([pip_exe, "install", "-r", requirements]).communicate()[0]
    if activate:
        virtualenv.activate()
    return virtualenv

def log(message):
    """Log message"""

    sys.stderr.write(": %s\n" % message)

class VirtualEnv(object):
    """Virtual environment"""

    def __init__(self, argv, version=None):
        self.python_name = os.path.basename(sys.executable)
        self.version = version or VIRTUALENV_VERSION
        self.path = os.path.abspath(argv[-1])
        self.argv = argv

    @property
    def scripts_dir(self):
        """Return path where scripts directory is located."""

        return os.path.join(self.path, 'Scripts' if sys.platform == 'win32'
                else 'bin')

    @property
    def is_installed(self):
        """Check this environment is installed."""

        return os.path.isfile(os.path.join(self.scripts_dir, self.python_name))

    @property
    def is_activated(self):
        """Check this environment is activated."""

        return 'VIRTUAL_ENV' in os.environ and \
                os.environ['VIRTUAL_ENV'] == self.path

    def install(self):
        """Install this environment."""

        tmpdir = tempfile.mkdtemp()
        virtualenv_requirement = 'virtualenv==%s' % self.version
        try:
            log("using virtualenv version %s" % self.version)
            installer = EZSetupInstaller(tmpdir)
            installer.install(virtualenv_requirement)
            virtualenv_py = os.path.join(tmpdir, 'virtualenv', 'virtualenv.py')
            virtualenv_cmd = [sys.executable, virtualenv_py] + self.argv
            log("execute %s" % " ".join(virtualenv_cmd))
            subprocess.call(virtualenv_cmd)
        finally:
            shutil.rmtree(tmpdir)

    def activate(self):
        """Activate this environment."""

        if self.is_activated:
            return # this environment is activated
        activate_this = os.path.join(self.scripts_dir, 'activate_this.py')
        execfile(activate_this, dict(__file__=activate_this))
        os.environ['VIRTUAL_ENV'] = self.path
        if not self.scripts_dir in os.getenv('PATH', ''):
            os.environ['PATH'] = os.pathsep.join(
                    [self.scripts_dir, os.getenv('PATH', '')])

class EZSetupInstaller(object):
    """Installer"""

    EZ_SETUP_PY = 'ez_setup.py'
    EZ_SETUP_URL = 'http://peak.telecommunity.com/dist/ez_setup.py'

    def __init__(self, install_dir, ez_setup_py=None):
        self.install_dir = install_dir
        self.ez_setup_py = ez_setup_py or (
                os.path.join(os.getcwd(), self.EZ_SETUP_PY) if os.path.isfile(
                    os.path.join(os.getcwd(), self.EZ_SETUP_PY)) else
                os.path.join(self.install_dir, self.EZ_SETUP_PY))
        self._fetch_ez_setup_py()

    def install(self, requirement):
        """Install given requirement."""

        env = os.environ.copy()
        env['PYTHONPATH'] = self.install_dir
        ez_setup_cmd = [sys.executable, self.ez_setup_py,
                '-q', '--editable', '--build-directory',  self.install_dir,
                requirement]
        log("download %s with %s" % (requirement, " ".join(ez_setup_cmd)))
        subprocess.call(ez_setup_cmd, env=env)

    def _fetch_ez_setup_py(self):
        """Fetch ez_setup.py."""

        if not os.path.isfile(self.ez_setup_py):
            ez_setup_url = self.EZ_SETUP_URL
            log("download %s to %s" % (ez_setup_url, self.ez_setup_py))
            urllib.urlretrieve(ez_setup_url, self.ez_setup_py)

if __name__ == '__main__':
    import traceback

    def main():
        """Main function."""

        version = VIRTUALENV_VERSION
        args = sys.argv[1:] if len(sys.argv) > 1 else VIRTUALENV_ARGS
        use_virtualenv(args, version)

    try:
        main()
        sys.exit(0)
    except Exception, e: # Catch all exceptions. pylint: disable=W0703
        sys.stderr.write(traceback.format_exc() if __debug__ else str(e))
        sys.exit(1)

<|endoftext|>


<commit_before>@command("laws")
def echo(nick, user, channel, message):
    argv = message.split(maxsplit=1)

    if len(argv) == 0:
        f = open('files/laws.txt', 'r')
        i = 1
        for line in f:
            say(channel, '{}. {}'.format(i, line))
            i = i + 1
        f.close()

    elif argv[0] == 'reset':
        f = open('files/laws.txt', 'r+')
        f.truncate()
        f.write("A robot may not injure a human being or, through inaction, allow a human being to come to harm.\nA robot must obey the orders given it by human beings, except where such orders would conflict with the First Law.\nA robot must protect its own existence as long as such protection does not conflict with the First or Second Law.\n")
        say(channel, '{}: Laws updated.'.format(nick))
        f.close()

    elif argv[0] == 'add' and len(argv) == 2:
        f = open('files/laws.txt', 'a')
        f.write("{}\n".format(argv[1]))
        say(channel, '{}: Laws updated.'.format(nick))
        f.close()
<commit_msg>Handle file exceptions. Use enumerate. Err msg. Close files sooner.<commit_after>@command("laws")
def echo(nick, user, channel, message):
    argv = message.split(maxsplit=1)

    if len(argv) == 0:
        try:
            f = open('files/laws.txt', 'r')
            for i,line in enumerate(f):
                say(channel, '{}. {}'.format(i+1, line))
            f.close()
        except IOError:
            say(channel,"Error: Coulh not open laws.txt!")

    elif argv[0] == 'reset':
        f = open('files/laws.txt', 'w')
        f.write("A robot may not injure a human being or, through inaction, allow a human being to come to harm.\nA robot must obey the orders given it by human beings, except where such orders would conflict with the First Law.\nA robot must protect its own existence as long as such protection does not conflict with the First or Second Law.\n")
        f.close()
        say(channel, '{}: Laws updated.'.format(nick))

    elif argv[0] == 'add' and len(argv) == 2:
        f = open('files/laws.txt', 'a')
        f.write("{}\n".format(argv[1]))
        f.close()
        say(channel, '{}: Laws updated.'.format(nick))
<|endoftext|>


<commit_before>##########################################################################
#
#  Copyright (c) 2013-2015, Image Engine Design Inc. All rights reserved.
#  Copyright (c) 2015, Nvizible Ltd. 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 John Haddon nor the names of
#        any other contributors to this software 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 OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import unittest
import os

import IECore

import Gaffer
import GafferTest
import GafferImage
import GafferImageTest

class CropTest( GafferImageTest.ImageTestCase ) :

	imageFileUndersizeDataWindow = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/blueWithDataWindow.100x100.exr" )
	imageFileOversizeDataWindow = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/checkerWithNegWindows.200x150.exr" )

	def testDefaultState( self ) :

		crop = GafferImage.Crop()

		self.assertEqual( crop["areaSource"].getValue(), GafferImage.Crop.AreaSource.Custom )
		self.assertTrue( crop["area"].getValue().isEmpty() )
		self.assertEqual( crop["affectDataWindow"].getValue(), True )
		self.assertEqual( crop["affectDisplayWindow"].getValue(), True )

	def testPassThrough( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Custom )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( True )
		crop["resetOrigin"].setValue( False )

		self.assertEqual(i['out'].channelDataHash( "R", IECore.V2i( 0 ) ), crop['out'].channelDataHash( "R", IECore.V2i( 0 ) ) )
		self.assertEqual(i['out'].channelDataHash( "G", IECore.V2i( 0 ) ), crop['out'].channelDataHash( "G", IECore.V2i( 0 ) ) )
		self.assertEqual(i['out'].channelDataHash( "B", IECore.V2i( 0 ) ), crop['out'].channelDataHash( "B", IECore.V2i( 0 ) ) )

		self.assertEqual( i["out"]["metadata"].hash(), crop["out"]["metadata"].hash() )
		self.assertEqual( i["out"]["channelNames"].hash(), crop["out"]["channelNames"].hash() )
		self.assertNotEqual( i["out"]["format"].hash(), crop["out"]["format"].hash() )
		self.assertNotEqual( i["out"]["dataWindow"].hash(), crop["out"]["dataWindow"].hash() )

		self.assertEqual( i["out"]["metadata"].getValue(), crop["out"]["metadata"].getValue() )
		self.assertEqual( i["out"]["channelNames"].getValue(), crop["out"]["channelNames"].getValue() )
		self.assertNotEqual( i["out"]["format"].getValue(), crop["out"]["format"].getValue() )
		self.assertNotEqual( i["out"]["dataWindow"].getValue(), crop["out"]["dataWindow"].getValue() )

	def testEnableBehaviour( self ) :

		crop = GafferImage.Crop()

		self.assertTrue( crop.enabledPlug().isSame( crop["enabled"] ) )
		self.assertTrue( crop.correspondingInput( crop["out"] ).isSame( crop["in"] ) )
		self.assertEqual( crop.correspondingInput( crop["in"] ), None )
		self.assertEqual( crop.correspondingInput( crop["enabled"] ), None )

	def testAffectDataWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Custom )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		self.assertEqual( i["out"]["format"].getValue(), crop["out"]["format"].getValue() )

	def testAffectDisplayWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Custom )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( False )
		crop["affectDisplayWindow"].setValue( True )
		crop["resetOrigin"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		self.assertEqual( i["out"]["dataWindow"].getValue(), crop["out"]["dataWindow"].getValue() )

		crop["resetOrigin"].setValue( True )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 10 ) ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( -10 ), IECore.V2i( 40 ) ) )

	def testIntersectDataWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Custom )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 30 ), IECore.V2i( 50 ) ) )

	def testDataWindowToDisplayWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.DataWindow )
		crop["affectDataWindow"].setValue( False )
		crop["affectDisplayWindow"].setValue( True )
		crop["resetOrigin"].setValue( False )

		self.assertEqual( i["out"]["dataWindow"].getValue(), crop["out"]["format"].getValue().getDisplayWindow() )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), i["out"]["dataWindow"].getValue() )

		crop["resetOrigin"].setValue( True )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 50 ) ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 50 ) ) )

	def testDisplayWindowToDataWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileOversizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.DisplayWindow )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( i["out"]["format"].getValue().getDisplayWindow(), crop["out"]["dataWindow"].getValue() )

	def testAffects( self ) :

		c = GafferImage.Crop()

		self.assertEqual(
			set( c.affects( c["affectDisplayWindow"] ) ),
			{ c["out"]["format"], c["out"]["dataWindow"], c["__offset"]["x"], c["__offset"]["y"] }
		)

		self.assertEqual(
			set( c.affects( c["affectDataWindow"] ) ),
			{ c["out"]["dataWindow"] }
		)

		self.assertTrue( c["out"]["dataWindow"] in set( c.affects( c["in"]["dataWindow"] ) ) )
		self.assertTrue( c["out"]["format"] in set( c.affects( c["in"]["format"] ) ) )

	def testResetOrigin( self ) :

		constant = GafferImage.Constant()
		constant["format"].setValue( GafferImage.Format( 100, 200, 1 ) )

		crop = GafferImage.Crop()
		crop["in"].setInput( constant["out"] )
		self.assertEqual( crop["affectDisplayWindow"].getValue(), True )
		self.assertEqual( crop["affectDataWindow"].getValue(), True )
		self.assertEqual( crop["resetOrigin"].getValue(), True )

		area = IECore.Box2i( IECore.V2i( 50 ), IECore.V2i( 100, 190 ) )
		crop["area"].setValue( area )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), area.size() ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 0 ), area.size() ) )

		crop["resetOrigin"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), area )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), area )

		# If we're not affecting the display window, then the reset origin flag
		# should be ignored.
		crop["resetOrigin"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue(), crop["in"]["format"].getValue() )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), area )

		# But if we are affecting the display window, and we are resetting the origin,
		# the data window should be offset even if affectDataWindow is off.

		crop["affectDisplayWindow"].setValue( True )
		crop["affectDataWindow"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), area.size() ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( -50 ), IECore.V2i( 50, 150 ) ) )

if __name__ == "__main__":
	unittest.main()
<commit_msg>CropTest : Add test for Format Area<commit_after>##########################################################################
#
#  Copyright (c) 2013-2015, Image Engine Design Inc. All rights reserved.
#  Copyright (c) 2015, Nvizible Ltd. 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 John Haddon nor the names of
#        any other contributors to this software 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 OWNER OR
#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##########################################################################

import unittest
import os

import IECore

import Gaffer
import GafferTest
import GafferImage
import GafferImageTest

class CropTest( GafferImageTest.ImageTestCase ) :

	imageFileUndersizeDataWindow = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/blueWithDataWindow.100x100.exr" )
	imageFileOversizeDataWindow = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/checkerWithNegWindows.200x150.exr" )

	def testDefaultState( self ) :

		crop = GafferImage.Crop()

		self.assertEqual( crop["areaSource"].getValue(), GafferImage.Crop.AreaSource.Area )
		self.assertTrue( crop["area"].getValue().isEmpty() )
		self.assertEqual( crop["affectDataWindow"].getValue(), True )
		self.assertEqual( crop["affectDisplayWindow"].getValue(), True )

	def testPassThrough( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Area )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( True )
		crop["resetOrigin"].setValue( False )

		self.assertEqual(i['out'].channelDataHash( "R", IECore.V2i( 0 ) ), crop['out'].channelDataHash( "R", IECore.V2i( 0 ) ) )
		self.assertEqual(i['out'].channelDataHash( "G", IECore.V2i( 0 ) ), crop['out'].channelDataHash( "G", IECore.V2i( 0 ) ) )
		self.assertEqual(i['out'].channelDataHash( "B", IECore.V2i( 0 ) ), crop['out'].channelDataHash( "B", IECore.V2i( 0 ) ) )

		self.assertEqual( i["out"]["metadata"].hash(), crop["out"]["metadata"].hash() )
		self.assertEqual( i["out"]["channelNames"].hash(), crop["out"]["channelNames"].hash() )
		self.assertNotEqual( i["out"]["format"].hash(), crop["out"]["format"].hash() )
		self.assertNotEqual( i["out"]["dataWindow"].hash(), crop["out"]["dataWindow"].hash() )

		self.assertEqual( i["out"]["metadata"].getValue(), crop["out"]["metadata"].getValue() )
		self.assertEqual( i["out"]["channelNames"].getValue(), crop["out"]["channelNames"].getValue() )
		self.assertNotEqual( i["out"]["format"].getValue(), crop["out"]["format"].getValue() )
		self.assertNotEqual( i["out"]["dataWindow"].getValue(), crop["out"]["dataWindow"].getValue() )

	def testEnableBehaviour( self ) :

		crop = GafferImage.Crop()

		self.assertTrue( crop.enabledPlug().isSame( crop["enabled"] ) )
		self.assertTrue( crop.correspondingInput( crop["out"] ).isSame( crop["in"] ) )
		self.assertEqual( crop.correspondingInput( crop["in"] ), None )
		self.assertEqual( crop.correspondingInput( crop["enabled"] ), None )

	def testAreaFormat( self ) :

		constant = GafferImage.Constant()
		constant['format'].setValue( GafferImage.Format( 1024, 576 ) )

		crop1 = GafferImage.Crop()
		crop1['in'].setInput( constant['out'] )
		crop1['areaSource'].setValue( GafferImage.Crop.AreaSource.Format )
		crop1['format'].setValue( GafferImage.Format( 2048, 1152 ) )

		crop2 = GafferImage.Crop()
		crop2['in'].setInput( constant['out'] )
		crop2['areaSource'].setValue( GafferImage.Crop.AreaSource.Area )
		crop2['area'].setValue( IECore.Box2i( IECore.V2i( 0, 0 ), IECore.V2i( 2048, 1152 ) ) )

		self.assertEqual( crop1['out']['dataWindow'].getValue(), crop2['out']['dataWindow'].getValue() )

		crop1['formatCenter'].setValue( True )
		crop2['area'].setValue( IECore.Box2i( IECore.V2i( -512, -288 ), IECore.V2i( 1536, 864 ) ) )
		crop2['resetOrigin'].setValue( True )

		self.assertEqual( crop1['out']['dataWindow'].getValue(), crop2['out']['dataWindow'].getValue() )

	def testAffectDataWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Area )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		self.assertEqual( i["out"]["format"].getValue(), crop["out"]["format"].getValue() )

	def testAffectDisplayWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Area )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( False )
		crop["affectDisplayWindow"].setValue( True )
		crop["resetOrigin"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 50 ) ) )
		self.assertEqual( i["out"]["dataWindow"].getValue(), crop["out"]["dataWindow"].getValue() )

		crop["resetOrigin"].setValue( True )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 10 ) ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( -10 ), IECore.V2i( 40 ) ) )

	def testIntersectDataWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Area )
		crop["area"].setValue( IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 50 ) ) )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 30 ), IECore.V2i( 50 ) ) )

	def testDataWindowToDisplayWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileUndersizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.DataWindow )
		crop["affectDataWindow"].setValue( False )
		crop["affectDisplayWindow"].setValue( True )
		crop["resetOrigin"].setValue( False )

		self.assertEqual( i["out"]["dataWindow"].getValue(), crop["out"]["format"].getValue().getDisplayWindow() )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), i["out"]["dataWindow"].getValue() )

		crop["resetOrigin"].setValue( True )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 50 ) ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 50 ) ) )

	def testDisplayWindowToDataWindow( self ) :

		i = GafferImage.ImageReader()
		i["fileName"].setValue( self.imageFileOversizeDataWindow )

		crop = GafferImage.Crop()
		crop["in"].setInput(i["out"])
		crop["areaSource"].setValue( GafferImage.Crop.AreaSource.DisplayWindow )
		crop["affectDataWindow"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( i["out"]["format"].getValue().getDisplayWindow(), crop["out"]["dataWindow"].getValue() )

	def testAffects( self ) :

		c = GafferImage.Crop()

		self.assertEqual(
			set( c.affects( c["affectDisplayWindow"] ) ),
			{ c["out"]["format"], c["out"]["dataWindow"], c["__offset"]["x"], c["__offset"]["y"] }
		)

		self.assertEqual(
			set( c.affects( c["affectDataWindow"] ) ),
			{ c["out"]["dataWindow"] }
		)

		self.assertTrue( c["out"]["dataWindow"] in set( c.affects( c["in"]["dataWindow"] ) ) )
		self.assertTrue( c["out"]["format"] in set( c.affects( c["in"]["format"] ) ) )

	def testResetOrigin( self ) :

		constant = GafferImage.Constant()
		constant["format"].setValue( GafferImage.Format( 100, 200, 1 ) )

		crop = GafferImage.Crop()
		crop["in"].setInput( constant["out"] )
		self.assertEqual( crop["affectDisplayWindow"].getValue(), True )
		self.assertEqual( crop["affectDataWindow"].getValue(), True )
		self.assertEqual( crop["resetOrigin"].getValue(), True )

		area = IECore.Box2i( IECore.V2i( 50 ), IECore.V2i( 100, 190 ) )
		crop["area"].setValue( area )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), area.size() ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( 0 ), area.size() ) )

		crop["resetOrigin"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), area )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), area )

		# If we're not affecting the display window, then the reset origin flag
		# should be ignored.
		crop["resetOrigin"].setValue( True )
		crop["affectDisplayWindow"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue(), crop["in"]["format"].getValue() )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), area )

		# But if we are affecting the display window, and we are resetting the origin,
		# the data window should be offset even if affectDataWindow is off.

		crop["affectDisplayWindow"].setValue( True )
		crop["affectDataWindow"].setValue( False )

		self.assertEqual( crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i( IECore.V2i( 0 ), area.size() ) )
		self.assertEqual( crop["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( -50 ), IECore.V2i( 50, 150 ) ) )

if __name__ == "__main__":
	unittest.main()
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from traceback import print_exc
from os import _exit as os_exit
from os import statvfs
import logging
import dbus
logger = logging.getLogger(__name__)

VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1)

# Use this function to make sure the code quits on an unexpected exception. Make sure to use it
# when using gobject.idle_add and also gobject.timeout_add.
# Without this, the code will just keep running, since gobject does not stop the mainloop on an
# exception.
# Example: gobject.idle_add(exit_on_error, myfunc, arg1, arg2)
def exit_on_error(func, *args, **kwargs):
	try:
		return func(*args, **kwargs)
	except:
		try:
			print 'exit_on_error: there was an exception. Printing stacktrace will be tryed and then exit'
			print_exc()
		except:
			pass

		# sys.exit() is not used, since that throws an exception, which does not lead to a program
		# halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230.
		os_exit(1)

__vrm_portal_id = None
def get_vrm_portal_id():
	# For the CCGX, the definition of the VRM Portal ID is that it is the mac address of the onboard-
	# ethernet port (eth0), stripped from its colons (:) and lower case.

	# nice coincidence is that this also works fine when running on your (linux) development computer.

	global __vrm_portal_id

	if __vrm_portal_id:
		return __vrm_portal_id

	# Assume we are on linux
	import fcntl, socket, struct

	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', 'eth0'[:15]))
	__vrm_portal_id = ''.join(['%02x' % ord(char) for char in info[18:24]])

	return __vrm_portal_id

# See VE.Can registers - public.docx for definition of this conversion
def convert_vreg_version_to_readable(version):
	def str_to_arr(x, length):
		a = []
		for i in range(0, len(x), length):
			a.append(x[i:i+length])
		return a

	x = "%x" % version
	x = x.upper()

	if len(x) == 5 or len(x) == 3 or len(x) == 1:
		x = '0' + x

	a = str_to_arr(x, 2);

	# remove the first 00 if there are three bytes and it is 00
	if len(a) == 3 and a[0] == '00':
		a.remove(0);

	# if we have two or three bytes now, and the first character is a 0, remove it
	if len(a) >= 2 and a[0][0:1] == '0':
		a[0] = a[0][1];

	result = ''
	for item in a:
		result += ('.' if result != '' else '') + item

	result = 'v' + result

	return result

def get_free_space(path):
	result = -1

	try:
		s = statvfs(path)
		result = s.f_frsize * s.f_bavail     # Number of free bytes that ordinary users
	except Exception, ex:
		logger.info("Error while retrieving free space for path %s: %s" % (path, ex))

	return result

def get_load_averages():
	c = read_file('/proc/loadavg')
	return c.split(' ')[:3]

# Returns False if it cannot find a machine name. Otherwise returns the string
# containing the name
def get_machine_name():
	c = read_file('/proc/device-tree/model')

	if c != False:
		return c.strip('\x00')

	return read_file('/etc/venus/machine')

# Returns False if it cannot open the file. Otherwise returns its rstripped contents
def read_file(path):
	content = False

	try:
		with open(path, 'r') as f:
			content = f.read().rstrip()
	except Exception, ex:
		logger.debug("Error while reading %s: %s" % (path, ex))

	return content

def wrap_dbus_value(value):
	if value is None:
		return VEDBUS_INVALID
	if isinstance(value, float):
		return dbus.Double(value, variant_level=1)
	if isinstance(value, bool):
		return dbus.Boolean(value, variant_level=1)
	if isinstance(value, int):
		return dbus.Int32(value, variant_level=1)
	if isinstance(value, str):
		return dbus.String(value, variant_level=1)
	if isinstance(value, unicode):
		return dbus.String(value, variant_level=1)
	if isinstance(value, list):
		if len(value) == 0:
			# If the list is empty we cannot infer the type of the contents. So assume unsigned integer.
			# A (signed) integer is dangerous, because an empty list of signed integers is used to encode
			# an invalid value.
			return dbus.Array([], signature=dbus.Signature('u'), variant_level=1)
		return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1)
	if isinstance(value, long):
		return dbus.Int64(value, variant_level=1)
	if isinstance(value, dict):
		# Wrapping the keys of the dictionary causes D-Bus errors like:
		# 'arguments to dbus_message_iter_open_container() were incorrect,
		# assertion "(type == DBUS_TYPE_ARRAY && contained_signature &&
		# *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL ||
		# _dbus_check_is_valid_signature (contained_signature))" failed in file ...'
		return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1)
	return value

dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64)

def unwrap_dbus_value(val):
	"""Converts D-Bus values back to the original type. For example if val is of type DBus.Double,
	a float will be returned."""
	if isinstance(val, dbus_int_types):
		return int(val)
	if isinstance(val, dbus.Double):
		return float(val)
	if isinstance(val, dbus.Array):
		v = [unwrap_dbus_value(x) for x in val]
		return None if len(v) == 0 else v
	if isinstance(val, (dbus.Signature, dbus.String)):
		return unicode(val)
	# Python has no byte type, so we convert to an integer.
	if isinstance(val, dbus.Byte):
		return int(val)
	if isinstance(val, dbus.ByteArray):
		return "".join([str(x) for x in val])
	if isinstance(val, (list, tuple)):
		return [unwrap_dbus_value(x) for x in val]
	if isinstance(val, (dbus.Dictionary, dict)):
		# Do not unwrap the keys, see comment in wrap_dbus_value
		return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()])
	if isinstance(val, dbus.Boolean):
		return bool(val)
	return val
<commit_msg>Add reify decorator.<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from traceback import print_exc
from os import _exit as os_exit
from os import statvfs
import logging
from functools import update_wrapper
import dbus
logger = logging.getLogger(__name__)

VEDBUS_INVALID = dbus.Array([], signature=dbus.Signature('i'), variant_level=1)

# Use this function to make sure the code quits on an unexpected exception. Make sure to use it
# when using gobject.idle_add and also gobject.timeout_add.
# Without this, the code will just keep running, since gobject does not stop the mainloop on an
# exception.
# Example: gobject.idle_add(exit_on_error, myfunc, arg1, arg2)
def exit_on_error(func, *args, **kwargs):
	try:
		return func(*args, **kwargs)
	except:
		try:
			print 'exit_on_error: there was an exception. Printing stacktrace will be tryed and then exit'
			print_exc()
		except:
			pass

		# sys.exit() is not used, since that throws an exception, which does not lead to a program
		# halt when used in a dbus callback, see connection.py in the Python/Dbus libraries, line 230.
		os_exit(1)

__vrm_portal_id = None
def get_vrm_portal_id():
	# For the CCGX, the definition of the VRM Portal ID is that it is the mac address of the onboard-
	# ethernet port (eth0), stripped from its colons (:) and lower case.

	# nice coincidence is that this also works fine when running on your (linux) development computer.

	global __vrm_portal_id

	if __vrm_portal_id:
		return __vrm_portal_id

	# Assume we are on linux
	import fcntl, socket, struct

	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', 'eth0'[:15]))
	__vrm_portal_id = ''.join(['%02x' % ord(char) for char in info[18:24]])

	return __vrm_portal_id

# See VE.Can registers - public.docx for definition of this conversion
def convert_vreg_version_to_readable(version):
	def str_to_arr(x, length):
		a = []
		for i in range(0, len(x), length):
			a.append(x[i:i+length])
		return a

	x = "%x" % version
	x = x.upper()

	if len(x) == 5 or len(x) == 3 or len(x) == 1:
		x = '0' + x

	a = str_to_arr(x, 2);

	# remove the first 00 if there are three bytes and it is 00
	if len(a) == 3 and a[0] == '00':
		a.remove(0);

	# if we have two or three bytes now, and the first character is a 0, remove it
	if len(a) >= 2 and a[0][0:1] == '0':
		a[0] = a[0][1];

	result = ''
	for item in a:
		result += ('.' if result != '' else '') + item

	result = 'v' + result

	return result

def get_free_space(path):
	result = -1

	try:
		s = statvfs(path)
		result = s.f_frsize * s.f_bavail     # Number of free bytes that ordinary users
	except Exception, ex:
		logger.info("Error while retrieving free space for path %s: %s" % (path, ex))

	return result

def get_load_averages():
	c = read_file('/proc/loadavg')
	return c.split(' ')[:3]

# Returns False if it cannot find a machine name. Otherwise returns the string
# containing the name
def get_machine_name():
	c = read_file('/proc/device-tree/model')

	if c != False:
		return c.strip('\x00')

	return read_file('/etc/venus/machine')

# Returns False if it cannot open the file. Otherwise returns its rstripped contents
def read_file(path):
	content = False

	try:
		with open(path, 'r') as f:
			content = f.read().rstrip()
	except Exception, ex:
		logger.debug("Error while reading %s: %s" % (path, ex))

	return content

def wrap_dbus_value(value):
	if value is None:
		return VEDBUS_INVALID
	if isinstance(value, float):
		return dbus.Double(value, variant_level=1)
	if isinstance(value, bool):
		return dbus.Boolean(value, variant_level=1)
	if isinstance(value, int):
		return dbus.Int32(value, variant_level=1)
	if isinstance(value, str):
		return dbus.String(value, variant_level=1)
	if isinstance(value, unicode):
		return dbus.String(value, variant_level=1)
	if isinstance(value, list):
		if len(value) == 0:
			# If the list is empty we cannot infer the type of the contents. So assume unsigned integer.
			# A (signed) integer is dangerous, because an empty list of signed integers is used to encode
			# an invalid value.
			return dbus.Array([], signature=dbus.Signature('u'), variant_level=1)
		return dbus.Array([wrap_dbus_value(x) for x in value], variant_level=1)
	if isinstance(value, long):
		return dbus.Int64(value, variant_level=1)
	if isinstance(value, dict):
		# Wrapping the keys of the dictionary causes D-Bus errors like:
		# 'arguments to dbus_message_iter_open_container() were incorrect,
		# assertion "(type == DBUS_TYPE_ARRAY && contained_signature &&
		# *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) || (contained_signature == NULL ||
		# _dbus_check_is_valid_signature (contained_signature))" failed in file ...'
		return dbus.Dictionary({(k, wrap_dbus_value(v)) for k, v in value.items()}, variant_level=1)
	return value

dbus_int_types = (dbus.Int32, dbus.UInt32, dbus.Byte, dbus.Int16, dbus.UInt16, dbus.UInt32, dbus.Int64, dbus.UInt64)

def unwrap_dbus_value(val):
	"""Converts D-Bus values back to the original type. For example if val is of type DBus.Double,
	a float will be returned."""
	if isinstance(val, dbus_int_types):
		return int(val)
	if isinstance(val, dbus.Double):
		return float(val)
	if isinstance(val, dbus.Array):
		v = [unwrap_dbus_value(x) for x in val]
		return None if len(v) == 0 else v
	if isinstance(val, (dbus.Signature, dbus.String)):
		return unicode(val)
	# Python has no byte type, so we convert to an integer.
	if isinstance(val, dbus.Byte):
		return int(val)
	if isinstance(val, dbus.ByteArray):
		return "".join([str(x) for x in val])
	if isinstance(val, (list, tuple)):
		return [unwrap_dbus_value(x) for x in val]
	if isinstance(val, (dbus.Dictionary, dict)):
		# Do not unwrap the keys, see comment in wrap_dbus_value
		return dict([(x, unwrap_dbus_value(y)) for x, y in val.items()])
	if isinstance(val, dbus.Boolean):
		return bool(val)
	return val

class reify(object):
	""" Decorator to replace a property of an object with the calculated value,
	    to make it concrete. """
	def __init__(self, wrapped):
		self.wrapped = wrapped
		update_wrapper(self, wrapped)
	def __get__(self, inst, objtype=None):
		if inst is None:
			return self
		v = self.wrapped(inst)
		setattr(inst, self.wrapped.__name__, v)
		return v
<|endoftext|>


<commit_before># Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

""" Units conversions and constants

The purpose of the module is to keep Sugar independent from the
screen size, factory and DPI. There a few use cases that needs
to be considered:

  - The XO display. The screen DPI is 201 and the screen
    resolution is 1200x900. The screen factor is 4:3.
  - The Sugar emulator runned on traditional screens. Resolution
    is variable, ranging from 800x600 up to 1200x900. The DPI
    is usually but not necessarily 96. The screen factor is
    either 4:3 or 16:9
  - Other embedded devices. DPI, screen resolution and screen
    factor are variable.

To achieve the goal a few rules needs to be respected when
writing code for Sugar:

  - Never use absolute positioning. Use the layout facilities
    provided by HippoCanvas. If you need custom layouts make
    sure they adapt to different screen resolutions.
  - Never specify sizes, fonts, borders or padding using pixels.
    Instead use the device independt units provided by this
    module.

We are currently providing the following resolution independent
units:

  - Points.
  - Grid. One cell of the screen grid as specificed by the HIG.
  - Microgrid. One microcell of the screen grid as
    specificed by the HIG.
  - A set of icon sizes as specified by the HIG (standard, small,
    medium, large, xlarge).

Just scaling UI elements on the base of the screen DPI is not
enough to provide a good experience. For example on smaller
screens smaller fonts or icons might be acceptable to gain
screen aestate. For this reason a constant zoom factor is
applied to all the transformation from resolution independent
units to device units.

"""

import gtk

_MAX_ZOOM_FACTOR = 2.0
_ZOOM_CONSTANT   = 650.0

def _compute_zoom_factor():
    screen_width = gtk.gdk.screen_width()
    if _screen_dpi == 201.0 and screen_width == 1200:
        return 1.0
    else:
        return min(_MAX_ZOOM_FACTOR, screen_width / _ZOOM_CONSTANT)

_gtk_xft_dpi = gtk.settings_get_default().get_property('gtk-xft-dpi')
_screen_dpi = float(_gtk_xft_dpi / 1024)
_dpi_factor  = _screen_dpi / 201.0
_zoom_factor = _compute_zoom_factor()

STANDARD_ICON_SCALE = 1.0 * _dpi_factor * _zoom_factor
SMALL_ICON_SCALE    = 0.5 * _dpi_factor * _zoom_factor
MEDIUM_ICON_SCALE   = 1.5 * _dpi_factor * _zoom_factor
LARGE_ICON_SCALE    = 2.0 * _dpi_factor * _zoom_factor
XLARGE_ICON_SCALE   = 2.75 * _dpi_factor * _zoom_factor

def points_to_device(points):
    return int(points * _zoom_factor)

def points_to_pixels(points):
    return int(points * _screen_dpi / 72.0 * _zoom_factor)

def grid_to_pixels(units):
    return int(units * 75.0 * _dpi_factor * _zoom_factor)

def microgrid_to_pixels(units):
    return int(units * 15.0 * _dpi_factor * _zoom_factor)
<commit_msg>gtk thinks the xo dpi is 200.0<commit_after># Copyright (C) 2006, Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

""" Units conversions and constants

The purpose of the module is to keep Sugar independent from the
screen size, factory and DPI. There a few use cases that needs
to be considered:

  - The XO display. The screen DPI is 201 and the screen
    resolution is 1200x900. The screen factor is 4:3.
  - The Sugar emulator runned on traditional screens. Resolution
    is variable, ranging from 800x600 up to 1200x900. The DPI
    is usually but not necessarily 96. The screen factor is
    either 4:3 or 16:9
  - Other embedded devices. DPI, screen resolution and screen
    factor are variable.

To achieve the goal a few rules needs to be respected when
writing code for Sugar:

  - Never use absolute positioning. Use the layout facilities
    provided by HippoCanvas. If you need custom layouts make
    sure they adapt to different screen resolutions.
  - Never specify sizes, fonts, borders or padding using pixels.
    Instead use the device independt units provided by this
    module.

We are currently providing the following resolution independent
units:

  - Points.
  - Grid. One cell of the screen grid as specificed by the HIG.
  - Microgrid. One microcell of the screen grid as
    specificed by the HIG.
  - A set of icon sizes as specified by the HIG (standard, small,
    medium, large, xlarge).

Just scaling UI elements on the base of the screen DPI is not
enough to provide a good experience. For example on smaller
screens smaller fonts or icons might be acceptable to gain
screen aestate. For this reason a constant zoom factor is
applied to all the transformation from resolution independent
units to device units.

"""

import gtk

_XO_DPI = 200.0
_MAX_ZOOM_FACTOR = 2.0
_ZOOM_CONSTANT   = 650.0

def _compute_zoom_factor():
    screen_width = gtk.gdk.screen_width()
    if _screen_dpi == _XO_DPI and screen_width == 1200:
        return 1.0
    else:
        return min(_MAX_ZOOM_FACTOR, screen_width / _ZOOM_CONSTANT)

_gtk_xft_dpi = gtk.settings_get_default().get_property('gtk-xft-dpi')
_screen_dpi = float(_gtk_xft_dpi / 1024)
_dpi_factor  = _screen_dpi / _XO_DPI
_zoom_factor = _compute_zoom_factor()

STANDARD_ICON_SCALE = 1.0 * _dpi_factor * _zoom_factor
SMALL_ICON_SCALE    = 0.5 * _dpi_factor * _zoom_factor
MEDIUM_ICON_SCALE   = 1.5 * _dpi_factor * _zoom_factor
LARGE_ICON_SCALE    = 2.0 * _dpi_factor * _zoom_factor
XLARGE_ICON_SCALE   = 2.75 * _dpi_factor * _zoom_factor

def points_to_device(points):
    return int(points * _zoom_factor)

def points_to_pixels(points):
    return int(points * _screen_dpi / 72.0 * _zoom_factor)

def grid_to_pixels(units):
    return int(units * 75.0 * _dpi_factor * _zoom_factor)

def microgrid_to_pixels(units):
    return int(units * 15.0 * _dpi_factor * _zoom_factor)
<|endoftext|>


<commit_before>"""The version for all Santa components."""

SANTA_VERSION = "2021.6"
<commit_msg>Bump version -> 2021.7 (#575)<commit_after>"""The version for all Santa components."""

SANTA_VERSION = "2021.7"
<|endoftext|>