<commit_before>"""
Command handler

This module contains the infrastructure for accepting commands on the
command line. The process is as follows:

1) The calling object (caller) inputs a string and triggers the command parsing system.
2) The system checks the state of the caller - loggedin or not
3) If no command string was supplied, we search the merged cmdset for system command CMD_NOINPUT
   and branches to execute that.  --> Finished
4) Cmdsets are gathered from different sources (in order of dropping priority):
           channels - all available channel names are auto-created into a cmdset, to allow
                  for giving the channel name and have the following immediately
                  sent to the channel. The sending is performed by the CMD_CHANNEL
                  system command.
           object cmdsets - all objects at caller's location are scanned for non-empty
                  cmdsets. This includes cmdsets on exits.
           caller - the caller is searched for its own currently active cmdset.
           player - lastly the cmdsets defined on caller.player are added.
5) All the gathered cmdsets (if more than one) are merged into one using the cmdset priority rules.
6) If merged cmdset is empty, raise NoCmdSet exception (this should not happen, at least the
   player should have a default cmdset available at all times). --> Finished
7) The raw input string is parsed using the parser defined by settings.COMMAND_PARSER. It
   uses the available commands from the merged cmdset to know which commands to look for and
   returns one or many matches.
8)   If match list is empty, branch to system command CMD_NOMATCH --> Finished
9)   If match list has more than one element, branch to system command CMD_MULTIMATCH --> Finished
10) A single match was found. If this is a channel-command (i.e. the command name is that of a channel),
    branch to CMD_CHANNEL --> Finished
11) At this point we have found a normal command. We assign useful variables to it that
    will be available to the command coder at run-time.
12) We have a unique cmdobject, primed for use. Call all hooks:
    at_pre_cmd(), cmdobj.parse(), cmdobj.func() and finally at_post_cmd().

"""

from copy import copy
from traceback import format_exc
from twisted.internet.defer import inlineCallbacks, returnValue
from django.conf import settings
from src.comms.channelhandler import CHANNELHANDLER
from src.utils import logger, utils
from src.commands.cmdset import CmdSet
from src.commands.cmdparser import at_multimatch_cmd
from src.utils.utils import string_suggestions, make_iter

from django.utils.translation import ugettext as _

__all__ = ("cmdhandler",)

# This decides which command parser is to be used.
# You have to restart the server for changes to take effect.
_COMMAND_PARSER = utils.variable_from_module(*settings.COMMAND_PARSER.rsplit('.', 1))

# System command names - import these variables rather than trying to
# remember the actual string constants. If not defined, Evennia
# hard-coded defaults are used instead.

# command to call if user just presses <return> with no input
CMD_NOINPUT = "__noinput_command"
# command to call if no command match was found
CMD_NOMATCH = "__nomatch_command"
# command to call if multiple command matches were found
CMD_MULTIMATCH = "__multimatch_command"
# command to call if found command is the name of a channel
CMD_CHANNEL = "__send_to_channel_command"
# command to call as the very first one when the user connects.
# (is expected to display the login screen)
CMD_LOGINSTART = "__unloggedin_look_command"

# custom Exceptions

class NoCmdSets(Exception):
    "No cmdsets found. Critical error."
    pass
class ExecSystemCommand(Exception):
    "Run a system command"
    def __init__(self, syscmd, sysarg):
        self.args = (syscmd, sysarg) # needed by exception error handling
        self.syscmd = syscmd
        self.sysarg = sysarg

# Helper function

@inlineCallbacks
def get_and_merge_cmdsets(caller):
    """
    Gather all relevant cmdsets and merge them. Note
    that this is only relevant for logged-in callers.

    Note that this function returns a deferred!
    """
    # The calling object's cmdset
    try:
        yield caller.at_cmdset_get()
    except Exception:
        logger.log_trace()
    try:
        caller_cmdset = caller.cmdset.current
    except AttributeError:
        caller_cmdset = None

    # Create cmdset for all player's available channels
    channel_cmdset = None
    if not caller_cmdset.no_channels:
        channel_cmdset = yield CHANNELHANDLER.get_cmdset(caller)

    # Gather cmdsets from location, objects in location or carried
    local_objects_cmdsets = [None]
    try:
        location = caller.location
    except Exception:
        location = None
    if location and not caller_cmdset.no_objs:
        # Gather all cmdsets stored on objects in the room and
        # also in the caller's inventory and the location itself
        local_objlist = yield location.contents_get(exclude=caller.dbobj) + caller.contents + [location]
        for obj in local_objlist:
            try:
                # call hook in case we need to do dynamic changing to cmdset
                yield obj.at_cmdset_get()
            except Exception:
                logger.log_trace()
        # the call-type lock is checked here, it makes sure a player is not seeing e.g. the commands
        # on a fellow player (which is why the no_superuser_bypass must be True)
        local_objects_cmdsets = yield [obj.cmdset.current for obj in local_objlist
                                       if (obj.cmdset.current and obj.locks.check(caller, 'call', no_superuser_bypass=True))]
        for cset in local_objects_cmdsets:
            #This is necessary for object sets, or we won't be able to separate
            #the command sets from each other in a busy room.
            cset.old_duplicates = cset.duplicates
            cset.duplicates = True

    # Player object's commandsets
    try:
        player_cmdset = caller.player.cmdset.current
    except AttributeError:
        player_cmdset = None

    cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
    # weed out all non-found sets
    cmdsets = yield [cmdset for cmdset in cmdsets if cmdset]
    # report cmdset errors to user (these should already have been logged)
    yield [caller.msg(cmdset.message) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
    # sort cmdsets after reverse priority (highest prio are merged in last)
    yield cmdsets.sort(key=lambda x: x.priority)
    #cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)

    if cmdsets:
        # Merge all command sets into one, beginning with the lowest-prio one
        cmdset = cmdsets.pop(0)
        for merging_cmdset in cmdsets:
            #print "<%s(%s,%s)> onto <%s(%s,%s)>" % (merging_cmdset.key, merging_cmdset.priority, merging_cmdset.mergetype,
            #                                        cmdset.key, cmdset.priority, cmdset.mergetype)
            cmdset = yield merging_cmdset + cmdset
    else:
        cmdset = None

    for cset in (cset for cset in local_objects_cmdsets if cset):
        cset.duplicates = cset.old_duplicates
    returnValue(cmdset)

# Main command-handler function

@inlineCallbacks
def cmdhandler(caller, raw_string, testing=False):
    """
    This is the main function to handle any string sent to the engine.

    caller - calling object
    raw_string - the command string given on the command line
    testing - if we should actually execute the command or not.
              if True, the command instance will be returned instead.

    Note that this function returns a deferred!
    """
    try: # catch bugs in cmdhandler itself
        try: # catch special-type commands

            cmdset = yield get_and_merge_cmdsets(caller)
            if not cmdset:
                # this is bad and shouldn't happen.
                raise NoCmdSets
            unformatted_raw_string = raw_string
            raw_string = raw_string.strip()
            if not raw_string:
                # Empty input. Test for system command instead.
                syscmd = yield cmdset.get(CMD_NOINPUT)
                sysarg = ""
                raise ExecSystemCommand(syscmd, sysarg)
            # Parse the input string and match to available cmdset.
            # This also checks for permissions, so all commands in match
            # are commands the caller is allowed to call.
            matches = yield _COMMAND_PARSER(raw_string, cmdset, caller)

            # Deal with matches

            if len(matches) > 1:
                # We have a multiple-match
                syscmd = yield cmdset.get(CMD_MULTIMATCH)
                sysarg = _("There were multiple matches.")
                if syscmd:
                    syscmd.matches = matches
                else:
                    sysarg = yield at_multimatch_cmd(caller, matches)
                raise ExecSystemCommand(syscmd, sysarg)

            if len(matches) == 1:
                # We have a unique command match.
                match = matches[0]
                cmdname, args, cmd = match[0], match[1], match[2]

                # check if we allow this type of command
                if cmdset.no_channels and hasattr(cmd, "is_channel") and cmd.is_channel:
                    matches = []
                if cmdset.no_exits and hasattr(cmd, "is_exit") and cmd.is_exit:
                    matches = []

            if not matches:
                # No commands match our entered command
                syscmd = yield cmdset.get(CMD_NOMATCH)
                if syscmd:
                    sysarg = raw_string
                else:
                    sysarg = _("Command '%s' is not available.") % raw_string
                    suggestions = string_suggestions(raw_string, cmdset.get_all_cmd_keys_and_aliases(caller), cutoff=0.7, maxnum=3)
                    if suggestions:
                        sysarg += _(" Maybe you meant %s?") % utils.list_to_string(suggestions, _('or'), addquote=True)
                    else:
                        sysarg += _(" Type \"help\" for help.")
                raise ExecSystemCommand(syscmd, sysarg)

            # Check if this is a Channel match.
            if hasattr(cmd, 'is_channel') and cmd.is_channel:
                # even if a user-defined syscmd is not defined, the
                # found cmd is already a system command in its own right.
                syscmd = yield cmdset.get(CMD_CHANNEL)
                if syscmd:
                    # replace system command with custom version
                    cmd = syscmd
                sysarg = "%s:%s" % (cmdname, args)
                raise ExecSystemCommand(cmd, sysarg)

            # A normal command.

            # Assign useful variables to the instance
            cmd.caller = caller
            cmd.cmdstring = cmdname
            cmd.args = args
            cmd.cmdset = cmdset
            cmd.raw_string = unformatted_raw_string

            if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
                # cmd.obj is automatically made available.
                # we make sure to validate its scripts.
                yield cmd.obj.scripts.validate()

            if testing:
                # only return the command instance
                returnValue(cmd)

            # pre-command hook
            yield cmd.at_pre_cmd()

            # Parse and execute
            yield cmd.parse()
            # (return value is normally None)
            ret = yield cmd.func()

            if hasattr(cmd, "funcparts"):
                # yield on command parts (for multi-part delayed commands)
                for funcpart in make_iter(cmd.funcparts):
                    yield funcpart()

            # post-command hook
            yield cmd.at_post_cmd()

            if cmd.save_for_next:
                # store a reference to this command, possibly
                # accessible by the next command.
                caller.ndb.last_cmd = yield copy(cmd)
            else:
                caller.ndb.last_cmd = None
            # Done! This returns a deferred. By default, Evennia does
            # not use this at all.
            returnValue(ret)

        except ExecSystemCommand, exc:
            # Not a normal command: run a system command, if available,
            # or fall back to a return string.
            syscmd = exc.syscmd
            sysarg = exc.sysarg
            if syscmd:
                syscmd.caller = caller
                syscmd.cmdstring = syscmd.key
                syscmd.args = sysarg
                syscmd.cmdset = cmdset
                syscmd.raw_string = unformatted_raw_string

                if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'):
                    # cmd.obj is automatically made available.
                    # we make sure to validate its scripts.
                    yield syscmd.obj.scripts.validate()

                if testing:
                    # only return the command instance
                    returnValue(syscmd)

                # parse and run the command
                yield syscmd.parse()
                yield syscmd.func()
            elif sysarg:
                # return system arg
                caller.msg(exc.sysarg)

        except NoCmdSets:
            # Critical error.
            string = "No command sets found! This is a sign of a critical bug.\n"
            string += "The error was logged.\n"
            string += "If logging out/in doesn't solve the problem, try to "
            string += "contact the server admin through some other means "
            string += "for assistance."
            caller.msg(_(string))
            logger.log_errmsg("No cmdsets found: %s" % caller)

        except Exception:
            # We should not end up here. If we do, it's a programming bug.
            string = "%s\nAbove traceback is from an untrapped error."
            string += " Please file a bug report."
            logger.log_trace(_(string))
            caller.msg(string % format_exc())

    except Exception:
        # This catches exceptions in cmdhandler exceptions themselves
        string = "%s\nAbove traceback is from a Command handler bug."
        string += " Please contact an admin and/or file a bug report."
        logger.log_trace(_(string))
        caller.msg(string % format_exc())
<commit_msg>Added an abort condition to the cmd's funcparts chain.<commit_after>"""
Command handler

This module contains the infrastructure for accepting commands on the
command line. The process is as follows:

1) The calling object (caller) inputs a string and triggers the command parsing system.
2) The system checks the state of the caller - loggedin or not
3) If no command string was supplied, we search the merged cmdset for system command CMD_NOINPUT
   and branches to execute that.  --> Finished
4) Cmdsets are gathered from different sources (in order of dropping priority):
           channels - all available channel names are auto-created into a cmdset, to allow
                  for giving the channel name and have the following immediately
                  sent to the channel. The sending is performed by the CMD_CHANNEL
                  system command.
           object cmdsets - all objects at caller's location are scanned for non-empty
                  cmdsets. This includes cmdsets on exits.
           caller - the caller is searched for its own currently active cmdset.
           player - lastly the cmdsets defined on caller.player are added.
5) All the gathered cmdsets (if more than one) are merged into one using the cmdset priority rules.
6) If merged cmdset is empty, raise NoCmdSet exception (this should not happen, at least the
   player should have a default cmdset available at all times). --> Finished
7) The raw input string is parsed using the parser defined by settings.COMMAND_PARSER. It
   uses the available commands from the merged cmdset to know which commands to look for and
   returns one or many matches.
8)   If match list is empty, branch to system command CMD_NOMATCH --> Finished
9)   If match list has more than one element, branch to system command CMD_MULTIMATCH --> Finished
10) A single match was found. If this is a channel-command (i.e. the command name is that of a channel),
    branch to CMD_CHANNEL --> Finished
11) At this point we have found a normal command. We assign useful variables to it that
    will be available to the command coder at run-time.
12) We have a unique cmdobject, primed for use. Call all hooks:
    at_pre_cmd(), cmdobj.parse(), cmdobj.func() and finally at_post_cmd().

"""

from copy import copy
from traceback import format_exc
from twisted.internet.defer import inlineCallbacks, returnValue
from django.conf import settings
from src.comms.channelhandler import CHANNELHANDLER
from src.utils import logger, utils
from src.commands.cmdset import CmdSet
from src.commands.cmdparser import at_multimatch_cmd
from src.utils.utils import string_suggestions, make_iter

from django.utils.translation import ugettext as _

__all__ = ("cmdhandler",)

# This decides which command parser is to be used.
# You have to restart the server for changes to take effect.
_COMMAND_PARSER = utils.variable_from_module(*settings.COMMAND_PARSER.rsplit('.', 1))

# System command names - import these variables rather than trying to
# remember the actual string constants. If not defined, Evennia
# hard-coded defaults are used instead.

# command to call if user just presses <return> with no input
CMD_NOINPUT = "__noinput_command"
# command to call if no command match was found
CMD_NOMATCH = "__nomatch_command"
# command to call if multiple command matches were found
CMD_MULTIMATCH = "__multimatch_command"
# command to call if found command is the name of a channel
CMD_CHANNEL = "__send_to_channel_command"
# command to call as the very first one when the user connects.
# (is expected to display the login screen)
CMD_LOGINSTART = "__unloggedin_look_command"

# custom Exceptions

class NoCmdSets(Exception):
    "No cmdsets found. Critical error."
    pass
class ExecSystemCommand(Exception):
    "Run a system command"
    def __init__(self, syscmd, sysarg):
        self.args = (syscmd, sysarg) # needed by exception error handling
        self.syscmd = syscmd
        self.sysarg = sysarg

# Helper function

@inlineCallbacks
def get_and_merge_cmdsets(caller):
    """
    Gather all relevant cmdsets and merge them. Note
    that this is only relevant for logged-in callers.

    Note that this function returns a deferred!
    """
    # The calling object's cmdset
    try:
        yield caller.at_cmdset_get()
    except Exception:
        logger.log_trace()
    try:
        caller_cmdset = caller.cmdset.current
    except AttributeError:
        caller_cmdset = None

    # Create cmdset for all player's available channels
    channel_cmdset = None
    if not caller_cmdset.no_channels:
        channel_cmdset = yield CHANNELHANDLER.get_cmdset(caller)

    # Gather cmdsets from location, objects in location or carried
    local_objects_cmdsets = [None]
    try:
        location = caller.location
    except Exception:
        location = None
    if location and not caller_cmdset.no_objs:
        # Gather all cmdsets stored on objects in the room and
        # also in the caller's inventory and the location itself
        local_objlist = yield location.contents_get(exclude=caller.dbobj) + caller.contents + [location]
        for obj in local_objlist:
            try:
                # call hook in case we need to do dynamic changing to cmdset
                yield obj.at_cmdset_get()
            except Exception:
                logger.log_trace()
        # the call-type lock is checked here, it makes sure a player is not seeing e.g. the commands
        # on a fellow player (which is why the no_superuser_bypass must be True)
        local_objects_cmdsets = yield [obj.cmdset.current for obj in local_objlist
                                       if (obj.cmdset.current and obj.locks.check(caller, 'call', no_superuser_bypass=True))]
        for cset in local_objects_cmdsets:
            #This is necessary for object sets, or we won't be able to separate
            #the command sets from each other in a busy room.
            cset.old_duplicates = cset.duplicates
            cset.duplicates = True

    # Player object's commandsets
    try:
        player_cmdset = caller.player.cmdset.current
    except AttributeError:
        player_cmdset = None

    cmdsets = yield [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
    # weed out all non-found sets
    cmdsets = yield [cmdset for cmdset in cmdsets if cmdset]
    # report cmdset errors to user (these should already have been logged)
    yield [caller.msg(cmdset.message) for cmdset in cmdsets if cmdset.key == "_CMDSET_ERROR"]
    # sort cmdsets after reverse priority (highest prio are merged in last)
    yield cmdsets.sort(key=lambda x: x.priority)
    #cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)

    if cmdsets:
        # Merge all command sets into one, beginning with the lowest-prio one
        cmdset = cmdsets.pop(0)
        for merging_cmdset in cmdsets:
            #print "<%s(%s,%s)> onto <%s(%s,%s)>" % (merging_cmdset.key, merging_cmdset.priority, merging_cmdset.mergetype,
            #                                        cmdset.key, cmdset.priority, cmdset.mergetype)
            cmdset = yield merging_cmdset + cmdset
    else:
        cmdset = None

    for cset in (cset for cset in local_objects_cmdsets if cset):
        cset.duplicates = cset.old_duplicates
    returnValue(cmdset)

# Main command-handler function

@inlineCallbacks
def cmdhandler(caller, raw_string, testing=False):
    """
    This is the main function to handle any string sent to the engine.

    caller - calling object
    raw_string - the command string given on the command line
    testing - if we should actually execute the command or not.
              if True, the command instance will be returned instead.

    Note that this function returns a deferred!
    """
    try: # catch bugs in cmdhandler itself
        try: # catch special-type commands

            cmdset = yield get_and_merge_cmdsets(caller)
            if not cmdset:
                # this is bad and shouldn't happen.
                raise NoCmdSets
            unformatted_raw_string = raw_string
            raw_string = raw_string.strip()
            if not raw_string:
                # Empty input. Test for system command instead.
                syscmd = yield cmdset.get(CMD_NOINPUT)
                sysarg = ""
                raise ExecSystemCommand(syscmd, sysarg)
            # Parse the input string and match to available cmdset.
            # This also checks for permissions, so all commands in match
            # are commands the caller is allowed to call.
            matches = yield _COMMAND_PARSER(raw_string, cmdset, caller)

            # Deal with matches

            if len(matches) > 1:
                # We have a multiple-match
                syscmd = yield cmdset.get(CMD_MULTIMATCH)
                sysarg = _("There were multiple matches.")
                if syscmd:
                    syscmd.matches = matches
                else:
                    sysarg = yield at_multimatch_cmd(caller, matches)
                raise ExecSystemCommand(syscmd, sysarg)

            if len(matches) == 1:
                # We have a unique command match.
                match = matches[0]
                cmdname, args, cmd = match[0], match[1], match[2]

                # check if we allow this type of command
                if cmdset.no_channels and hasattr(cmd, "is_channel") and cmd.is_channel:
                    matches = []
                if cmdset.no_exits and hasattr(cmd, "is_exit") and cmd.is_exit:
                    matches = []

            if not matches:
                # No commands match our entered command
                syscmd = yield cmdset.get(CMD_NOMATCH)
                if syscmd:
                    sysarg = raw_string
                else:
                    sysarg = _("Command '%s' is not available.") % raw_string
                    suggestions = string_suggestions(raw_string, cmdset.get_all_cmd_keys_and_aliases(caller), cutoff=0.7, maxnum=3)
                    if suggestions:
                        sysarg += _(" Maybe you meant %s?") % utils.list_to_string(suggestions, _('or'), addquote=True)
                    else:
                        sysarg += _(" Type \"help\" for help.")
                raise ExecSystemCommand(syscmd, sysarg)

            # Check if this is a Channel match.
            if hasattr(cmd, 'is_channel') and cmd.is_channel:
                # even if a user-defined syscmd is not defined, the
                # found cmd is already a system command in its own right.
                syscmd = yield cmdset.get(CMD_CHANNEL)
                if syscmd:
                    # replace system command with custom version
                    cmd = syscmd
                sysarg = "%s:%s" % (cmdname, args)
                raise ExecSystemCommand(cmd, sysarg)

            # A normal command.

            # Assign useful variables to the instance
            cmd.caller = caller
            cmd.cmdstring = cmdname
            cmd.args = args
            cmd.cmdset = cmdset
            cmd.raw_string = unformatted_raw_string

            if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
                # cmd.obj is automatically made available.
                # we make sure to validate its scripts.
                yield cmd.obj.scripts.validate()

            if testing:
                # only return the command instance
                returnValue(cmd)

            # pre-command hook
            yield cmd.at_pre_cmd()

            # Parse and execute
            yield cmd.parse()
            # (return value is normally None)
            ret = yield cmd.func()

            if hasattr(cmd, "funcparts"):
                # yield on command parts (for multi-part delayed commands)
                for funcpart in make_iter(cmd.funcparts):
                    err = yield funcpart()
                    # returning anything but a deferred/None will kill the chain
                    if err: break

            # post-command hook
            yield cmd.at_post_cmd()

            if cmd.save_for_next:
                # store a reference to this command, possibly
                # accessible by the next command.
                caller.ndb.last_cmd = yield copy(cmd)
            else:
                caller.ndb.last_cmd = None
            # Done! This returns a deferred. By default, Evennia does
            # not use this at all.
            returnValue(ret)

        except ExecSystemCommand, exc:
            # Not a normal command: run a system command, if available,
            # or fall back to a return string.
            syscmd = exc.syscmd
            sysarg = exc.sysarg
            if syscmd:
                syscmd.caller = caller
                syscmd.cmdstring = syscmd.key
                syscmd.args = sysarg
                syscmd.cmdset = cmdset
                syscmd.raw_string = unformatted_raw_string

                if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'):
                    # cmd.obj is automatically made available.
                    # we make sure to validate its scripts.
                    yield syscmd.obj.scripts.validate()

                if testing:
                    # only return the command instance
                    returnValue(syscmd)

                # parse and run the command
                yield syscmd.parse()
                yield syscmd.func()
            elif sysarg:
                # return system arg
                caller.msg(exc.sysarg)

        except NoCmdSets:
            # Critical error.
            string = "No command sets found! This is a sign of a critical bug.\n"
            string += "The error was logged.\n"
            string += "If logging out/in doesn't solve the problem, try to "
            string += "contact the server admin through some other means "
            string += "for assistance."
            caller.msg(_(string))
            logger.log_errmsg("No cmdsets found: %s" % caller)

        except Exception:
            # We should not end up here. If we do, it's a programming bug.
            string = "%s\nAbove traceback is from an untrapped error."
            string += " Please file a bug report."
            logger.log_trace(_(string))
            caller.msg(string % format_exc())

    except Exception:
        # This catches exceptions in cmdhandler exceptions themselves
        string = "%s\nAbove traceback is from a Command handler bug."
        string += " Please contact an admin and/or file a bug report."
        logger.log_trace(_(string))
        caller.msg(string % format_exc())
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Amara, universalsubtitles.org
#
# Copyright (C) 2013 Participatory Culture Foundation
#
# 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/agpl-3.0.html.

from django.contrib import admin

from externalsites import models

class SyncHistoryAdmin(admin.ModelAdmin):
    fields = (
        'video_url',
        'account_type',
        'account_id',
        'language',
        'datetime',
        'version',
        'result',
        'details',
        'retry',
    )
    readonly_fields = (
        'video_url',
        'account_type',
        'account_id',
        'language',
        'datetime',
        'version',
    )
    list_display = (
        'account',
        'video_url',
        'language',
        'retry',
    )
    list_filter = (
        'result',
        'retry',
    )
    list_select_related = True

    class Meta:
        model = models.SyncHistory

    def account(self, sh):
        return sh.get_account()

    def has_add_permission(self, request):
        return False

admin.site.register(models.KalturaAccount)
admin.site.register(models.BrightcoveAccount)
admin.site.register(models.YouTubeAccount)
admin.site.register(models.SyncedSubtitleVersion)
admin.site.register(models.SyncHistory, SyncHistoryAdmin)
<commit_msg>Adding openid-connect admin page<commit_after># -*- coding: utf-8 -*-
# Amara, universalsubtitles.org
#
# Copyright (C) 2013 Participatory Culture Foundation
#
# 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/agpl-3.0.html.

from django.contrib import admin

from externalsites import models

class SyncHistoryAdmin(admin.ModelAdmin):
    fields = (
        'video_url',
        'account_type',
        'account_id',
        'language',
        'datetime',
        'version',
        'result',
        'details',
        'retry',
    )
    readonly_fields = (
        'video_url',
        'account_type',
        'account_id',
        'language',
        'datetime',
        'version',
    )
    list_display = (
        'account',
        'video_url',
        'language',
        'retry',
    )
    list_filter = (
        'result',
        'retry',
    )
    list_select_related = True

    class Meta:
        model = models.SyncHistory

    def account(self, sh):
        return sh.get_account()

    def has_add_permission(self, request):
        return False

class OpenIDConnectLinkAdmin(admin.ModelAdmin):
    raw_id_fields = (
        'user',
    )

admin.site.register(models.KalturaAccount)
admin.site.register(models.BrightcoveAccount)
admin.site.register(models.YouTubeAccount)
admin.site.register(models.SyncedSubtitleVersion)
admin.site.register(models.SyncHistory, SyncHistoryAdmin)
admin.site.register(models.OpenIDConnectLink, OpenIDConnectLinkAdmin)
<|endoftext|>


<commit_before>import os

from django.db import models
from django.conf import settings

from labtracker.Viewer.models import base
import labtracker.Viewer.utils
import labtracker.LabtrackerCore.models as c_models
import labtracker.Machine.models as m_models

app_name = __name__.split('.')[-3]

class MachineMap(base.ViewCore):
    view = models.OneToOneField(base.ViewCore, parent_link=True, editable=False)

    def save(self):
        newmap = self.type_id == None
        self.type = labtracker.Viewer.utils.getViewType(__name__)
        super(MachineMap,self).save()

        if newmap:
            """
            Need to create directories for images
            """
            # create directory need to save image to
            css_dir = '%s/static/css/%s/%s/%s' % \
                (settings.APP_DIR, app_name, self.type.name, self.name)

            if not os.path.isdir(css_dir):
                os.mkdir(css_dir)

    def delete(self):
        self.view.delete()
        super(MachineMap,self).delete()   # delete self

    @models.permalink
    def get_absolute_url(self):
        return ('Viewer-MachineMap-view', [str(self.shortname)])

    @models.permalink
    def get_absolute_edit_url(self):
        return ('Viewer-MachineMap-edit', [str(self.shortname)])

    def getUnmappedItems(self):
        """
        Returns a list of items that have not been mapped yet
        """
        mapped = self.getMappedItems()
        mapped_set = set([m_item.machine for m_item in mapped])

        unmapped = []

        for group in groups:
            items = group.items.all()
            unmapped.extend( set(items).difference(mapped_set) )

        return unmapped

    def getMappedItems(self):
        """
        Returns a list of the Items that are currently in use by the view
        """
        return MachineMap_Item.objects.filter(view=self)

    class Meta:
        app_label = "Viewer"

class MachineMap_Size(models.Model):
    """
    This holds the allowed sizes for machines
    """
    name = models.CharField(max_length=60, unique=True)
    description = models.CharField(max_length=2616, blank=True)
    width = models.PositiveSmallIntegerField()
    height = models.PositiveSmallIntegerField()

    def __unicode__(self):
        return self.name

    class Meta:
        app_label = "Viewer"

class MachineMap_Item(models.Model):
    """
    This table is used by the machine map view to determine where computers are
    located
    """
    ORIENTATION_CHOICES = (
        ('H', 'Horizontal'),
        ('V', 'Vertical'),
    )

    machine = models.ForeignKey(m_models.Item)
    view = models.ForeignKey(MachineMap)
    size = models.ForeignKey(MachineMap_Size)
    xpos = models.IntegerField()
    ypos = models.IntegerField()
    orientation = models.CharField(max_length=1, choices=ORIENTATION_CHOICES,
            default='H')
    date_added = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return "%s -- %s (%d, %d)" % \
            (self.view, self.machine, self.xpos, self.ypos)

    class Meta:
        app_label = "Viewer"

        unique_together = (
            ('machine', 'view')
        )

<commit_msg>Commented out inheritance and namespace clashes with groups in ViewCore<commit_after>import os

from django.db import models
from django.conf import settings

from labtracker.Viewer.models import base
import labtracker.Viewer.utils
import labtracker.LabtrackerCore.models as c_models
import labtracker.Machine.models as m_models

app_name = __name__.split('.')[-3]

class MachineMap(base.ViewCore):
    view = models.OneToOneField(base.ViewCore, parent_link=True, editable=False)
    #groups = models.ManyToManyField(m_models.Group, related_name="view_machinemap_groups")

    def save(self):
        newmap = self.type_id == None
        self.type = labtracker.Viewer.utils.getViewType(__name__)
        super(MachineMap,self).save()

        if newmap:
            """
            Need to create directories for images
            """
            # create directory need to save image to
            css_dir = '%s/static/css/%s/%s/%s' % \
                (settings.APP_DIR, app_name, self.type.name, self.name)

            if not os.path.isdir(css_dir):
                os.mkdir(css_dir)

    def delete(self):
        self.view.delete()
        super(MachineMap,self).delete()   # delete self

    @models.permalink
    def get_absolute_url(self):
        return ('Viewer-MachineMap-view', [str(self.shortname)])

    @models.permalink
    def get_absolute_edit_url(self):
        return ('Viewer-MachineMap-edit', [str(self.shortname)])

    def getUnmappedItems(self):
        """
        Returns a list of items that have not been mapped yet
        """
        mapped = self.getMappedItems()
        mapped_set = set([m_item.machine for m_item in mapped])

        #groups = self.groups.all()
        unmapped = []

        for group in c_models.Group.objects.all(): #groups:
            items = group.items.all()
            unmapped.extend( set(items).difference(mapped_set) )

        return unmapped

    def getMappedItems(self):
        """
        Returns a list of the Items that are currently in use by the view
        """
        return MachineMap_Item.objects.filter(view=self)

    class Meta:
        app_label = "Viewer"

class MachineMap_Size(models.Model):
    """
    This holds the allowed sizes for machines
    """
    name = models.CharField(max_length=60, unique=True)
    description = models.CharField(max_length=2616, blank=True)
    width = models.PositiveSmallIntegerField()
    height = models.PositiveSmallIntegerField()

    def __unicode__(self):
        return self.name

    class Meta:
        app_label = "Viewer"

class MachineMap_Item(models.Model):
    """
    This table is used by the machine map view to determine where computers are
    located
    """
    ORIENTATION_CHOICES = (
        ('H', 'Horizontal'),
        ('V', 'Vertical'),
    )

    machine = models.ForeignKey(m_models.Item)
    view = models.ForeignKey(MachineMap)
    size = models.ForeignKey(MachineMap_Size)
    xpos = models.IntegerField()
    ypos = models.IntegerField()
    orientation = models.CharField(max_length=1, choices=ORIENTATION_CHOICES,
            default='H')
    date_added = models.DateTimeField(auto_now_add=True)
    last_modified = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return "%s -- %s (%d, %d)" % \
            (self.view, self.machine, self.xpos, self.ypos)

    class Meta:
        app_label = "Viewer"

        unique_together = (
            ('machine', 'view')
        )

<|endoftext|>


<commit_before>import re
import sys
import parser

d={}
#  d is the dictionary of unittest changes, keyed to the old name
#  used by unittest.
#  d[old][0] is the new replacement function.
#  d[old][1] is the operator you will substitute, or '' if there is none.
#  d[old][2] is the possible number of arguments to the unittest
#  function.

# Old Unittest Name             new name         operator  # of args
d['assertRaises']           = ('raises',               '', ['Any'])
d['fail']                   = ('raise AssertionError', '', [0,1])
d['assert_']                = ('assert',               '', [1,2])
d['failIf']                 = ('assert not',           '', [1,2])
d['assertEqual']            = ('assert',            ' ==', [2,3])
d['failIfEqual']            = ('assert not',        ' ==', [2,3])
d['assertIn']               = ('assert',            ' in', [2,3])
d['assertNotIn']            = ('assert',            ' not in', [2,3])
d['assertNotEqual']         = ('assert',            ' !=', [2,3])
d['failUnlessEqual']        = ('assert',            ' ==', [2,3])
d['assertAlmostEqual']      = ('assert round',      ' ==', [2,3,4])
d['failIfAlmostEqual']      = ('assert not round',  ' ==', [2,3,4])
d['assertNotAlmostEqual']   = ('assert round',      ' !=', [2,3,4])
d['failUnlessAlmostEquals'] = ('assert round',      ' ==', [2,3,4])

#  the list of synonyms
d['failUnlessRaises']      = d['assertRaises']
d['failUnless']            = d['assert_']
d['assertEquals']          = d['assertEqual']
d['assertNotEquals']       = d['assertNotEqual']
d['assertAlmostEquals']    = d['assertAlmostEqual']
d['assertNotAlmostEquals'] = d['assertNotAlmostEqual']

# set up the regular expressions we will need
leading_spaces = re.compile(r'^(\s*)') # this never fails

pat = ''
for k in d.keys():  # this complicated pattern to match all unittests
    pat += '|' + r'^(\s*)' + 'self.' + k + r'\(' # \tself.whatever(

old_names = re.compile(pat[1:])
linesep='\n'        # nobody will really try to convert files not read
                    # in text mode, will they?

def blocksplitter(fp):
    '''split a file into blocks that are headed by functions to rename'''

    blocklist = []
    blockstring = ''

    for line in fp:
        interesting = old_names.match(line)
        if interesting :
            if blockstring:
                blocklist.append(blockstring)
                blockstring = line # reset the block
        else:
            blockstring += line

    blocklist.append(blockstring)
    return blocklist

def rewrite_utest(block):
    '''rewrite every block to use the new utest functions'''

    '''returns the rewritten unittest, unless it ran into problems,
       in which case it just returns the block unchanged.
    '''
    utest = old_names.match(block)

    if not utest:
        return block

    old = utest.group(0).lstrip()[5:-1] # the name we want to replace
    new = d[old][0] # the name of the replacement function
    op  = d[old][1] # the operator you will use , or '' if there is none.
    possible_args = d[old][2]  # a list of the number of arguments the
                               # unittest function could possibly take.

    if possible_args == ['Any']: # just rename assertRaises & friends
        return re.sub('self.'+old, new, block)

    message_pos = possible_args[-1]
    # the remaining unittests can have an optional message to print
    # when they fail.  It is always the last argument to the function.

    try:
        indent, argl, trailer = decompose_unittest(old, block)

    except SyntaxError: # but we couldn't parse it!
        return block

    argnum = len(argl)
    if argnum not in possible_args:
        # sanity check - this one isn't real either
        return block

    elif argnum == message_pos:
        message = argl[-1]
        argl = argl[:-1]
    else:
        message = None

    if argnum is 0 or (argnum is 1 and argnum is message_pos): #unittest fail()
        string = ''
        if message:
            message = ' ' + message

    elif message_pos is 4:  # assertAlmostEqual & friends
        try:
            pos = argl[2].lstrip()
        except IndexError:
            pos = '7' # default if none is specified
        string = '(%s -%s, %s)%s 0' % (argl[0], argl[1], pos, op )

    else: # assert_, assertEquals and all the rest
        string = ' ' + op.join(argl)

    if message:
        string = string + ',' + message

    return indent + new + string + trailer

def decompose_unittest(old, block):
    '''decompose the block into its component parts'''

    ''' returns indent, arglist, trailer
        indent -- the indentation
        arglist -- the arguments to the unittest function
        trailer -- any extra junk after the closing paren, such as #commment
    '''

    indent = re.match(r'(\s*)', block).group()
    pat = re.search('self.' + old + r'\(', block)

    args, trailer = get_expr(block[pat.end():], ')')
    arglist = break_args(args, [])

    if arglist == ['']: # there weren't any
        return indent, [], trailer

    for i in range(len(arglist)):
        try:
            parser.expr(arglist[i].lstrip('\t '))
        except SyntaxError:
            if i == 0:
                arglist[i] = '(' + arglist[i] + ')'
            else:
                arglist[i] = ' (' + arglist[i] + ')'

    return indent, arglist, trailer

def break_args(args, arglist):
    '''recursively break a string into a list of arguments'''
    try:
        first, rest = get_expr(args, ',')
        if not rest:
            return arglist + [first]
        else:
            return [first] + break_args(rest, arglist)
    except SyntaxError:
        return arglist + [args]

def get_expr(s, char):
    '''split a string into an expression, and the rest of the string'''

    pos=[]
    for i in range(len(s)):
        if s[i] == char:
            pos.append(i)
    if pos == []:
        raise SyntaxError # we didn't find the expected char.  Ick.

    for p in pos:
        # make the python parser do the hard work of deciding which comma
        # splits the string into two expressions
        try:
            parser.expr('(' + s[:p] + ')')
            return s[:p], s[p+1:]
        except SyntaxError: # It's not an expression yet
            pass
    raise SyntaxError       # We never found anything that worked.

if __name__ == '__main__':

    import sys
    import py

    usage = "usage: %prog [-s [filename ...] | [-i | -c filename ...]]"
    optparser = py.compat.optparse.OptionParser(usage)

    def select_output (option, opt, value, optparser, **kw):
        if hasattr(optparser, 'output'):
            optparser.error(
                'Cannot combine -s -i and -c options. Use one only.')
        else:
            optparser.output = kw['output']

    optparser.add_option("-s", "--stdout", action="callback",
                         callback=select_output,
                         callback_kwargs={'output':'stdout'},
                         help="send your output to stdout")

    optparser.add_option("-i", "--inplace", action="callback",
                         callback=select_output,
                         callback_kwargs={'output':'inplace'},
                         help="overwrite files in place")

    optparser.add_option("-c", "--copy", action="callback",
                         callback=select_output,
                         callback_kwargs={'output':'copy'},
                         help="copy files ... fn.py --> fn_cp.py")

    options, args = optparser.parse_args()

    output = getattr(optparser, 'output', 'stdout')

    if output in ['inplace', 'copy'] and not args:
        optparser.error(
                '-i and -c option  require at least one filename')

    if not args:
        s = ''
        for block in blocksplitter(sys.stdin.read()):
            s += rewrite_utest(block)
        sys.stdout.write(s)

    else:
        for infilename in args: # no error checking to see if we can open, etc.
            infile = file(infilename)
            s = ''
            for block in blocksplitter(infile):
                s += rewrite_utest(block)
            if output == 'inplace':
                outfile = file(infilename, 'w+')
            elif output == 'copy': # yes, just go clobber any existing .cp
                outfile = file (infilename[:-3]+ '_cp.py', 'w+')
            else:
                outfile = sys.stdout

            outfile.write(s)

<commit_msg>[svn r50645] Fix for "utestconvert.py < input".<commit_after>import re
import sys
import parser

d={}
#  d is the dictionary of unittest changes, keyed to the old name
#  used by unittest.
#  d[old][0] is the new replacement function.
#  d[old][1] is the operator you will substitute, or '' if there is none.
#  d[old][2] is the possible number of arguments to the unittest
#  function.

# Old Unittest Name             new name         operator  # of args
d['assertRaises']           = ('raises',               '', ['Any'])
d['fail']                   = ('raise AssertionError', '', [0,1])
d['assert_']                = ('assert',               '', [1,2])
d['failIf']                 = ('assert not',           '', [1,2])
d['assertEqual']            = ('assert',            ' ==', [2,3])
d['failIfEqual']            = ('assert not',        ' ==', [2,3])
d['assertIn']               = ('assert',            ' in', [2,3])
d['assertNotIn']            = ('assert',            ' not in', [2,3])
d['assertNotEqual']         = ('assert',            ' !=', [2,3])
d['failUnlessEqual']        = ('assert',            ' ==', [2,3])
d['assertAlmostEqual']      = ('assert round',      ' ==', [2,3,4])
d['failIfAlmostEqual']      = ('assert not round',  ' ==', [2,3,4])
d['assertNotAlmostEqual']   = ('assert round',      ' !=', [2,3,4])
d['failUnlessAlmostEquals'] = ('assert round',      ' ==', [2,3,4])

#  the list of synonyms
d['failUnlessRaises']      = d['assertRaises']
d['failUnless']            = d['assert_']
d['assertEquals']          = d['assertEqual']
d['assertNotEquals']       = d['assertNotEqual']
d['assertAlmostEquals']    = d['assertAlmostEqual']
d['assertNotAlmostEquals'] = d['assertNotAlmostEqual']

# set up the regular expressions we will need
leading_spaces = re.compile(r'^(\s*)') # this never fails

pat = ''
for k in d.keys():  # this complicated pattern to match all unittests
    pat += '|' + r'^(\s*)' + 'self.' + k + r'\(' # \tself.whatever(

old_names = re.compile(pat[1:])
linesep='\n'        # nobody will really try to convert files not read
                    # in text mode, will they?

def blocksplitter(fp):
    '''split a file into blocks that are headed by functions to rename'''

    blocklist = []
    blockstring = ''

    for line in fp:
        interesting = old_names.match(line)
        if interesting :
            if blockstring:
                blocklist.append(blockstring)
                blockstring = line # reset the block
        else:
            blockstring += line

    blocklist.append(blockstring)
    return blocklist

def rewrite_utest(block):
    '''rewrite every block to use the new utest functions'''

    '''returns the rewritten unittest, unless it ran into problems,
       in which case it just returns the block unchanged.
    '''
    utest = old_names.match(block)

    if not utest:
        return block

    old = utest.group(0).lstrip()[5:-1] # the name we want to replace
    new = d[old][0] # the name of the replacement function
    op  = d[old][1] # the operator you will use , or '' if there is none.
    possible_args = d[old][2]  # a list of the number of arguments the
                               # unittest function could possibly take.

    if possible_args == ['Any']: # just rename assertRaises & friends
        return re.sub('self.'+old, new, block)

    message_pos = possible_args[-1]
    # the remaining unittests can have an optional message to print
    # when they fail.  It is always the last argument to the function.

    try:
        indent, argl, trailer = decompose_unittest(old, block)

    except SyntaxError: # but we couldn't parse it!
        return block

    argnum = len(argl)
    if argnum not in possible_args:
        # sanity check - this one isn't real either
        return block

    elif argnum == message_pos:
        message = argl[-1]
        argl = argl[:-1]
    else:
        message = None

    if argnum is 0 or (argnum is 1 and argnum is message_pos): #unittest fail()
        string = ''
        if message:
            message = ' ' + message

    elif message_pos is 4:  # assertAlmostEqual & friends
        try:
            pos = argl[2].lstrip()
        except IndexError:
            pos = '7' # default if none is specified
        string = '(%s -%s, %s)%s 0' % (argl[0], argl[1], pos, op )

    else: # assert_, assertEquals and all the rest
        string = ' ' + op.join(argl)

    if message:
        string = string + ',' + message

    return indent + new + string + trailer

def decompose_unittest(old, block):
    '''decompose the block into its component parts'''

    ''' returns indent, arglist, trailer
        indent -- the indentation
        arglist -- the arguments to the unittest function
        trailer -- any extra junk after the closing paren, such as #commment
    '''

    indent = re.match(r'(\s*)', block).group()
    pat = re.search('self.' + old + r'\(', block)

    args, trailer = get_expr(block[pat.end():], ')')
    arglist = break_args(args, [])

    if arglist == ['']: # there weren't any
        return indent, [], trailer

    for i in range(len(arglist)):
        try:
            parser.expr(arglist[i].lstrip('\t '))
        except SyntaxError:
            if i == 0:
                arglist[i] = '(' + arglist[i] + ')'
            else:
                arglist[i] = ' (' + arglist[i] + ')'

    return indent, arglist, trailer

def break_args(args, arglist):
    '''recursively break a string into a list of arguments'''
    try:
        first, rest = get_expr(args, ',')
        if not rest:
            return arglist + [first]
        else:
            return [first] + break_args(rest, arglist)
    except SyntaxError:
        return arglist + [args]

def get_expr(s, char):
    '''split a string into an expression, and the rest of the string'''

    pos=[]
    for i in range(len(s)):
        if s[i] == char:
            pos.append(i)
    if pos == []:
        raise SyntaxError # we didn't find the expected char.  Ick.

    for p in pos:
        # make the python parser do the hard work of deciding which comma
        # splits the string into two expressions
        try:
            parser.expr('(' + s[:p] + ')')
            return s[:p], s[p+1:]
        except SyntaxError: # It's not an expression yet
            pass
    raise SyntaxError       # We never found anything that worked.

if __name__ == '__main__':

    import sys
    import py

    usage = "usage: %prog [-s [filename ...] | [-i | -c filename ...]]"
    optparser = py.compat.optparse.OptionParser(usage)

    def select_output (option, opt, value, optparser, **kw):
        if hasattr(optparser, 'output'):
            optparser.error(
                'Cannot combine -s -i and -c options. Use one only.')
        else:
            optparser.output = kw['output']

    optparser.add_option("-s", "--stdout", action="callback",
                         callback=select_output,
                         callback_kwargs={'output':'stdout'},
                         help="send your output to stdout")

    optparser.add_option("-i", "--inplace", action="callback",
                         callback=select_output,
                         callback_kwargs={'output':'inplace'},
                         help="overwrite files in place")

    optparser.add_option("-c", "--copy", action="callback",
                         callback=select_output,
                         callback_kwargs={'output':'copy'},
                         help="copy files ... fn.py --> fn_cp.py")

    options, args = optparser.parse_args()

    output = getattr(optparser, 'output', 'stdout')

    if output in ['inplace', 'copy'] and not args:
        optparser.error(
                '-i and -c option  require at least one filename')

    if not args:
        s = ''
        for block in blocksplitter(sys.stdin):
            s += rewrite_utest(block)
        sys.stdout.write(s)

    else:
        for infilename in args: # no error checking to see if we can open, etc.
            infile = file(infilename)
            s = ''
            for block in blocksplitter(infile):
                s += rewrite_utest(block)
            if output == 'inplace':
                outfile = file(infilename, 'w+')
            elif output == 'copy': # yes, just go clobber any existing .cp
                outfile = file (infilename[:-3]+ '_cp.py', 'w+')
            else:
                outfile = sys.stdout

            outfile.write(s)

<|endoftext|>


<commit_before>import argparse
import logging
import os
import sys
import time

import six
from verlib import NormalizedVersion

from . import utils
from .exceptions import (
    GitCommandError,
    JirafsError,
    NotTicketFolderException
)

logger = logging.getLogger(__name__)

def main():
    if sys.version_info < (2, 7):
        raise RuntimeError(
            "Jirafs requires minimally version 2.7 of Python 2, or "
            "any version of Python 3.  Please upgrade your version of "
            "python before using Jirafs."
        )
    if utils.get_git_version() < NormalizedVersion('1.8'):
        raise RuntimeError(
            "Jirafs requires minimally version 1.8 of Git.  Please "
            "upgrade your version of git before using Jirafs."
        )

    commands = utils.get_installed_commands()

    parser = argparse.ArgumentParser(
        description='Edit Jira issues locally from your filesystem',
        add_help=False,
    )
    parser.add_argument(
        'command',
        nargs=1,
        type=six.text_type,
        choices=commands.keys()
    )
    args, extra = parser.parse_known_args()

    command_name = args.command[0]
    cmd_class = commands[command_name]

    started = time.time()
    logger.debug(
        'Command %s(%s) started',
        command_name,
        extra
    )
    jira = utils.lazy_get_jira()
    try:
        cmd_class.execute_command(
            extra, jira=jira, path=os.getcwd(), command_name=command_name
        )
    except GitCommandError as e:
        print(
            "Error (code: %s) while running git command." % (
                e.returncode
            )
        )
        print("")
        print("Command:")
        print("    %s" % e.command)
        print("")
        print("Output:")
        for line in e.output.decode('utf8').split('\n'):
            print("    %s" % line)
        print("")
        sys.exit(1)
    except NotTicketFolderException:
        if not getattr(cmd_class, 'TRY_SUBFOLDERS', False):
            print(
                "The command '%s' must be ran from within an issue folder." % (
                    command_name
                )
            )
            sys.exit(1)
        count_runs = 0
        for folder in os.listdir(os.getcwd()):
            try:
                cmd_class.execute_command(
                    extra,
                    jira=jira,
                    path=os.path.join(
                        os.getcwd(),
                        folder,
                    ),
                )
                count_runs += 1
            except NotTicketFolderException:
                pass
        if count_runs == 0:
            print(
                "The command '%s' must be ran from within an issue folder "
                "or from within a folder containing issue folders." % (
                    command_name
                )
            )
            sys.exit(1)
    except JirafsError as e:
        print("Jirafs encountered an error processing your request: %s" % e)

    logger.debug(
        'Command %s(%s) finished in %s seconds',
        command_name,
        extra,
        (time.time() - started)
    )
<commit_msg>Pass command_name to executor when running for subfolders, too.<commit_after>import argparse
import logging
import os
import sys
import time

import six
from verlib import NormalizedVersion

from . import utils
from .exceptions import (
    GitCommandError,
    JirafsError,
    NotTicketFolderException
)

logger = logging.getLogger(__name__)

def main():
    if sys.version_info < (2, 7):
        raise RuntimeError(
            "Jirafs requires minimally version 2.7 of Python 2, or "
            "any version of Python 3.  Please upgrade your version of "
            "python before using Jirafs."
        )
    if utils.get_git_version() < NormalizedVersion('1.8'):
        raise RuntimeError(
            "Jirafs requires minimally version 1.8 of Git.  Please "
            "upgrade your version of git before using Jirafs."
        )

    commands = utils.get_installed_commands()

    parser = argparse.ArgumentParser(
        description='Edit Jira issues locally from your filesystem',
        add_help=False,
    )
    parser.add_argument(
        'command',
        nargs=1,
        type=six.text_type,
        choices=commands.keys()
    )
    args, extra = parser.parse_known_args()

    command_name = args.command[0]
    cmd_class = commands[command_name]

    started = time.time()
    logger.debug(
        'Command %s(%s) started',
        command_name,
        extra
    )
    jira = utils.lazy_get_jira()
    try:
        cmd_class.execute_command(
            extra, jira=jira, path=os.getcwd(), command_name=command_name
        )
    except GitCommandError as e:
        print(
            "Error (code: %s) while running git command." % (
                e.returncode
            )
        )
        print("")
        print("Command:")
        print("    %s" % e.command)
        print("")
        print("Output:")
        for line in e.output.decode('utf8').split('\n'):
            print("    %s" % line)
        print("")
        sys.exit(1)
    except NotTicketFolderException:
        if not getattr(cmd_class, 'TRY_SUBFOLDERS', False):
            print(
                "The command '%s' must be ran from within an issue folder." % (
                    command_name
                )
            )
            sys.exit(1)
        count_runs = 0
        for folder in os.listdir(os.getcwd()):
            try:
                cmd_class.execute_command(
                    extra,
                    jira=jira,
                    path=os.path.join(
                        os.getcwd(),
                        folder,
                    ),
                    command_name=command_name,
                )
                count_runs += 1
            except NotTicketFolderException:
                pass
        if count_runs == 0:
            print(
                "The command '%s' must be ran from within an issue folder "
                "or from within a folder containing issue folders." % (
                    command_name
                )
            )
            sys.exit(1)
    except JirafsError as e:
        print("Jirafs encountered an error processing your request: %s" % e)

    logger.debug(
        'Command %s(%s) finished in %s seconds',
        command_name,
        extra,
        (time.time() - started)
    )
<|endoftext|>


<commit_before><commit_msg>rename time to timer avoid conflict<commit_after><|endoftext|>


<commit_before>"""
Command handler

This module contains the infrastructure for accepting commands on the
command line. The process is as follows:

1) The calling object (caller) inputs a string and triggers the command parsing system.
2) The system checks the state of the caller - loggedin or not
3) If no command string was supplied, we search the merged cmdset for system command CMD_NOINPUT
   and branches to execute that.  --> Finished
4) Cmdsets are gathered from different sources (in order of dropping priority):
           channels - all available channel names are auto-created into a cmdset, to allow
                  for giving the channel name and have the following immediately
                  sent to the channel. The sending is performed by the CMD_CHANNEL
                  system command.
           object cmdsets - all objects at caller's location are scanned for non-empty
                  cmdsets. This includes cmdsets on exits.
           caller - the caller is searched for its own currently active cmdset.
           player - lastly the cmdsets defined on caller.player are added.
5) All the gathered cmdsets (if more than one) are merged into one using the cmdset priority rules.
6) If merged cmdset is empty, raise NoCmdSet exception (this should not happen, at least the
   player should have a default cmdset available at all times). --> Finished
7) The raw input string is parsed using the parser defined by settings.COMMAND_PARSER. It
   uses the available commands from the merged cmdset to know which commands to look for and
   returns one or many matches.
8)   If match list is empty, branch to system command CMD_NOMATCH --> Finished
9)   If match list has more than one element, branch to system command CMD_MULTIMATCH --> Finished
10) A single match was found. If this is a channel-command (i.e. the command name is that of a channel),
    branch to CMD_CHANNEL --> Finished
11) At this point we have found a normal command. We assign useful variables to it that
    will be available to the command coder at run-time.
12) We have a unique cmdobject, primed for use. Call all hooks:
    at_pre_cmd(), cmdobj.parse(), cmdobj.func() and finally at_post_cmd().

"""

from copy import copy
from traceback import format_exc
from twisted.internet.defer import inlineCallbacks, returnValue
from django.conf import settings
from src.comms.channelhandler import CHANNELHANDLER
from src.commands.cmdsethandler import import_cmdset
from src.utils import logger, utils
from src.commands.cmdparser import at_multimatch_cmd

#This switches the command parser to a user-defined one.
# You have to restart the server for this to take effect.
COMMAND_PARSER = utils.mod_import(*settings.COMMAND_PARSER.rsplit('.', 1))

# There are a few system-hardcoded command names. These
# allow for custom behaviour when the command handler hits
# special situations -- it then calls a normal Command
# that you can customize!
# Import these variables and use them rather than trying
# to remember the actual string constants.

CMD_NOINPUT = "__noinput_command"
CMD_NOMATCH = "__nomatch_command"
CMD_MULTIMATCH = "__multimatch_command"
CMD_CHANNEL = "__send_to_channel_command"
# this is the name of the command the engine calls when the player
# connects. It is expected to show the login screen.
CMD_LOGINSTART = "__unloggedin_look_command"

class NoCmdSets(Exception):
    "No cmdsets found. Critical error."
    pass
class ExecSystemCommand(Exception):
    "Run a system command"
    def __init__(self, syscmd, sysarg):
        self.args = (syscmd, sysarg) # needed by exception error handling
        self.syscmd = syscmd
        self.sysarg = sysarg

@inlineCallbacks
def get_and_merge_cmdsets(caller):
    """
    Gather all relevant cmdsets and merge them. Note
    that this is only relevant for logged-in callers.
    """
    # The calling object's cmdset
    try:
        yield caller.at_cmdset_get()
    except Exception:
        logger.log_trace()
    try:
        caller_cmdset = caller.cmdset.current
    except AttributeError:
        caller_cmdset = None

    # Create cmdset for all player's available channels
    channel_cmdset = None
    if not caller_cmdset.no_channels:
        channel_cmdset = yield CHANNELHANDLER.get_cmdset(caller)

    # Gather cmdsets from location, objects in location or carried
    local_objects_cmdsets = [None]
    location = None
    if hasattr(caller, "location"):
        location = caller.location
    if location and not caller_cmdset.no_objs:
        # Gather all cmdsets stored on objects in the room and
        # also in the caller's inventory and the location itself
        local_objlist = yield location.contents_get(exclude=caller.dbobj) + caller.contents + [location]
        for obj in local_objlist:
            try:
                # call hook in case we need to do dynamic changing to cmdset
                yield obj.at_cmdset_get()
            except Exception:
                logger.log_trace()
        local_objects_cmdsets = yield [obj.cmdset.current for obj in local_objlist
                                       if (obj.cmdset.current and obj.locks.check(caller, 'call', no_superuser_bypass=True))]
        for cset in local_objects_cmdsets:
            #This is necessary for object sets, or we won't be able to separate
            #the command sets from each other in a busy room.
            cset.old_duplicates = cset.duplicates
            cset.duplicates = True

    # Player object's commandsets
    try:
        player_cmdset = caller.player.cmdset.current
    except AttributeError:
        player_cmdset = None

    cmdsets = [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
    # weed out all non-found sets
    cmdsets = yield [cmdset for cmdset in cmdsets if cmdset]
    # sort cmdsets after reverse priority (highest prio are merged in last)
    cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)

    if cmdsets:
        # Merge all command sets into one, beginning with the lowest-prio one
        cmdset = cmdsets.pop(0)
        for merging_cmdset in cmdsets:
            #print "<%s(%s,%s)> onto <%s(%s,%s)>" % (merging_cmdset.key, merging_cmdset.priority, merging_cmdset.mergetype,
            #                                        cmdset.key, cmdset.priority, cmdset.mergetype)
            cmdset = yield merging_cmdset + cmdset
    else:
        cmdset = None

    for cset in (cset for cset in local_objects_cmdsets if cset):
        cset.duplicates = cset.old_duplicates

    returnValue(cmdset)

# Main command-handler function

@inlineCallbacks
def cmdhandler(caller, raw_string, testing=False):
    """
    This is the main function to handle any string sent to the engine.

    caller - calling object
    raw_string - the command string given on the command line
    testing - if we should actually execute the command or not.
              if True, the command instance will be returned instead.

    Note that this function returns a deferred!
    """
    try: # catch bugs in cmdhandler itself
        try: # catch special-type commands

            cmdset = yield get_and_merge_cmdsets(caller)
            if not cmdset:
                # this is bad and shouldn't happen.
                raise NoCmdSets

            raw_string = raw_string.strip()
            if not raw_string:
                # Empty input. Test for system command instead.
                syscmd = yield cmdset.get(CMD_NOINPUT)
                sysarg = ""
                raise ExecSystemCommand(syscmd, sysarg)
            # Parse the input string and match to available cmdset.
            # This also checks for permissions, so all commands in match
            # are commands the caller is allowed to call.
            matches = yield COMMAND_PARSER(raw_string, cmdset, caller)
            # Deal with matches
            if not matches:
                # No commands match our entered command
                syscmd = yield cmdset.get(CMD_NOMATCH)
                if syscmd:
                    sysarg = raw_string
                else:
                    sysarg = "Huh? (Type \"help\" for help)"
                raise ExecSystemCommand(syscmd, sysarg)

            if len(matches) > 1:
                # We have a multiple-match
                syscmd = yield cmdset.get(CMD_MULTIMATCH)
                sysarg = "There where multiple matches."
                if syscmd:
                    syscmd.matches = matches
                else:
                    sysarg = yield at_multimatch_cmd(caller, matches)
                raise ExecSystemCommand(syscmd, sysarg)

            # At this point, we have a unique command match.
            match = matches[0]
            cmdname, args, cmd = match[0], match[1], match[2]

            # Check if this is a Channel match.
            if hasattr(cmd, 'is_channel') and cmd.is_channel:
                # even if a user-defined syscmd is not defined, the
                # found cmd is already a system command in its own right.
                syscmd = yield cmdset.get(CMD_CHANNEL)
                if syscmd:
                    # replace system command with custom version
                    cmd = syscmd
                sysarg = "%s:%s" % (cmdname, args)
                raise ExecSystemCommand(cmd, sysarg)

            # A normal command.

            # Assign useful variables to the instance
            cmd.caller = caller
            cmd.cmdstring = cmdname
            cmd.args = args
            cmd.cmdset = cmdset

            if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
                # cmd.obj are automatically made available.
                # we make sure to validate its scripts.
                yield cmd.obj.scripts.validate()

            if testing:
                # only return the command instance
                returnValue(cmd)

            # pre-command hook
            yield cmd.at_pre_cmd()

            # Parse and execute
            yield cmd.parse()
            # (return value is normally None)
            ret = yield cmd.func()

            # post-command hook
            yield cmd.at_post_cmd()

            if cmd.save_for_next:
                # store a reference to this command, possibly
                # accessible by the next command.
                caller.ndb.last_cmd = yield copy(cmd)
            else:
                caller.ndb.last_cmd = None

            # Done! By default, Evennia does not use this return at all
            def callback(r):
                return r
            returnValue(ret).addCallback(r)

        except ExecSystemCommand, exc:
            # Not a normal command: run a system command, if available,
            # or fall back to a return string.
            syscmd = exc.syscmd
            sysarg = exc.sysarg
            if syscmd:
                syscmd.caller = caller
                syscmd.cmdstring = syscmd.key
                syscmd.args = sysarg
                syscmd.cmdset = cmdset

                if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'):
                    # cmd.obj is automatically made available.
                    # we make sure to validate its scripts.
                    syscmd.obj.scripts.validate()

                if testing:
                    # only return the command instance
                    returnValue(syscmd)

                # parse and run the command
                syscmd.parse()
                syscmd.func()
            elif sysarg:
                caller.msg(exc.sysarg)

        except NoCmdSets:
            # Critical error.
            string = "No command sets found! This is a sign of a critical bug.\n"
            string += "The error was logged.\n"
            string += "If logging out/in doesn't solve the problem, try to "
            string += "contact the server admin through some other means "
            string += "for assistance."
            caller.msg(string)
            logger.log_errmsg("No cmdsets found: %s" % caller)

        except Exception:
            # We should not end up here. If we do, it's a programming bug.
            string = "%s\nAbove traceback is from an untrapped error."
            string += " Please file a bug report."
            logger.log_trace(string)
            caller.msg(string % format_exc())

    except Exception:
        # This catches exceptions in cmdhandler exceptions themselves
        string = "%s\nAbove traceback is from a Command handler bug."
        string += " Please contact an admin."
        logger.log_trace(string)
        caller.msg(string % format_exc())

#----------------------------------------------------- end cmdhandler
<commit_msg>Added more yields to cmdhandler, removed unnecessary callback to return.<commit_after>"""
Command handler

This module contains the infrastructure for accepting commands on the
command line. The process is as follows:

1) The calling object (caller) inputs a string and triggers the command parsing system.
2) The system checks the state of the caller - loggedin or not
3) If no command string was supplied, we search the merged cmdset for system command CMD_NOINPUT
   and branches to execute that.  --> Finished
4) Cmdsets are gathered from different sources (in order of dropping priority):
           channels - all available channel names are auto-created into a cmdset, to allow
                  for giving the channel name and have the following immediately
                  sent to the channel. The sending is performed by the CMD_CHANNEL
                  system command.
           object cmdsets - all objects at caller's location are scanned for non-empty
                  cmdsets. This includes cmdsets on exits.
           caller - the caller is searched for its own currently active cmdset.
           player - lastly the cmdsets defined on caller.player are added.
5) All the gathered cmdsets (if more than one) are merged into one using the cmdset priority rules.
6) If merged cmdset is empty, raise NoCmdSet exception (this should not happen, at least the
   player should have a default cmdset available at all times). --> Finished
7) The raw input string is parsed using the parser defined by settings.COMMAND_PARSER. It
   uses the available commands from the merged cmdset to know which commands to look for and
   returns one or many matches.
8)   If match list is empty, branch to system command CMD_NOMATCH --> Finished
9)   If match list has more than one element, branch to system command CMD_MULTIMATCH --> Finished
10) A single match was found. If this is a channel-command (i.e. the command name is that of a channel),
    branch to CMD_CHANNEL --> Finished
11) At this point we have found a normal command. We assign useful variables to it that
    will be available to the command coder at run-time.
12) We have a unique cmdobject, primed for use. Call all hooks:
    at_pre_cmd(), cmdobj.parse(), cmdobj.func() and finally at_post_cmd().

"""

from copy import copy
from traceback import format_exc
from twisted.internet.defer import inlineCallbacks, returnValue
from django.conf import settings
from src.comms.channelhandler import CHANNELHANDLER
from src.commands.cmdsethandler import import_cmdset
from src.utils import logger, utils
from src.commands.cmdparser import at_multimatch_cmd

#This switches the command parser to a user-defined one.
# You have to restart the server for this to take effect.
COMMAND_PARSER = utils.mod_import(*settings.COMMAND_PARSER.rsplit('.', 1))

# There are a few system-hardcoded command names. These
# allow for custom behaviour when the command handler hits
# special situations -- it then calls a normal Command
# that you can customize!
# Import these variables and use them rather than trying
# to remember the actual string constants.

CMD_NOINPUT = "__noinput_command"
CMD_NOMATCH = "__nomatch_command"
CMD_MULTIMATCH = "__multimatch_command"
CMD_CHANNEL = "__send_to_channel_command"
# this is the name of the command the engine calls when the player
# connects. It is expected to show the login screen.
CMD_LOGINSTART = "__unloggedin_look_command"

class NoCmdSets(Exception):
    "No cmdsets found. Critical error."
    pass
class ExecSystemCommand(Exception):
    "Run a system command"
    def __init__(self, syscmd, sysarg):
        self.args = (syscmd, sysarg) # needed by exception error handling
        self.syscmd = syscmd
        self.sysarg = sysarg

@inlineCallbacks
def get_and_merge_cmdsets(caller):
    """
    Gather all relevant cmdsets and merge them. Note
    that this is only relevant for logged-in callers.
    """
    # The calling object's cmdset
    try:
        yield caller.at_cmdset_get()
    except Exception:
        logger.log_trace()
    try:
        caller_cmdset = caller.cmdset.current
    except AttributeError:
        caller_cmdset = None

    # Create cmdset for all player's available channels
    channel_cmdset = None
    if not caller_cmdset.no_channels:
        channel_cmdset = yield CHANNELHANDLER.get_cmdset(caller)

    # Gather cmdsets from location, objects in location or carried
    local_objects_cmdsets = [None]
    location = None
    if hasattr(caller, "location"):
        location = caller.location
    if location and not caller_cmdset.no_objs:
        # Gather all cmdsets stored on objects in the room and
        # also in the caller's inventory and the location itself
        local_objlist = yield location.contents_get(exclude=caller.dbobj) + caller.contents + [location]
        for obj in local_objlist:
            try:
                # call hook in case we need to do dynamic changing to cmdset
                yield obj.at_cmdset_get()
            except Exception:
                logger.log_trace()
        local_objects_cmdsets = yield [obj.cmdset.current for obj in local_objlist
                                       if (obj.cmdset.current and obj.locks.check(caller, 'call', no_superuser_bypass=True))]
        for cset in local_objects_cmdsets:
            #This is necessary for object sets, or we won't be able to separate
            #the command sets from each other in a busy room.
            cset.old_duplicates = cset.duplicates
            cset.duplicates = True

    # Player object's commandsets
    try:
        player_cmdset = caller.player.cmdset.current
    except AttributeError:
        player_cmdset = None

    cmdsets = [caller_cmdset] + [player_cmdset] + [channel_cmdset] + local_objects_cmdsets
    # weed out all non-found sets
    cmdsets = yield [cmdset for cmdset in cmdsets if cmdset]
    # sort cmdsets after reverse priority (highest prio are merged in last)
    cmdsets = yield sorted(cmdsets, key=lambda x: x.priority)

    if cmdsets:
        # Merge all command sets into one, beginning with the lowest-prio one
        cmdset = cmdsets.pop(0)
        for merging_cmdset in cmdsets:
            #print "<%s(%s,%s)> onto <%s(%s,%s)>" % (merging_cmdset.key, merging_cmdset.priority, merging_cmdset.mergetype,
            #                                        cmdset.key, cmdset.priority, cmdset.mergetype)
            cmdset = yield merging_cmdset + cmdset
    else:
        cmdset = None

    for cset in (cset for cset in local_objects_cmdsets if cset):
        cset.duplicates = cset.old_duplicates

    returnValue(cmdset)

# Main command-handler function

@inlineCallbacks
def cmdhandler(caller, raw_string, testing=False):
    """
    This is the main function to handle any string sent to the engine.

    caller - calling object
    raw_string - the command string given on the command line
    testing - if we should actually execute the command or not.
              if True, the command instance will be returned instead.

    Note that this function returns a deferred!
    """
    try: # catch bugs in cmdhandler itself
        try: # catch special-type commands

            cmdset = yield get_and_merge_cmdsets(caller)
            if not cmdset:
                # this is bad and shouldn't happen.
                raise NoCmdSets

            raw_string = raw_string.strip()
            if not raw_string:
                # Empty input. Test for system command instead.
                syscmd = yield cmdset.get(CMD_NOINPUT)
                sysarg = ""
                raise ExecSystemCommand(syscmd, sysarg)
            # Parse the input string and match to available cmdset.
            # This also checks for permissions, so all commands in match
            # are commands the caller is allowed to call.
            matches = yield COMMAND_PARSER(raw_string, cmdset, caller)
            # Deal with matches
            if not matches:
                # No commands match our entered command
                syscmd = yield cmdset.get(CMD_NOMATCH)
                if syscmd:
                    sysarg = raw_string
                else:
                    sysarg = "Huh? (Type \"help\" for help)"
                raise ExecSystemCommand(syscmd, sysarg)

            if len(matches) > 1:
                # We have a multiple-match
                syscmd = yield cmdset.get(CMD_MULTIMATCH)
                sysarg = "There where multiple matches."
                if syscmd:
                    syscmd.matches = matches
                else:
                    sysarg = yield at_multimatch_cmd(caller, matches)
                raise ExecSystemCommand(syscmd, sysarg)

            # At this point, we have a unique command match.
            match = matches[0]
            cmdname, args, cmd = match[0], match[1], match[2]

            # Check if this is a Channel match.
            if hasattr(cmd, 'is_channel') and cmd.is_channel:
                # even if a user-defined syscmd is not defined, the
                # found cmd is already a system command in its own right.
                syscmd = yield cmdset.get(CMD_CHANNEL)
                if syscmd:
                    # replace system command with custom version
                    cmd = syscmd
                sysarg = "%s:%s" % (cmdname, args)
                raise ExecSystemCommand(cmd, sysarg)

            # A normal command.

            # Assign useful variables to the instance
            cmd.caller = caller
            cmd.cmdstring = cmdname
            cmd.args = args
            cmd.cmdset = cmdset

            if hasattr(cmd, 'obj') and hasattr(cmd.obj, 'scripts'):
                # cmd.obj are automatically made available.
                # we make sure to validate its scripts.
                yield cmd.obj.scripts.validate()

            if testing:
                # only return the command instance
                returnValue(cmd)

            # pre-command hook
            yield cmd.at_pre_cmd()

            # Parse and execute
            yield cmd.parse()
            # (return value is normally None)
            ret = yield cmd.func()

            # post-command hook
            yield cmd.at_post_cmd()

            if cmd.save_for_next:
                # store a reference to this command, possibly
                # accessible by the next command.
                caller.ndb.last_cmd = yield copy(cmd)
            else:
                caller.ndb.last_cmd = None

            # Done! This returns a deferred. By default, Evennia does
            # not use this at all.
            returnValue(ret)

        except ExecSystemCommand, exc:
            # Not a normal command: run a system command, if available,
            # or fall back to a return string.
            syscmd = exc.syscmd
            sysarg = exc.sysarg
            if syscmd:
                syscmd.caller = caller
                syscmd.cmdstring = syscmd.key
                syscmd.args = sysarg
                syscmd.cmdset = cmdset

                if hasattr(syscmd, 'obj') and hasattr(syscmd.obj, 'scripts'):
                    # cmd.obj is automatically made available.
                    # we make sure to validate its scripts.
                    yield syscmd.obj.scripts.validate()

                if testing:
                    # only return the command instance
                    returnValue(syscmd)

                # parse and run the command
                yield syscmd.parse()
                yield syscmd.func()
            elif sysarg:
                # return system arg
                caller.msg(exc.sysarg)

        except NoCmdSets:
            # Critical error.
            string = "No command sets found! This is a sign of a critical bug.\n"
            string += "The error was logged.\n"
            string += "If logging out/in doesn't solve the problem, try to "
            string += "contact the server admin through some other means "
            string += "for assistance."
            caller.msg(string)
            logger.log_errmsg("No cmdsets found: %s" % caller)

        except Exception:
            # We should not end up here. If we do, it's a programming bug.
            string = "%s\nAbove traceback is from an untrapped error."
            string += " Please file a bug report."
            logger.log_trace(string)
            caller.msg(string % format_exc())

    except Exception:
        # This catches exceptions in cmdhandler exceptions themselves
        string = "%s\nAbove traceback is from a Command handler bug."
        string += " Please contact an admin and/or file a bug report."
        logger.log_trace(string)
        caller.msg(string % format_exc())

#----------------------------------------------------- end cmdhandler
<|endoftext|>


<commit_before>import matplotlib.pyplot as plt
import numpy as np
from VanillaRNN import*
from Tools import*

def __main__():
    K, eta, H_size = 10, 0.9, 100

    print('Dataset creation')
    #Create dictionary
    dictionary, train, valid, test = build_Dictionary('Dataset.txt')

    print('RNN initialization')
    #Initialize RNN
    myRnn = MyRNN(dictionary, train, valid, test, H_size, eta)

    print('Train the RNN')
    #Train the RNN
    lossTrain, lossVal = myRnn.training_step(K)

    print('Test the RNN')
    #Test the RNN
    lossTest = myRnn.test_step()

    loss = ''
    for s in lossTrain:
        loss += str(s) + ', '
    file = open('lossTrain.txt', 'w')
    file.write(loss)
    file.close()

    loss = ''
    for s in lossVal:
        loss += str(s) + ', '
    file = open('lossVal.txt', 'w')
    file.write(loss)
    file.close()
    print('Loss value of the test set: ', lossTest)

    #t = list(range(10))
    plt.plot([range(len(lossTrain))], lossTrain, 'ro', [range(len(lossVal))], lossVal, 'g^')
    plt.xlabel('time')
    plt.ylabel('loss value')
    plt.title('Loss function computation')
    plt.grid(True)
    #plt.savefig("test.png")
    plt.show()

    '''
    for i in range(K):
        print('Epoch ', i, ':')
        myRnn.fwdRnn()
        Vnew, Unew, Wnew = myRnn.bwRnn()
        # V = myRnn.V
        myRnn.V, myRnn.U, myRnn.W = Vnew, Unew, Wnew
        # print('Vecchio valore di V: ', V)
        # print('Nuovo valore di V: ', (myRnn.V == Vnew))
        # print('Valore di O: ', myRnn.O.sum())
        loss_val += [myRnn.lossFunction(myRnn.Y, myRnn.O, myRnn.N)]
        myRnn.S = np.zeros((myRnn.N, myRnn.T, myRnn.H))
        myRnn.O = np.zeros((myRnn.N, myRnn.T, myRnn.D))
    '''
__main__()    <commit_msg>code improvement<commit_after><|endoftext|>


<commit_before>import re

import feedparser
from django.conf import settings
from django.core.cache import cache

def get_news_cached(base_url):
    cache_key = 'news_cache_key'
    news = cache.get(cache_key)
    if not news:
        news = get_news(base_url)
        cache.set(cache_key, news, settings.NEWS_FEED_CACHE_TIMEOUT)
    return news

def get_news(base_url):
    img_re = re.compile(r'<img.*?src=["\']+(.*?)["\']+/>')
    slug_re = re.compile(r'([\w-]+$)')
    entries = get_news_feeds()
    for entity in entries:
        img_search = img_re.search(entity.description)
        try:
            entity.image = img_search.group(1)
            entity.parsed_description = img_re.sub('', entity.description)
        except AttributeError:
            entity.parsed_description = entity.description

        try:
            entity.slug = slug_re.search(entity.link).group(1)
            entity.real_link = base_url + entity.slug if base_url and entity.slug else entity.link
        except AttributeError:
            entity.slug = None
            entity.real_link = entity.link

        if not hasattr(entity, 'image') or not entity.image:
            entity.is_default_image = True
            entity.image = settings.NEWS_FEED_DEFAULT_IMAGE

    return entries

def get_news_feeds():
    feed = feedparser.parse(settings.NEWS_FEED_URL)
    return feed.entries
<commit_msg>Convert image url to use https<commit_after>import re

import feedparser
from django.conf import settings
from django.core.cache import cache

def convert_http_to_https(url):
    url = url.replace("http://", "https://") if url and url.startswith('http://') else url
    return url

def get_news_cached(base_url):
    cache_key = 'news_cache_key'
    news = cache.get(cache_key)
    if not news:
        news = get_news(base_url)
        cache.set(cache_key, news, settings.NEWS_FEED_CACHE_TIMEOUT)
    return news

def get_news(base_url):
    img_re = re.compile(r'<img.*?src=["\']+(.*?)["\']+/>')
    slug_re = re.compile(r'([\w-]+$)')
    entries = get_news_feeds()
    for entity in entries:
        img_search = img_re.search(entity.description)
        try:
            entity.image = convert_http_to_https(img_search.group(1))
            entity.parsed_description = img_re.sub('', entity.description)
        except AttributeError:
            entity.parsed_description = entity.description

        try:
            entity.slug = slug_re.search(entity.link).group(1)
            entity.real_link = base_url + entity.slug if base_url and entity.slug else entity.link
        except AttributeError:
            entity.slug = None
            entity.real_link = entity.link

        if not hasattr(entity, 'image') or not entity.image:
            entity.is_default_image = True
            entity.image = settings.NEWS_FEED_DEFAULT_IMAGE

    return entries

def get_news_feeds():
    feed = feedparser.parse(settings.NEWS_FEED_URL)
    return feed.entries
<|endoftext|>


<commit_before>import py
import pytest
from fake_filesystem_unittest import _Patcher

_Patcher.SKIPMODULES.add(py)  # Ignore pytest components when faking filesystem

@pytest.yield_fixture
def fs():
    """ Fake filesystem. """
    patcher = _Patcher()
    patcher.setUp()
    yield
    patcher.tearDown()
<commit_msg>Change _Patcher to Patcher in conftest.py<commit_after>import py
import pytest
from pyfakefs.fake_filesystem_unittest import Patcher

Patcher.SKIPMODULES.add(py)  # Ignore pytest components when faking filesystem

@pytest.yield_fixture
def fs():
    """ Fake filesystem. """
    patcher = Patcher()
    patcher.setUp()
    yield
    patcher.tearDown()
<|endoftext|>