<commit_before>import os
_mrtrix_bin_path = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(os.path.abspath(__file__))), os.pardir, os.pardir, 'bin'))
# Remember to remove the '.exe' from Windows binary executables
_mrtrix_exe_list = [ os.path.splitext(name)[0] for name in os.listdir(_mrtrix_bin_path) ]

_processes = [ ]

def command(cmd, exitOnError=True):

  import inspect, itertools, os, shlex, subprocess, sys, tempfile
  from distutils.spawn import find_executable
  from mrtrix3 import app

  global _mrtrix_exe_list

  # Vectorise the command string, preserving anything encased within quotation marks
  cmdsplit = shlex.split(cmd)

  if app._lastFile:
    # Check to see if the last file produced in the previous script execution is
    #   intended to be produced by this command; if it is, this will be the last
    #   command that gets skipped by the -continue option
    # It's possible that the file might be defined in a '--option=XXX' style argument
    #   It's also possible that the filename in the command string has the file extension omitted
    for entry in cmdsplit:
      if entry.startswith('--') and '=' in entry:
        cmdtotest = entry.split('=')[1]
      else:
        cmdtotest = entry
      filetotest = [ app._lastFile, os.path.splitext(app._lastFile)[0] ]
      if cmdtotest in filetotest:
        app.debug('Detected last file \'' + app._lastFile + '\' in command \'' + cmd + '\'; this is the last run.command() / run.function() call that will be skipped')
        app._lastFile = ''
        break
    if app._verbosity:
      sys.stderr.write(app.colourExec + 'Skipping command:' + app.colourClear + ' ' + cmd + '\n')
      sys.stderr.flush()
    return

  # This splits the command string based on the piping character '|', such that each
  #   individual executable (along with its arguments) appears as its own list
  # Note that for Pyton2 support, it is necessary to convert itertools() output from
  #   a generator to a list before it is passed to filter()
  cmdstack = [ list(g) for k, g in filter(lambda t : t[0], ((k, list(g)) for k, g in itertools.groupby(cmdsplit, lambda s : s is not '|') ) ) ]

  for line in cmdstack:
    is_mrtrix_exe = line[0] in _mrtrix_exe_list
    if is_mrtrix_exe:
      line[0] = versionMatch(line[0])
      if app._nthreads is not None:
        line.extend( [ '-nthreads', str(app._nthreads) ] )
      # Get MRtrix3 binaries to output additional INFO-level information if running in debug mode
      if app._verbosity == 3:
        line.append('-info')
      elif not app._verbosity:
        line.append('-quiet')
    else:
      line[0] = exeName(line[0])
    shebang = _shebang(line[0])
    if len(shebang):
      if not is_mrtrix_exe:
        # If a shebang is found, and this call is therefore invoking an
        #   interpreter, can't rely on the interpreter finding the script
        #   from PATH; need to find the full path ourselves.
        line[0] = find_executable(line[0])
      for item in reversed(shebang):
        line.insert(0, item)

  if app._verbosity:
    sys.stderr.write(app.colourExec + 'Command:' + app.colourClear + '  ' + cmd + '\n')
    sys.stderr.flush()

  app.debug('To execute: ' + str(cmdstack))

  # Construct temporary text files for holding stdout / stderr contents when appropriate
  #   (One entry per process; each is a tuple containing two entries, each of which is either a
  #   file-like object, or None)
  tempfiles = [ ]

  # Execute all processes
  _processes = [ ]
  for index, command in enumerate(cmdstack):
    file_out = None
    file_err = None
    # If there's at least one command prior to this, need to receive the stdout from the prior command
    #   at the stdin of this command; otherwise, nothing to receive
    if index > 0:
      handle_in = _processes[index-1].stdout
    else:
      handle_in = None
    # If this is not the last command, then stdout needs to be piped to the next command;
    #   otherwise, write stdout to a temporary file so that the contents can be read later
    if index < len(cmdstack)-1:
      handle_out = subprocess.PIPE
    else:
      file_out = tempfile.TemporaryFile()
      handle_out = file_out.fileno()
    # If we're in debug / info mode, the contents of stderr will be read and printed to the terminal
    #   as the command progresses, hence this needs to go to a pipe; otherwise, write it to a temporary
    #   file so that the contents can be read later
    if app._verbosity > 1:
      handle_err = subprocess.PIPE
    else:
      file_err = tempfile.TemporaryFile()
      handle_err = file_err.fileno()
    # Set off the processes
    try:
      process = subprocess.Popen (command, stdin=handle_in, stdout=handle_out, stderr=handle_err)
      _processes.append(process)
      tempfiles.append( ( file_out, file_err ) )
    # FileNotFoundError not defined in Python 2.7
    except OSError as e:
      if exitOnError:
        app.error('\'' + command[0] + '\' not executed ("' + str(e) + '"); script cannot proceed')
      else:
        app.warn('\'' + command[0] + '\' not executed ("' + str(e) + '")')
        for p in _processes:
          p.terminate()
        _processes = [ ]
        break
    except (KeyboardInterrupt, SystemExit):
      import inspect, signal
      app._handler(signal.SIGINT, inspect.currentframe())

  return_stdout = ''
  return_stderr = ''
  error = False
  error_text = ''

  # Wait for all commands to complete
  try:

    # Switch how we monitor running processes / wait for them to complete
    #   depending on whether or not the user has specified -verbose or -debug option
    if app._verbosity > 1:
      for process in _processes:
        stderrdata = ''
        while True:
          # Have to read one character at a time: Waiting for a newline character using e.g. readline() will prevent MRtrix progressbars from appearing
          line = process.stderr.read(1).decode('utf-8')
          sys.stderr.write(line)
          sys.stderr.flush()
          stderrdata += line
          if not line and process.poll() is not None:
            break
        return_stderr += stderrdata
        if process.returncode:
          error = True
          error_text += stderrdata
    else:
      for process in _processes:
        process.wait()

  except (KeyboardInterrupt, SystemExit):
    import inspect, signal
    app._handler(signal.SIGINT, inspect.currentframe())

  # For any command stdout / stderr data that wasn't either passed to another command or
  #   printed to the terminal during execution, read it here.
  for index in range(len(cmdstack)):
    if tempfiles[index][0] is not None:
      tempfiles[index][0].flush()
      tempfiles[index][0].seek(0)
      stdout_text = tempfiles[index][0].read().decode('utf-8')
      return_stdout += stdout_text
      if _processes[index].returncode:
        error = True
        error_text += stdout_text
    if tempfiles[index][1] is not None:
      tempfiles[index][1].flush()
      tempfiles[index][1].seek(0)
      stderr_text = tempfiles[index][1].read().decode('utf-8')
      return_stderr += stderr_text
      if _processes[index].returncode:
        error = True
        error_text += stderr_text

  _processes = [ ]

  if (error):
    app._cleanup = False
    if exitOnError:
      caller = inspect.getframeinfo(inspect.stack()[1][0])
      app.console('')
      sys.stderr.write(os.path.basename(sys.argv[0]) + ': ' + app.colourError + '[ERROR] Command failed: ' + cmd + app.colourClear + app.colourDebug + ' (' + os.path.basename(caller.filename) + ':' + str(caller.lineno) + ')' + app.colourClear + '\n')
      sys.stderr.write(os.path.basename(sys.argv[0]) + ': ' + app.colourConsole + 'Output of failed command:' + app.colourClear + '\n')
      sys.stderr.write(error_text)
      sys.stderr.flush()
      if app._tempDir:
        with open(os.path.join(app._tempDir, 'error.txt'), 'w') as outfile:
          outfile.write(cmd + '\n\n' + error_text + '\n')
      app.complete()
      sys.exit(1)
    else:
      app.warn('Command failed: ' + cmd)

  # Only now do we append to the script log, since the command has completed successfully
  # Note: Writing the command as it was formed as the input to run.command():
  #   other flags may potentially change if this file is eventually used to resume the script
  if app._tempDir:
    with open(os.path.join(app._tempDir, 'log.txt'), 'a') as outfile:
      outfile.write(cmd + '\n')

  return (return_stdout, return_stderr)

def function(fn, *args):

  import os, sys
  from mrtrix3 import app

  fnstring = fn.__module__ + '.' + fn.__name__ + '(' + ', '.join(args) + ')'

  if app._lastFile:
    # Check to see if the last file produced in the previous script execution is
    #   intended to be produced by this command; if it is, this will be the last
    #   command that gets skipped by the -continue option
    # It's possible that the file might be defined in a '--option=XXX' style argument
    #  It's also possible that the filename in the command string has the file extension omitted
    for entry in args:
      if entry.startswith('--') and '=' in entry:
        totest = entry.split('=')[1]
      else:
        totest = entry
      filetotest = [ app._lastFile, os.path.splitext(app._lastFile)[0] ]
      if totest in filetotest:
        app.debug('Detected last file \'' + app._lastFile + '\' in function \'' + fnstring + '\'; this is the last run.command() / run.function() call that will be skipped')
        app._lastFile = ''
        break
    if app._verbosity:
      sys.stderr.write(app.colourExec + 'Skipping function:' + app.colourClear + ' ' + fnstring + '\n')
      sys.stderr.flush()
    return

  if app._verbosity:
    sys.stderr.write(app.colourExec + 'Function:' + app.colourClear + ' ' + fnstring + '\n')
    sys.stderr.flush()

  # Now we need to actually execute the requested function
  result = fn(*args)

  # Only now do we append to the script log, since the function has completed successfully
  if app._tempDir:
    with open(os.path.join(app._tempDir, 'log.txt'), 'a') as outfile:
      outfile.write(fnstring + '\n')

  return result

# When running on Windows, add the necessary '.exe' so that hopefully the correct
#   command is found by subprocess
def exeName(item):
  from distutils.spawn import find_executable
  from mrtrix3 import app
  if not app.isWindows():
    return item
  if item.endswith('.exe'):
    return item
  if find_executable(item) is not None:
    return item
  if find_executable(item + '.exe') is not None:
    return item + '.exe'
  # If it can't be found, return the item as-is; find_executable() fails to identify Python scripts
  return item

# Make sure we're not accidentally running an MRtrix executable on the system that
#   belongs to a different version of MRtrix3 to the script library currently being used,
#   or a non-MRtrix3 command with the same name as an MRtrix3 command
#   (e.g. C:\Windows\system32\mrinfo.exe; On Windows, subprocess uses CreateProcess(),
#   which checks system32\ before PATH)
def versionMatch(item):
  import os
  from distutils.spawn import find_executable
  from mrtrix3 import app
  global _mrtrix_bin_path, _mrtrix_exe_list

  if not item in _mrtrix_exe_list:
    app.debug('Command ' + item + ' not found in MRtrix3 bin/ directory')
    return item

  exe_path_manual = os.path.join(_mrtrix_bin_path, exeName(item))
  if os.path.isfile(exe_path_manual):
    app.debug('Version-matched executable for ' + item + ': ' + exe_path_manual)
    return exe_path_manual

  exe_path_sys = find_executable(exeName(item))
  if exe_path_sys and os.path.isfile(exe_path_sys):
    app.debug('Using non-version-matched executable for ' + item + ': ' + exe_path_sys)
    return exe_path_sys

  app.error('Unable to find executable for MRtrix3 command ' + item)

# If the target executable is not a binary, but is actually a script, use the
#   shebang at the start of the file to alter the subprocess call
def _shebang(item):
  import os
  from mrtrix3 import app
  from distutils.spawn import find_executable
  # If a complete path has been provided rather than just a file name, don't perform any additional file search
  if os.sep in item:
    path = item
  else:
    path = versionMatch(item)
    if path == item:
      path = find_executable(exeName(item))
  if not path:
    app.debug('File \"' + item + '\": Could not find file to query')
    return []
  # Read the first 1024 bytes of the file
  with open(path, 'rb') as f:
    data = f.read(1024)
  # Try to find the shebang line
  for line in data.splitlines():
    # Are there any non-text characters? If so, it's a binary file, so no need to looking for a shebang
    try :
      line = str(line.decode('utf-8'))
    except:
      app.debug('File \"' + item + '\": Not a text file')
      return []
    line = line.strip()
    if len(line) > 2 and line[0:2] == '#!':
      # Need to strip first in case there's a gap between the shebang symbol and the interpreter path
      shebang = line[2:].strip().split(' ')
      if app.isWindows():
        # On Windows, /usr/bin/env can't be easily found, and any direct interpreter path will have a similar issue.
        #   Instead, manually find the right interpreter to call using distutils
        if os.path.basename(shebang[0]) == 'env':
          new_shebang = [ os.path.abspath(find_executable(exeName(shebang[1]))) ]
          new_shebang.extend(shebang[2:])
          shebang = new_shebang
        else:
          new_shebang = [ os.path.abspath(find_executable(exeName(os.path.basename(shebang[0])))) ]
          new_shebang.extend(shebang[1:])
          shebang = new_shebang
        if not shebang or not shebang[0]:
          app.error('Malformed shebang in file \"' + item + '\": \"' + line + '\"')
      app.debug('File \"' + item + '\": string \"' + line + '\": ' + str(shebang))
      return shebang
  app.debug('File \"' + item + '\": No shebang found')
  return []
<commit_msg>run.command(): Comment mistakes<commit_after>import os
_mrtrix_bin_path = os.path.abspath(os.path.join(os.path.abspath(os.path.dirname(os.path.abspath(__file__))), os.pardir, os.pardir, 'bin'))
# Remember to remove the '.exe' from Windows binary executables
_mrtrix_exe_list = [ os.path.splitext(name)[0] for name in os.listdir(_mrtrix_bin_path) ]

_processes = [ ]

def command(cmd, exitOnError=True):

  import inspect, itertools, os, shlex, subprocess, sys, tempfile
  from distutils.spawn import find_executable
  from mrtrix3 import app

  global _mrtrix_exe_list

  # Vectorise the command string, preserving anything encased within quotation marks
  cmdsplit = shlex.split(cmd)

  if app._lastFile:
    # Check to see if the last file produced in the previous script execution is
    #   intended to be produced by this command; if it is, this will be the last
    #   command that gets skipped by the -continue option
    # It's possible that the file might be defined in a '--option=XXX' style argument
    #   It's also possible that the filename in the command string has the file extension omitted
    for entry in cmdsplit:
      if entry.startswith('--') and '=' in entry:
        cmdtotest = entry.split('=')[1]
      else:
        cmdtotest = entry
      filetotest = [ app._lastFile, os.path.splitext(app._lastFile)[0] ]
      if cmdtotest in filetotest:
        app.debug('Detected last file \'' + app._lastFile + '\' in command \'' + cmd + '\'; this is the last run.command() / run.function() call that will be skipped')
        app._lastFile = ''
        break
    if app._verbosity:
      sys.stderr.write(app.colourExec + 'Skipping command:' + app.colourClear + ' ' + cmd + '\n')
      sys.stderr.flush()
    return

  # This splits the command string based on the piping character '|', such that each
  #   individual executable (along with its arguments) appears as its own list
  # Note that for Python2 support, it is necessary to convert groupby() output from
  #   a generator to a list before it is passed to filter()
  cmdstack = [ list(g) for k, g in filter(lambda t : t[0], ((k, list(g)) for k, g in itertools.groupby(cmdsplit, lambda s : s is not '|') ) ) ]

  for line in cmdstack:
    is_mrtrix_exe = line[0] in _mrtrix_exe_list
    if is_mrtrix_exe:
      line[0] = versionMatch(line[0])
      if app._nthreads is not None:
        line.extend( [ '-nthreads', str(app._nthreads) ] )
      # Get MRtrix3 binaries to output additional INFO-level information if running in debug mode
      if app._verbosity == 3:
        line.append('-info')
      elif not app._verbosity:
        line.append('-quiet')
    else:
      line[0] = exeName(line[0])
    shebang = _shebang(line[0])
    if len(shebang):
      if not is_mrtrix_exe:
        # If a shebang is found, and this call is therefore invoking an
        #   interpreter, can't rely on the interpreter finding the script
        #   from PATH; need to find the full path ourselves.
        line[0] = find_executable(line[0])
      for item in reversed(shebang):
        line.insert(0, item)

  if app._verbosity:
    sys.stderr.write(app.colourExec + 'Command:' + app.colourClear + '  ' + cmd + '\n')
    sys.stderr.flush()

  app.debug('To execute: ' + str(cmdstack))

  # Construct temporary text files for holding stdout / stderr contents when appropriate
  #   (One entry per process; each is a tuple containing two entries, each of which is either a
  #   file-like object, or None)
  tempfiles = [ ]

  # Execute all processes
  _processes = [ ]
  for index, command in enumerate(cmdstack):
    file_out = None
    file_err = None
    # If there's at least one command prior to this, need to receive the stdout from the prior command
    #   at the stdin of this command; otherwise, nothing to receive
    if index > 0:
      handle_in = _processes[index-1].stdout
    else:
      handle_in = None
    # If this is not the last command, then stdout needs to be piped to the next command;
    #   otherwise, write stdout to a temporary file so that the contents can be read later
    if index < len(cmdstack)-1:
      handle_out = subprocess.PIPE
    else:
      file_out = tempfile.TemporaryFile()
      handle_out = file_out.fileno()
    # If we're in debug / info mode, the contents of stderr will be read and printed to the terminal
    #   as the command progresses, hence this needs to go to a pipe; otherwise, write it to a temporary
    #   file so that the contents can be read later
    if app._verbosity > 1:
      handle_err = subprocess.PIPE
    else:
      file_err = tempfile.TemporaryFile()
      handle_err = file_err.fileno()
    # Set off the processes
    try:
      process = subprocess.Popen (command, stdin=handle_in, stdout=handle_out, stderr=handle_err)
      _processes.append(process)
      tempfiles.append( ( file_out, file_err ) )
    # FileNotFoundError not defined in Python 2.7
    except OSError as e:
      if exitOnError:
        app.error('\'' + command[0] + '\' not executed ("' + str(e) + '"); script cannot proceed')
      else:
        app.warn('\'' + command[0] + '\' not executed ("' + str(e) + '")')
        for p in _processes:
          p.terminate()
        _processes = [ ]
        break
    except (KeyboardInterrupt, SystemExit):
      import inspect, signal
      app._handler(signal.SIGINT, inspect.currentframe())

  return_stdout = ''
  return_stderr = ''
  error = False
  error_text = ''

  # Wait for all commands to complete
  try:

    # Switch how we monitor running processes / wait for them to complete
    #   depending on whether or not the user has specified -verbose or -debug option
    if app._verbosity > 1:
      for process in _processes:
        stderrdata = ''
        while True:
          # Have to read one character at a time: Waiting for a newline character using e.g. readline() will prevent MRtrix progressbars from appearing
          line = process.stderr.read(1).decode('utf-8')
          sys.stderr.write(line)
          sys.stderr.flush()
          stderrdata += line
          if not line and process.poll() is not None:
            break
        return_stderr += stderrdata
        if process.returncode:
          error = True
          error_text += stderrdata
    else:
      for process in _processes:
        process.wait()

  except (KeyboardInterrupt, SystemExit):
    import inspect, signal
    app._handler(signal.SIGINT, inspect.currentframe())

  # For any command stdout / stderr data that wasn't either passed to another command or
  #   printed to the terminal during execution, read it here.
  for index in range(len(cmdstack)):
    if tempfiles[index][0] is not None:
      tempfiles[index][0].flush()
      tempfiles[index][0].seek(0)
      stdout_text = tempfiles[index][0].read().decode('utf-8')
      return_stdout += stdout_text
      if _processes[index].returncode:
        error = True
        error_text += stdout_text
    if tempfiles[index][1] is not None:
      tempfiles[index][1].flush()
      tempfiles[index][1].seek(0)
      stderr_text = tempfiles[index][1].read().decode('utf-8')
      return_stderr += stderr_text
      if _processes[index].returncode:
        error = True
        error_text += stderr_text

  _processes = [ ]

  if (error):
    app._cleanup = False
    if exitOnError:
      caller = inspect.getframeinfo(inspect.stack()[1][0])
      app.console('')
      sys.stderr.write(os.path.basename(sys.argv[0]) + ': ' + app.colourError + '[ERROR] Command failed: ' + cmd + app.colourClear + app.colourDebug + ' (' + os.path.basename(caller.filename) + ':' + str(caller.lineno) + ')' + app.colourClear + '\n')
      sys.stderr.write(os.path.basename(sys.argv[0]) + ': ' + app.colourConsole + 'Output of failed command:' + app.colourClear + '\n')
      sys.stderr.write(error_text)
      sys.stderr.flush()
      if app._tempDir:
        with open(os.path.join(app._tempDir, 'error.txt'), 'w') as outfile:
          outfile.write(cmd + '\n\n' + error_text + '\n')
      app.complete()
      sys.exit(1)
    else:
      app.warn('Command failed: ' + cmd)

  # Only now do we append to the script log, since the command has completed successfully
  # Note: Writing the command as it was formed as the input to run.command():
  #   other flags may potentially change if this file is eventually used to resume the script
  if app._tempDir:
    with open(os.path.join(app._tempDir, 'log.txt'), 'a') as outfile:
      outfile.write(cmd + '\n')

  return (return_stdout, return_stderr)

def function(fn, *args):

  import os, sys
  from mrtrix3 import app

  fnstring = fn.__module__ + '.' + fn.__name__ + '(' + ', '.join(args) + ')'

  if app._lastFile:
    # Check to see if the last file produced in the previous script execution is
    #   intended to be produced by this command; if it is, this will be the last
    #   command that gets skipped by the -continue option
    # It's possible that the file might be defined in a '--option=XXX' style argument
    #  It's also possible that the filename in the command string has the file extension omitted
    for entry in args:
      if entry.startswith('--') and '=' in entry:
        totest = entry.split('=')[1]
      else:
        totest = entry
      filetotest = [ app._lastFile, os.path.splitext(app._lastFile)[0] ]
      if totest in filetotest:
        app.debug('Detected last file \'' + app._lastFile + '\' in function \'' + fnstring + '\'; this is the last run.command() / run.function() call that will be skipped')
        app._lastFile = ''
        break
    if app._verbosity:
      sys.stderr.write(app.colourExec + 'Skipping function:' + app.colourClear + ' ' + fnstring + '\n')
      sys.stderr.flush()
    return

  if app._verbosity:
    sys.stderr.write(app.colourExec + 'Function:' + app.colourClear + ' ' + fnstring + '\n')
    sys.stderr.flush()

  # Now we need to actually execute the requested function
  result = fn(*args)

  # Only now do we append to the script log, since the function has completed successfully
  if app._tempDir:
    with open(os.path.join(app._tempDir, 'log.txt'), 'a') as outfile:
      outfile.write(fnstring + '\n')

  return result

# When running on Windows, add the necessary '.exe' so that hopefully the correct
#   command is found by subprocess
def exeName(item):
  from distutils.spawn import find_executable
  from mrtrix3 import app
  if not app.isWindows():
    return item
  if item.endswith('.exe'):
    return item
  if find_executable(item) is not None:
    return item
  if find_executable(item + '.exe') is not None:
    return item + '.exe'
  # If it can't be found, return the item as-is; find_executable() fails to identify Python scripts
  return item

# Make sure we're not accidentally running an MRtrix executable on the system that
#   belongs to a different version of MRtrix3 to the script library currently being used,
#   or a non-MRtrix3 command with the same name as an MRtrix3 command
#   (e.g. C:\Windows\system32\mrinfo.exe; On Windows, subprocess uses CreateProcess(),
#   which checks system32\ before PATH)
def versionMatch(item):
  import os
  from distutils.spawn import find_executable
  from mrtrix3 import app
  global _mrtrix_bin_path, _mrtrix_exe_list

  if not item in _mrtrix_exe_list:
    app.debug('Command ' + item + ' not found in MRtrix3 bin/ directory')
    return item

  exe_path_manual = os.path.join(_mrtrix_bin_path, exeName(item))
  if os.path.isfile(exe_path_manual):
    app.debug('Version-matched executable for ' + item + ': ' + exe_path_manual)
    return exe_path_manual

  exe_path_sys = find_executable(exeName(item))
  if exe_path_sys and os.path.isfile(exe_path_sys):
    app.debug('Using non-version-matched executable for ' + item + ': ' + exe_path_sys)
    return exe_path_sys

  app.error('Unable to find executable for MRtrix3 command ' + item)

# If the target executable is not a binary, but is actually a script, use the
#   shebang at the start of the file to alter the subprocess call
def _shebang(item):
  import os
  from mrtrix3 import app
  from distutils.spawn import find_executable
  # If a complete path has been provided rather than just a file name, don't perform any additional file search
  if os.sep in item:
    path = item
  else:
    path = versionMatch(item)
    if path == item:
      path = find_executable(exeName(item))
  if not path:
    app.debug('File \"' + item + '\": Could not find file to query')
    return []
  # Read the first 1024 bytes of the file
  with open(path, 'rb') as f:
    data = f.read(1024)
  # Try to find the shebang line
  for line in data.splitlines():
    # Are there any non-text characters? If so, it's a binary file, so no need to looking for a shebang
    try :
      line = str(line.decode('utf-8'))
    except:
      app.debug('File \"' + item + '\": Not a text file')
      return []
    line = line.strip()
    if len(line) > 2 and line[0:2] == '#!':
      # Need to strip first in case there's a gap between the shebang symbol and the interpreter path
      shebang = line[2:].strip().split(' ')
      if app.isWindows():
        # On Windows, /usr/bin/env can't be easily found, and any direct interpreter path will have a similar issue.
        #   Instead, manually find the right interpreter to call using distutils
        if os.path.basename(shebang[0]) == 'env':
          new_shebang = [ os.path.abspath(find_executable(exeName(shebang[1]))) ]
          new_shebang.extend(shebang[2:])
          shebang = new_shebang
        else:
          new_shebang = [ os.path.abspath(find_executable(exeName(os.path.basename(shebang[0])))) ]
          new_shebang.extend(shebang[1:])
          shebang = new_shebang
        if not shebang or not shebang[0]:
          app.error('Malformed shebang in file \"' + item + '\": \"' + line + '\"')
      app.debug('File \"' + item + '\": string \"' + line + '\": ' + str(shebang))
      return shebang
  app.debug('File \"' + item + '\": No shebang found')
  return []
<|endoftext|>


<commit_before># Copyright (c) 2013, Menno Smits
# Released subject to the New BSD License
# Please see http://en.wikipedia.org/wiki/BSD_licenses

"""
Structured representation for IMAP response.
Inspired by Ruby Net::IMAP::Envelope and Net::IMAP::Address
(see http://www.ruby-doc.org/stdlib-2.0.0/libdoc/net/imap/rdoc/Net/IMAP.html).
"""

from collections import namedtuple

# the following hacks to add docstrings to namedtuples is courtesy of:
# http://stackoverflow.com/questions/1606436/adding-docstrings-to-namedtuples-in-python

class Address(namedtuple("Address", "Name Route Mailbox Host")):
    """
    Represents electronic mail addresses.

    Fields (in-order):

        Name -- Returns the phrase from [RFC-822] mailbox.

        Route -- Returns the route from [RFC-822] route-addr.

        Mailbox -- None indicates end of [RFC-822] group. If not None and host is None,
                   returns [RFC-822] group name. Otherwise, returns [RFC-822] local-part.

        Host -- None indicates [RFC-822] group syntax. Otherwise, returns [RFC-822] domain name.

    """

# note lowercase "from" is a keyword
class Envelope(namedtuple("Envelope", "Date Subject From Sender Reply_To To " + \
                          "Cc Bcc In_Reply_To Message_Id")):
    """

    Represents envelope structures of messages.

    Fields (in-order):

        Date -- Returns a string that represents the "Date:" header.

        Subject -- Returns a string that represents the "Subject:" header.

        From -- Returns a tuple sequence of Address structure that represents "From:" header.

        Sender -- Returns a tuple sequence of Address structure that represents "Sender:" header.

        Reply_To -- Returns a tuple sequence of Address structure that represents "Reply_To:" header.

        To -- Returns a tuple sequence of Address structure that represents "To:" header.

        Cc -- Returns a tuple sequence of Address structure that represents "Cc:" header.

        Bcc -- Returns a tuple sequence of Address structure that represents "Bcc:" header.

        In_Reply_To -- Returns a string that represents the "In-Reply-To:" header.

        Message_Id -- Returns a string that represents the "Message-Id:" header.

    """
<commit_msg>updated documentation for response types<commit_after># Copyright (c) 2013, Menno Smits
# Released subject to the New BSD License
# Please see http://en.wikipedia.org/wiki/BSD_licenses

"""
Structured representation for IMAP response.
Inspired by Ruby Net::IMAP::Envelope and Net::IMAP::Address
(see http://www.ruby-doc.org/stdlib-2.0.0/libdoc/net/imap/rdoc/Net/IMAP.html).
"""

from collections import namedtuple

# the following hacks to add docstrings to namedtuples is courtesy of:
# http://stackoverflow.com/questions/1606436/adding-docstrings-to-namedtuples-in-python

class Address(namedtuple("Address", "Name Route Mailbox Host")):
    """
    Represents electronic mail addresses.

    Fields (in-order):

        Name -- Returns the phrase from [RFC-822] mailbox.

        Route -- Returns the route from [RFC-822] route-addr.

        Mailbox -- None indicates end of [RFC-822] group. If not None and host is None,
                   returns [RFC-822] group name. Otherwise, returns [RFC-822] local-part.

        Host -- None indicates [RFC-822] group syntax. Otherwise, returns [RFC-822] domain name.

    """

# note lowercase "from" is a keyword
class Envelope(namedtuple("Envelope", "Date Subject From Sender Reply_To To " + \
                          "Cc Bcc In_Reply_To Message_Id")):
    """

    Represents envelope structures of messages.

    Fields (in-order):

        Date -- Returns a string that represents the "Date:" header.

        Subject -- Returns a string that represents the "Subject:" header.

        From -- Returns a tuple sequence of Address structure that represents "From:" header,
                or None if header does not exist.

        Sender -- Returns a tuple sequence of Address structure that represents "Sender:" header,
                  or None if header does not exist.

        Reply_To -- Returns a tuple sequence of Address structure that represents "Reply_To:" header,
                    or None if header does not exist.

        To -- Returns a tuple sequence of Address structure that represents "To:" header,
              or None if header does not exist.

        Cc -- Returns a tuple sequence of Address structure that represents "Cc:" header,
              or None if header does not exist.

        Bcc -- Returns a tuple sequence of Address structure that represents "Bcc:" header,
               or None if header does not exist.

        In_Reply_To -- Returns a string that represents the "In-Reply-To:" header.

        Message_Id -- Returns a string that represents the "Message-Id:" header.

    """
<|endoftext|>


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

import argparse
import fileinput
from compound import Compound
from lattice import Lattice
import multiprocessing

import pickle
import logging
import pdb
from nltk.corpus import PlaintextCorpusReader
from nltk.tokenize import WhitespaceTokenizer
import sys
import multiprocessing as mp
import codecs
from annoy import AnnoyIndex
from sklearn.metrics.pairwise import cosine_similarity
import gensim
import yaml

from viterbi_decompounder import ViterbiDecompounder

class BaseDecompounder:

    def __init__(self, model_folder, modelSetup, nAccuracy=250, globalNN=500,
            similarityThreshold=0.0):

        # Basic Logging:
        self.logger = logging.getLogger('')
        hdlr = logging.FileHandler('decompound.log')
        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        hdlr.setFormatter(formatter)
        self.logger.addHandler(hdlr)
        self.logger.setLevel(logging.DEBUG)
        ########################################

        self.nAccuracy = nAccuracy
        self.similarityThreshold = similarityThreshold
        self.globalNN = globalNN
        self.FUGENLAUTE = modelSetup["FUGENLAUTE"]

        print >> sys.stderr, "Loading prototypes..."
        self.prototypes = pickle.load(open(model_folder + '/prototypes.p', 'rb'))

        print >> sys.stderr, "Loading KNN search..."
        self.annoy_tree = AnnoyIndex(500)
        self.annoy_tree.load(model_folder + '/tree.ann')

        print >> sys.stderr, "Loading gensim model..."
        self.model = gensim.models.Word2Vec.load_word2vec_format(args.model_folder + '/w2v.bin', binary=True)

        print >> sys.stderr, "Done."

    def decompound(self, inputCompound, offset=0):

        # 1. See if we can deal with compound
        #
        if len(inputCompound) == 0:
            return []

        self.logger.debug('Looking up word %s in Word2Vec model' % inputCompound)
        if inputCompound not in self.model.vocab:  # We haven't vector representation for compound
            self.logger.debug('ERROR COULDNT FIND KEY %s IN WORD2VEC MODEL' % inputCompound)
            return []
        self.logger.debug('Found key in index dict for word %s' % inputCompound)
        inputCompoundRep = self.model[inputCompound]
        inputCompoundIndex = self.model.vocab[inputCompound].index

        # 2. See if we have prefixes of compound in vocabulary
        #
        self.logger.info('Getting all matching prefixes')
        prefixes = set()
        for prefix in self.prototypes.keys():
            if len(inputCompound) > len(prefix) and inputCompound.startswith(prefix):
                prefixes.add(prefix)
        self.logger.debug('Possible prefixes: %r' % prefixes)
        if len(prefixes) == 0:  # cannot split
            return []

        # 3. Get all possible splits (so that we have representations for both prefix and tail)
        #
        self.logger.info('Getting possible splits')
        splits = set()

        for prefix in prefixes:
            rest = inputCompound[len(prefix):]

            # get all possible tails
            possible_tails = []  # (haus, 4)
            for fug in self.FUGENLAUTE:
                if rest.startswith(fug):
                    tail_offset = len(prefix) + len(fug)
                    possible_tails += [
                            (rest[len(fug):], tail_offset, fug),         #original case
                            (rest[len(fug):].title(), tail_offset, fug)  #title case
                    ]

            for (tail, tail_offset, fug) in possible_tails:
                self.logger.debug('Tail: %s, Fug: %s' % (tail, fug))
                if tail not in self.model.vocab:  # we haven't representation for this tail
                    self.logger.debug('Discarding split %s %s %s' % (inputCompound, prefix, tail))
                    continue
                splits.add((prefix, tail, tail_offset, fug))
                self.logger.debug('Considering split %s %s %s' % (inputCompound, prefix, tail))

        if len(splits) == 0:
            self.logger.error('Cannot decompound %s' % inputCompound)
            return []

        # 4. See if retrieved splits are good in terms of word embeddings
        #
        result = []
        self.logger.info('Applying direction vectors to possible splits')

        for prefix, tail, tail_offset, fug in splits:
            self.logger.debug('Applying %d directions vectors to split %s %s' %
                    (len(self.prototypes[prefix]), prefix, tail))

            for origin, evidence in self.prototypes[prefix]:
                self.logger.debug('Prefix %s by indexes %d and %d' % (prefix, origin[0], origin[1]))

                dirVectorCompoundRepresentation = self.model[self.model.index2word[origin[0]]]
                dirVectorTailRepresentation = self.model[self.model.index2word[origin[1]]]
                dirVectorDifference = dirVectorCompoundRepresentation - dirVectorTailRepresentation

                predictionRepresentation = self.model[tail] + dirVectorDifference

                self.logger.debug('Getting Annoy KNN')
                try:
                    neighbours = self.annoy_tree.get_nns_by_vector(list(predictionRepresentation),
                            self.globalNN)[:self.nAccuracy]
                    self.logger.debug(neighbours)
                except Exception as e:
                    print e
                    self.logger.error('Problem found when retrieving KNN for prediction representation')
                    self.logger.error(list(predictionRepresentation))
                    exit()

                # Find rank
                rank = -1
                for i, nei in enumerate(neighbours):
                    if nei == inputCompoundIndex:
                        rank = i
                if rank == -1:
                    self.logger.debug('%d not found in neighbours. NO RANK. WONT SPLIT' % inputCompoundIndex)
                    continue
                self.logger.debug('%d found in neighbours. Rank: %d' % (inputCompoundIndex, rank))

                # compare cosine against threshold
                similarity = cosine_similarity(predictionRepresentation, inputCompoundRep)[0][0]
                self.logger.debug('Computed cosine similarity: %f' % similarity)
                if similarity < self.similarityThreshold:
                    self.logger.debug('%d has too small cosine similarity, discarding' % inputCompoundIndex)
                    continue

                result.append((prefix, tail, tail_offset, origin[0],
                    origin[1], rank, similarity, fug))

        return result

    def get_decompound_lattice(self, inputCompound):
        # 1. Initialize
        #
        lattice = {}  # from: from -> (to, label, rank, cosine, fug)

        # 2. Make graph
        #
        def add_edges(from_, label):
            candidates = self.decompound(label)
            tails = set()

            #Default path:
            if from_ not in lattice:
                lattice[from_] = []

            lattice[from_] += [(from_, from_ + len(label), label, 0, 1.0, "")]

            #Canidate pathes:
            for index, candidate in enumerate(candidates):
                prefix, tail, tail_offset, origin0, origin1, rank, similarity, fug = candidate

                to = from_ + tail_offset
                lattice[from_] += [(from_, to, prefix, rank, similarity, fug)]

                tails.add((tail, tail_offset))
            for (tail, next_tail_offset) in tails:
                add_edges(from_ + next_tail_offset, tail)

        add_edges(0, inputCompound)

        for k in lattice.keys():
            lattice[k] = list(set(lattice[k]))

        return lattice

def print_path(viterbi_path):
    return " ".join(map(lambda p: "%d,%d,%s" % p, viterbi_path))

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Decompound words.')

    parser.add_argument('model_folder')

    parser.add_argument('--mode', choices=['1-best', 'lattices', 'dict_w2v', 'w2v_dict'], default='1-best')
    parser.add_argument('--globalNN', default=500)
    parser.add_argument('--nAccuracy', default=250)
    parser.add_argument('--similarityThreshold', default=0.0)

    args = parser.parse_args()

    print >> sys.stderr, "Loading model..."
    modelSetup = yaml.load(open(args.model_folder + "/model.yaml", 'r'))

    base_decompounder = BaseDecompounder(args.model_folder, modelSetup,
            nAccuracy=args.nAccuracy, globalNN=args.globalNN,
            similarityThreshold=args.similarityThreshold)

    if args.mode == "lattices":
        for line in sys.stdin:
            print(
                base_decompounder.get_decompound_lattice(
                    line.decode('utf8').rstrip('\n').title(),
                )
            )
    elif args.mode == "w2v_dict":
        for word in base_decompounder.model.vocab.keys():
            print word.encode('utf-8')
    elif args.mode in ["1-best", "dict_w2v"]:
        vit = ViterbiDecompounder()
        vit.load_weights(modelSetup["WEIGHTS"])

        words = []
        if args.mode == "1-best":
            words = map(lambda line: line.decode('utf8').strip(),
                    sys.stdin)
        else:
            words = base_decompounder.model.vocab.keys()

        print >>sys.stderr, "# words: %d" % len(words)

        def process_word(word):
            lattice = Lattice(base_decompounder.get_decompound_lattice(word))
            viterbi_path = vit.viterbi_decode(Compound(word, None, lattice))
            return [word.encode('utf-8'), print_path(viterbi_path).encode('utf-8')]

        pool = multiprocessing.Pool()
        for pword in pool.map(process_word, words):
            print " ".join(pword)

<commit_msg>Limit to 4 processes (memory restrictions).<commit_after>#!/usr/bin/env python
# coding: utf-8

import argparse
import fileinput
from compound import Compound
from lattice import Lattice
import multiprocessing

import pickle
import logging
import pdb
from nltk.corpus import PlaintextCorpusReader
from nltk.tokenize import WhitespaceTokenizer
import sys
import multiprocessing as mp
import codecs
from annoy import AnnoyIndex
from sklearn.metrics.pairwise import cosine_similarity
import gensim
import yaml

from viterbi_decompounder import ViterbiDecompounder

class BaseDecompounder:

    def __init__(self, model_folder, modelSetup, nAccuracy=250, globalNN=500,
            similarityThreshold=0.0):

        # Basic Logging:
        self.logger = logging.getLogger('')
        hdlr = logging.FileHandler('decompound.log')
        formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
        hdlr.setFormatter(formatter)
        self.logger.addHandler(hdlr)
        self.logger.setLevel(logging.DEBUG)
        ########################################

        self.nAccuracy = nAccuracy
        self.similarityThreshold = similarityThreshold
        self.globalNN = globalNN
        self.FUGENLAUTE = modelSetup["FUGENLAUTE"]

        print >> sys.stderr, "Loading prototypes..."
        self.prototypes = pickle.load(open(model_folder + '/prototypes.p', 'rb'))

        print >> sys.stderr, "Loading KNN search..."
        self.annoy_tree = AnnoyIndex(500)
        self.annoy_tree.load(model_folder + '/tree.ann')

        print >> sys.stderr, "Loading gensim model..."
        self.model = gensim.models.Word2Vec.load_word2vec_format(args.model_folder + '/w2v.bin', binary=True)

        print >> sys.stderr, "Done."

    def decompound(self, inputCompound, offset=0):

        # 1. See if we can deal with compound
        #
        if len(inputCompound) == 0:
            return []

        self.logger.debug('Looking up word %s in Word2Vec model' % inputCompound)
        if inputCompound not in self.model.vocab:  # We haven't vector representation for compound
            self.logger.debug('ERROR COULDNT FIND KEY %s IN WORD2VEC MODEL' % inputCompound)
            return []
        self.logger.debug('Found key in index dict for word %s' % inputCompound)
        inputCompoundRep = self.model[inputCompound]
        inputCompoundIndex = self.model.vocab[inputCompound].index

        # 2. See if we have prefixes of compound in vocabulary
        #
        self.logger.info('Getting all matching prefixes')
        prefixes = set()
        for prefix in self.prototypes.keys():
            if len(inputCompound) > len(prefix) and inputCompound.startswith(prefix):
                prefixes.add(prefix)
        self.logger.debug('Possible prefixes: %r' % prefixes)
        if len(prefixes) == 0:  # cannot split
            return []

        # 3. Get all possible splits (so that we have representations for both prefix and tail)
        #
        self.logger.info('Getting possible splits')
        splits = set()

        for prefix in prefixes:
            rest = inputCompound[len(prefix):]

            # get all possible tails
            possible_tails = []  # (haus, 4)
            for fug in self.FUGENLAUTE:
                if rest.startswith(fug):
                    tail_offset = len(prefix) + len(fug)
                    possible_tails += [
                            (rest[len(fug):], tail_offset, fug),         #original case
                            (rest[len(fug):].title(), tail_offset, fug)  #title case
                    ]

            for (tail, tail_offset, fug) in possible_tails:
                self.logger.debug('Tail: %s, Fug: %s' % (tail, fug))
                if tail not in self.model.vocab:  # we haven't representation for this tail
                    self.logger.debug('Discarding split %s %s %s' % (inputCompound, prefix, tail))
                    continue
                splits.add((prefix, tail, tail_offset, fug))
                self.logger.debug('Considering split %s %s %s' % (inputCompound, prefix, tail))

        if len(splits) == 0:
            self.logger.error('Cannot decompound %s' % inputCompound)
            return []

        # 4. See if retrieved splits are good in terms of word embeddings
        #
        result = []
        self.logger.info('Applying direction vectors to possible splits')

        for prefix, tail, tail_offset, fug in splits:
            self.logger.debug('Applying %d directions vectors to split %s %s' %
                    (len(self.prototypes[prefix]), prefix, tail))

            for origin, evidence in self.prototypes[prefix]:
                self.logger.debug('Prefix %s by indexes %d and %d' % (prefix, origin[0], origin[1]))

                dirVectorCompoundRepresentation = self.model[self.model.index2word[origin[0]]]
                dirVectorTailRepresentation = self.model[self.model.index2word[origin[1]]]
                dirVectorDifference = dirVectorCompoundRepresentation - dirVectorTailRepresentation

                predictionRepresentation = self.model[tail] + dirVectorDifference

                self.logger.debug('Getting Annoy KNN')
                try:
                    neighbours = self.annoy_tree.get_nns_by_vector(list(predictionRepresentation),
                            self.globalNN)[:self.nAccuracy]
                    self.logger.debug(neighbours)
                except Exception as e:
                    print e
                    self.logger.error('Problem found when retrieving KNN for prediction representation')
                    self.logger.error(list(predictionRepresentation))
                    exit()

                # Find rank
                rank = -1
                for i, nei in enumerate(neighbours):
                    if nei == inputCompoundIndex:
                        rank = i
                if rank == -1:
                    self.logger.debug('%d not found in neighbours. NO RANK. WONT SPLIT' % inputCompoundIndex)
                    continue
                self.logger.debug('%d found in neighbours. Rank: %d' % (inputCompoundIndex, rank))

                # compare cosine against threshold
                similarity = cosine_similarity(predictionRepresentation, inputCompoundRep)[0][0]
                self.logger.debug('Computed cosine similarity: %f' % similarity)
                if similarity < self.similarityThreshold:
                    self.logger.debug('%d has too small cosine similarity, discarding' % inputCompoundIndex)
                    continue

                result.append((prefix, tail, tail_offset, origin[0],
                    origin[1], rank, similarity, fug))

        return result

    def get_decompound_lattice(self, inputCompound):
        # 1. Initialize
        #
        lattice = {}  # from: from -> (to, label, rank, cosine, fug)

        # 2. Make graph
        #
        def add_edges(from_, label):
            candidates = self.decompound(label)
            tails = set()

            #Default path:
            if from_ not in lattice:
                lattice[from_] = []

            lattice[from_] += [(from_, from_ + len(label), label, 0, 1.0, "")]

            #Canidate pathes:
            for index, candidate in enumerate(candidates):
                prefix, tail, tail_offset, origin0, origin1, rank, similarity, fug = candidate

                to = from_ + tail_offset
                lattice[from_] += [(from_, to, prefix, rank, similarity, fug)]

                tails.add((tail, tail_offset))
            for (tail, next_tail_offset) in tails:
                add_edges(from_ + next_tail_offset, tail)

        add_edges(0, inputCompound)

        for k in lattice.keys():
            lattice[k] = list(set(lattice[k]))

        return lattice

def print_path(viterbi_path):
    return " ".join(map(lambda p: "%d,%d,%s" % p, viterbi_path))

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Decompound words.')

    parser.add_argument('model_folder')

    parser.add_argument('--mode', choices=['1-best', 'lattices', 'dict_w2v', 'w2v_dict'], default='1-best')
    parser.add_argument('--globalNN', default=500)
    parser.add_argument('--nAccuracy', default=250)
    parser.add_argument('--similarityThreshold', default=0.0)

    args = parser.parse_args()

    print >> sys.stderr, "Loading model..."
    modelSetup = yaml.load(open(args.model_folder + "/model.yaml", 'r'))

    base_decompounder = BaseDecompounder(args.model_folder, modelSetup,
            nAccuracy=args.nAccuracy, globalNN=args.globalNN,
            similarityThreshold=args.similarityThreshold)

    if args.mode == "lattices":
        for line in sys.stdin:
            print(
                base_decompounder.get_decompound_lattice(
                    line.decode('utf8').rstrip('\n').title(),
                )
            )
    elif args.mode == "w2v_dict":
        for word in base_decompounder.model.vocab.keys():
            print word.encode('utf-8')
    elif args.mode in ["1-best", "dict_w2v"]:
        vit = ViterbiDecompounder()
        vit.load_weights(modelSetup["WEIGHTS"])

        words = []
        if args.mode == "1-best":
            words = map(lambda line: line.decode('utf8').strip(),
                    sys.stdin)
        else:
            words = base_decompounder.model.vocab.keys()

        print >>sys.stderr, "# words: %d" % len(words)

        def process_word(word):
            lattice = Lattice(base_decompounder.get_decompound_lattice(word))
            viterbi_path = vit.viterbi_decode(Compound(word, None, lattice))
            return [word.encode('utf-8'), print_path(viterbi_path).encode('utf-8')]

        pool = multiprocessing.Pool(4)
        for pword in pool.map(process_word, words):
            print " ".join(pword)

<|endoftext|>


<commit_before>"""
by Liam A.
used: http://www.december.com/html/spec/color

"""

from ggame import App, Color, LineStyle, Sprite, RectangleAsset, CircleAsset, EllipseAsset, PolygonAsset
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 700

# Colors
Lgreen = Color (0x7CFC00, 0.95)
turqo = Color (0x40E0D0, 0.99)
Orange = Color (0xFF8600, 1)
black = Color (0x000000, 0.85)
purp = Color (0x68228B, 0.6)
brn = Color (0x5C3317, 0.9)
pale = Color (0xFFFACD, 0.4)

bl_line = LineStyle(3, black)
thinline = LineStyle(1, black)

class Flowr(Sprite):
    asset = ImageAsset("images/d8d9596f8e39f135f86a01f61d381eec.jpg")
    def __init__(self):
        position(30, 100)
class Tree(Sprite):
    asset = ImageAsset("images/download.jpeg")
    def __init__(self):
        position(45, 160)
class Cat(Sprite):
    asset = ImageAsset("images/cute-cartoon-cat-cute-light-brown-cartoon-cat-with-a-black-nose-and-7VM6VK-clipart.png")
    def __init__(self):
        position(30, 220)

class Bunny(Sprite):
    asset = ImageAsset("images/bunny.png")
    def __init__(self):
        position(45, 280)

class Draw(App):
    def __init__(self, width, height):
        self.a="no"
        super().__init__(width, height)
        Draw.listenMouseEvent("mouseup", ym_up)
        Draw.listenMouseEvent("mousedown", nm_dn)
    def ym_up(self,event):
        self.a="yes"
    def nm_dn(self,event):
        self.a="no"

my_draw = Draw(SCREEN_WIDTH, SCREEN_HEIGHT)
my_draw.run()<commit_msg>Updated from Brython Server: 11/15/2016 1:42:52 PM<commit_after>"""
by Liam A.
used: http://www.december.com/html/spec/color

"""

from ggame import App, Color, LineStyle, Sprite, RectangleAsset, CircleAsset, EllipseAsset, PolygonAsset, ImageAsset
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 700

# Colors
Lgreen = Color (0x7CFC00, 0.95)
turqo = Color (0x40E0D0, 0.99)
Orange = Color (0xFF8600, 1)
black = Color (0x000000, 0.85)
purp = Color (0x68228B, 0.6)
brn = Color (0x5C3317, 0.9)
pale = Color (0xFFFACD, 0.4)

bl_line = LineStyle(3, black)
thinline = LineStyle(1, black)

class Flowr(Sprite):
    asset = ImageAsset("images/d8d9596f8e39f135f86a01f61d381eec.jpg")
    def __init__(self):
        position(30, 100)
class Tree(Sprite):
    asset = ImageAsset("images/download.jpeg")
    def __init__(self):
        position(45, 160)
class Cat(Sprite):
    asset = ImageAsset("images/cute-cartoon-cat-cute-light-brown-cartoon-cat-with-a-black-nose-and-7VM6VK-clipart.png")
    def __init__(self):
        position(30, 220)

class Bunny(Sprite):
    asset = ImageAsset("images/bunny.png")
    def __init__(self):
        position(45, 280)

class Draw(App):
    def __init__(self, width, height):
        self.a="no"
        super().__init__(width, height)
        Draw.listenMouseEvent("mouseup", ym_up)
        Draw.listenMouseEvent("mousedown", nm_dn)
    def ym_up(self,event):
        self.a="yes"
    def nm_dn(self,event):
        self.a="no"

my_draw = Draw(SCREEN_WIDTH, SCREEN_HEIGHT)
my_draw.run()<|endoftext|>


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

# Copyright (C) 2009-2012:
#    Gabes Jean, naparuba@gmail.com
#    Gerhard Lausser, Gerhard.Lausser@consol.de
#    Gregory Starck, g.starck@gmail.com
#    Hartmut Goebel, h.goebel@goebel-consult.de
#    Frederic Mohier, frederic.mohier@gmail.com
#
# This file is part of Shinken.
#
# Shinken 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.
#
# Shinken 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 Shinken.  If not, see <http://www.gnu.org/licenses/>.

import math

from shinken.misc.perfdata import PerfDatas
from shinken.log import logger

# Will try to return a dict with:
# lnk: link to add in this perfdata thing
# title: text to show on it
# metrics: list of ('html color', percent) like [('#68f', 35), ('white', 64)]
def get_perfometer_table_values(elt, metric=None):
    # first try to get the command name called
    cmd = elt.check_command.call.split('!')[0]
    logger.debug("[WebUI] Looking for perfometer value for element: %s, command: %s", elt.get_full_name(), cmd)

    tab = {'check_http': manage_check_http_command,
           'check_ping': manage_check_ping_command,
           'check_tcp': manage_check_tcp_command,
        }

    f = tab.get(cmd, None)
    if f:
        return f(elt, metric)

    try:
        r = manage_unknown_command(elt, metric)
    except:
        return None
    return r

def manage_check_http_command(elt, metric='time'):
    logger.debug("[WebUI] Get check_http perfdata of %s", elt.get_full_name())
    p = PerfDatas(elt.perf_data)
    if not metric in p:
        return None

    m = p[metric]
    v = m.value
    if not v:
        return None

    # Percent of ok should be time/1s
    pct = get_logarithmic(v, 1)
    # Now get the color
    # OK: #6f2 (102,255,34) green
    # Warning: #f60 (255,102,0) orange
    # Crit: #ff0033 (255,0,51)
    base_color = {0: (102, 255, 34), 1: (255, 102, 0), 2: (255, 0, 51)}
    state_id = get_stateid(elt)
    color = base_color.get(state_id, (179, 196, 255))
    s_color = 'RGB(%d,%d,%d)' % color
    lnk = '#'
    metrics = [(s_color, pct), ('white', 100-pct)]
    title = '%ss' % v
    #print "HTTP: return", {'lnk': lnk, 'metrics': metrics, 'title': title}
    return {'lnk': lnk, 'metrics': metrics, 'title': title}

def manage_check_ping_command(elt, metric='rta'):
    logger.debug("[WebUI] Get check_ping perfdata of %s", elt.get_full_name())
    p = PerfDatas(elt.perf_data)
    if not metric in p:
        return None

    m = p[metric]
    v = m.value
    crit = m.critical
    if not v or not crit:
        return None

    # Percent of ok should be the log of time versus max/2
    pct = get_logarithmic(v, crit / 2)
    # Now get the color
    # OK: #6f2 (102,255,34) green
    # Warning: #f60 (255,102,0) orange
    # Crit: #ff0033 (255,0,51)
    base_color = {0: (102, 255, 34), 1: (255, 102, 0), 2: (255, 0, 51)}
    state_id = get_stateid(elt)
    color = base_color.get(state_id, (179, 196, 255))
    s_color = 'RGB(%d,%d,%d)' % color

    lnk = '#'
    metrics = [(s_color, pct), ('white', 100-pct)]
    title = '%sms' % v
    #print "HTTP: return", {'lnk': lnk, 'metrics': metrics, 'title': title}
    return {'lnk': lnk, 'metrics': metrics, 'title': title}

def manage_check_tcp_command(elt, metric='time'):
    logger.debug("[WebUI] Get check_tcp perfdata of %s", elt.get_full_name())
    p = PerfDatas(elt.perf_data)
    if not metric in p:
        return None

    m = p[metric]
    v = m.value

    if not v or not m.max:
        return None

    # Percent of ok should be the log of time versus m.max / 2
    pct = get_logarithmic(v, m.max / 2)

    # Now get the color
    # OK: #6f2 (102,255,34) green
    # Warning: #f60 (255,102,0) orange
    # Crit: #ff0033 (255,0,51)
    base_color = {0: (102, 255, 34), 1: (255, 102, 0), 2: (255, 0, 51)}
    state_id = get_stateid(elt)
    color = base_color.get(state_id, (179, 196, 255))
    s_color = 'RGB(%d,%d,%d)' % color

    #pct = 100 * (v / m.max)
    # Convert to int
    #pct = int(pct)
    # Minimum 1%, maximum 100%
    #pct = min(max(1, pct), 100)
    lnk = '#'
    metrics = [(s_color, pct), ('white', 100-pct)]
    title = '%ss' % v
    #print "HTTP: return", {'lnk': lnk, 'metrics': metrics, 'title': title}
    return {'lnk': lnk, 'metrics': metrics, 'title': title}

def manage_unknown_command(elt, metric=None):
    logger.debug("[WebUI] perfometer, manage command for: %s, metric: %s", elt.get_full_name(), metric)
    p = PerfDatas(elt.perf_data)
    if len(p) == 0:
        return None

    # Got some override name we know to be ok for printing
    if metric is None and 'time' in p and p['time'].value is not None:
        metric = p['time']
    else:
        if metric is None:
            for v in p:
                if v.name is not None and v.value is not None:
                    metric = v
        else:
            for v in p:
                if v.name is not None and v.value is not None and v.name == metric:
                    metric = v

    if metric is None:
        return None

    name = metric.name
    value = metric.value
    logger.debug("[WebUI] perfometer, manage command, metric: %s=%d", name, value)
    if not value:
        return None

    pct = 0
    # If metric UOM is %
    if metric.uom and metric.uom == '%':
        # Return value
        pct = value
    # Look if min/max are defined
    elif metric.min and metric.max and (metric.max - metric.min != 0):
        pct = 100 * (value / (metric.max - metric.min))
    else:
        # Assume value is 100%
        pct = 100

    # Percentage is at least 1% and max 100%
    pct = max(1, pct)
    pct = min(pct, 100)

    # Title
    try:
        title = '%s%s' % (value, metric.uom)
    except:
        title = '%s' % (value)

    # Link
    lnk = '#'

    # Get the color
    base = {0: 'success', 1: 'warning', 2: 'danger', 3: 'info'}
    color = base.get(elt.state_id, 'info')

    logger.debug("[WebUI] perfometer, manage command, metric: %s=%d -> %d", name, value, pct)

    return {'lnk': lnk, 'metrics': [(color, pct)], 'title': title}

def get_stateid(elt):
    state_id = elt.state_id

    # For host, make DOWN as critical
    if state_id == 1 and elt.__class__.my_type == 'host':
        state_id = 2

    return state_id

def get_logarithmic(value, half):
    l_half = math.log(half, 10)
    print 'Half is', l_half
    l_value = math.log(value, 10)
    print "l value is", l_value
    # Get the percent of our value for what we asked for
    r = 50 + 10.0 * (l_value - l_half)
    # Make it an int between 1 and 100
    r = int(r)
    r = max(1, r)
    r = min(r, 100)

    return r
<commit_msg>bugfix when value is zero<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright (C) 2009-2012:
#    Gabes Jean, naparuba@gmail.com
#    Gerhard Lausser, Gerhard.Lausser@consol.de
#    Gregory Starck, g.starck@gmail.com
#    Hartmut Goebel, h.goebel@goebel-consult.de
#    Frederic Mohier, frederic.mohier@gmail.com
#
# This file is part of Shinken.
#
# Shinken 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.
#
# Shinken 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 Shinken.  If not, see <http://www.gnu.org/licenses/>.

import math

from shinken.misc.perfdata import PerfDatas
from shinken.log import logger

# Will try to return a dict with:
# lnk: link to add in this perfdata thing
# title: text to show on it
# metrics: list of ('html color', percent) like [('#68f', 35), ('white', 64)]
def get_perfometer_table_values(elt, metric=None):
    # first try to get the command name called
    cmd = elt.check_command.call.split('!')[0]
    logger.debug("[WebUI] Looking for perfometer value for element: %s, command: %s", elt.get_full_name(), cmd)

    tab = {'check_http': manage_check_http_command,
           'check_ping': manage_check_ping_command,
           'check_tcp': manage_check_tcp_command,
        }

    f = tab.get(cmd, None)
    if f:
        return f(elt, metric)

    try:
        r = manage_unknown_command(elt, metric)
    except:
        return None
    return r

def manage_check_http_command(elt, metric='time'):
    logger.debug("[WebUI] Get check_http perfdata of %s", elt.get_full_name())
    p = PerfDatas(elt.perf_data)
    if not metric in p:
        return None

    m = p[metric]
    v = m.value
    if not v:
        return None

    # Percent of ok should be time/1s
    pct = get_logarithmic(v, 1)
    # Now get the color
    # OK: #6f2 (102,255,34) green
    # Warning: #f60 (255,102,0) orange
    # Crit: #ff0033 (255,0,51)
    base_color = {0: (102, 255, 34), 1: (255, 102, 0), 2: (255, 0, 51)}
    state_id = get_stateid(elt)
    color = base_color.get(state_id, (179, 196, 255))
    s_color = 'RGB(%d,%d,%d)' % color
    lnk = '#'
    metrics = [(s_color, pct), ('white', 100-pct)]
    title = '%ss' % v
    #print "HTTP: return", {'lnk': lnk, 'metrics': metrics, 'title': title}
    return {'lnk': lnk, 'metrics': metrics, 'title': title}

def manage_check_ping_command(elt, metric='rta'):
    logger.debug("[WebUI] Get check_ping perfdata of %s", elt.get_full_name())
    p = PerfDatas(elt.perf_data)
    if not metric in p:
        return None

    m = p[metric]
    v = m.value
    crit = m.critical
    if not v or not crit:
        return None

    # Percent of ok should be the log of time versus max/2
    pct = get_logarithmic(v, crit / 2)
    # Now get the color
    # OK: #6f2 (102,255,34) green
    # Warning: #f60 (255,102,0) orange
    # Crit: #ff0033 (255,0,51)
    base_color = {0: (102, 255, 34), 1: (255, 102, 0), 2: (255, 0, 51)}
    state_id = get_stateid(elt)
    color = base_color.get(state_id, (179, 196, 255))
    s_color = 'RGB(%d,%d,%d)' % color

    lnk = '#'
    metrics = [(s_color, pct), ('white', 100-pct)]
    title = '%sms' % v
    #print "HTTP: return", {'lnk': lnk, 'metrics': metrics, 'title': title}
    return {'lnk': lnk, 'metrics': metrics, 'title': title}

def manage_check_tcp_command(elt, metric='time'):
    logger.debug("[WebUI] Get check_tcp perfdata of %s", elt.get_full_name())
    p = PerfDatas(elt.perf_data)
    if not metric in p:
        return None

    m = p[metric]
    v = m.value

    if not v or not m.max:
        return None

    # Percent of ok should be the log of time versus m.max / 2
    pct = get_logarithmic(v, m.max / 2)

    # Now get the color
    # OK: #6f2 (102,255,34) green
    # Warning: #f60 (255,102,0) orange
    # Crit: #ff0033 (255,0,51)
    base_color = {0: (102, 255, 34), 1: (255, 102, 0), 2: (255, 0, 51)}
    state_id = get_stateid(elt)
    color = base_color.get(state_id, (179, 196, 255))
    s_color = 'RGB(%d,%d,%d)' % color

    #pct = 100 * (v / m.max)
    # Convert to int
    #pct = int(pct)
    # Minimum 1%, maximum 100%
    #pct = min(max(1, pct), 100)
    lnk = '#'
    metrics = [(s_color, pct), ('white', 100-pct)]
    title = '%ss' % v
    #print "HTTP: return", {'lnk': lnk, 'metrics': metrics, 'title': title}
    return {'lnk': lnk, 'metrics': metrics, 'title': title}

def manage_unknown_command(elt, metric=None):
    logger.debug("[WebUI] perfometer, manage command for: %s, metric: %s", elt.get_full_name(), metric)
    p = PerfDatas(elt.perf_data)
    if len(p) == 0:
        return None

    # Got some override name we know to be ok for printing
    if metric is None and 'time' in p and p['time'].value is not None:
        metric = p['time']
    else:
        if metric is None:
            for v in p:
                if v.name is not None and v.value is not None:
                    metric = v
        else:
            for v in p:
                if v.name is not None and v.value is not None and v.name == metric:
                    metric = v

    if metric is None:
        return None

    name = metric.name
    value = metric.value
    logger.debug("[WebUI] perfometer, manage command, metric: %s=%d", name, value)
    if value is None:
        return None

    pct = 0
    # If metric UOM is %
    if metric.uom and metric.uom == '%':
        # Return value
        pct = value
    # Look if min/max are defined
    elif metric.min and metric.max and (metric.max - metric.min != 0):
        pct = 100 * (value / (metric.max - metric.min))
    else:
        # Assume value is 100%
        pct = 100

    # Percentage is at least 1% and max 100%
    pct = max(1, pct)
    pct = min(pct, 100)

    # Title
    try:
        title = '%s%s' % (value, metric.uom)
    except:
        title = '%s' % (value)

    # Link
    lnk = '#'

    # Get the color
    base = {0: 'success', 1: 'warning', 2: 'danger', 3: 'info'}
    color = base.get(elt.state_id, 'info')

    logger.debug("[WebUI] perfometer, manage command, metric: %s=%d -> %d", name, value, pct)

    return {'lnk': lnk, 'metrics': [(color, pct)], 'title': title}

def get_stateid(elt):
    state_id = elt.state_id

    # For host, make DOWN as critical
    if state_id == 1 and elt.__class__.my_type == 'host':
        state_id = 2

    return state_id

def get_logarithmic(value, half):
    l_half = math.log(half, 10)
    print 'Half is', l_half
    l_value = math.log(value, 10)
    print "l value is", l_value
    # Get the percent of our value for what we asked for
    r = 50 + 10.0 * (l_value - l_half)
    # Make it an int between 1 and 100
    r = int(r)
    r = max(1, r)
    r = min(r, 100)

    return r
<|endoftext|>


<commit_before>import unittest
import time

from cpy2py import kernel_state, TwinMaster, TwinObject
from cpy2py.utility.compat import rangex

class PyPyng(TwinObject):
    __twin_id__ = 'pypy_asnyc'

    def play(self, opponent, recursion=0):
        if recursion <= 0:
            return self.__class__.__name__
        return opponent.play(self, recursion-1)

class Pyng(PyPyng):
    __twin_id__ = kernel_state.MASTER_ID

class TestPingPongCall(unittest.TestCase):
    def setUp(self):
        self.twinterpreter = TwinMaster(executable='pypy', twinterpreter_id='pypy_asnyc', kernel='async')
        self.twinterpreter.start()

    def tearDown(self):
        self.twinterpreter.stop()
        time.sleep(0.1)

    def test_bounce_none(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        self.assertEqual(pypy_instance.__class__.__name__, pypy_instance.play(py_instance, 0))
        self.assertEqual(py_instance.__class__.__name__, py_instance.play(pypy_instance, 0))

    def test_bounce_one(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        self.assertEqual(py_instance.__class__.__name__, pypy_instance.play(py_instance, 1))
        self.assertEqual(pypy_instance.__class__.__name__, py_instance.play(pypy_instance, 1))

    def test_bounce_any(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        for bounces in rangex(1, 20, 2):
            self.assertEqual(py_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(pypy_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))
        for bounces in rangex(0, 20, 2):
            self.assertEqual(pypy_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(py_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))

    def test_bounce_lots(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        for bounces in rangex(1, 200, 20):
            self.assertEqual(py_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(pypy_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))
        for bounces in rangex(0, 200, 20):
            self.assertEqual(pypy_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(py_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))
<commit_msg>recursion test now adds keepalive for travis<commit_after>from __future__ import print_function
import unittest
import time

from cpy2py import kernel_state, TwinMaster, TwinObject
from cpy2py.utility.compat import rangex

class PyPyng(TwinObject):
    __twin_id__ = 'pypy_asnyc'

    def play(self, opponent, recursion=0):
        if recursion > 0 and recursion % 20 == 0:
            print('.', end='')
        if recursion <= 0:
            return self.__class__.__name__
        return opponent.play(self, recursion-1)

class Pyng(PyPyng):
    __twin_id__ = kernel_state.MASTER_ID

class TestPingPongCall(unittest.TestCase):
    def setUp(self):
        self.twinterpreter = TwinMaster(executable='pypy', twinterpreter_id='pypy_asnyc', kernel='async')
        self.twinterpreter.start()

    def tearDown(self):
        self.twinterpreter.stop()
        time.sleep(0.1)

    def test_bounce_none(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        self.assertEqual(pypy_instance.__class__.__name__, pypy_instance.play(py_instance, 0))
        self.assertEqual(py_instance.__class__.__name__, py_instance.play(pypy_instance, 0))

    def test_bounce_one(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        self.assertEqual(py_instance.__class__.__name__, pypy_instance.play(py_instance, 1))
        self.assertEqual(pypy_instance.__class__.__name__, py_instance.play(pypy_instance, 1))

    def test_bounce_any(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        for bounces in rangex(1, 20, 2):
            self.assertEqual(py_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(pypy_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))
        for bounces in rangex(0, 20, 2):
            self.assertEqual(pypy_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(py_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))

    def test_bounce_lots(self):
        pypy_instance = PyPyng()
        py_instance = Pyng()
        for bounces in rangex(1, 200, 20):
            self.assertEqual(py_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(pypy_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))
        for bounces in rangex(0, 200, 20):
            self.assertEqual(pypy_instance.__class__.__name__, pypy_instance.play(py_instance, bounces))
            self.assertEqual(py_instance.__class__.__name__, py_instance.play(pypy_instance, bounces))
<|endoftext|>


<commit_before>from __future__ import unicode_literals

# from django.db.models.signals import post_save, post_delete
from django.conf import settings
from django.dispatch import receiver
# from cms.models import Title
from cms.constants import PUBLISHER_STATE_DIRTY
from cms.signals import post_placeholder_operation, post_obj_operation, post_publish

from djangocms_misc.global_untranslated_placeholder.utils import get_untranslated_default_language

# published. if not default language, publish default as well
@receiver(
    post_publish,
    dispatch_uid="cms_global_untranslated_placeholder_post_publish",
)
def post_publish_handler(**kwargs):
    page_instance = kwargs.get('instance', None)
    if not page_instance:
        return
    published_language = kwargs.get('language', settings.LANGUAGE_CODE)
    default_language = get_untranslated_default_language()
    if not published_language == default_language:
        page_instance.publish(default_language)

# something has changed, if we are not on the default lang, mark current lang/title as dirty as well
@receiver(
    post_placeholder_operation,
    dispatch_uid="cms_global_untranslated_placeholder_post_placeholder_operation",
)
def post_placeholder_operation_handler(sender, operation, request, language, token, origin, **kwargs):
    if operation == 'change_plugin':
        plugin = kwargs.get('new_plugin', None)
    if not plugin:
        plugin = kwargs.get('plugin', None)
    if not plugin:
        plugin = kwargs.get('plugins', [None, ])[0]
    if plugin:
        placeholder = plugin.placeholder
        print plugin.language
        if not plugin.language == language:
            # mark plugin.language Title as dirty!
            if placeholder.page:
                title = placeholder.page.get_title_obj(language)
                title.publisher_state = PUBLISHER_STATE_DIRTY
                title.save()
<commit_msg>drafting publish issues for global untranslated placeholders<commit_after>from __future__ import unicode_literals

# from django.db.models.signals import post_save, post_delete
from django.conf import settings
from django.dispatch import receiver
# from cms.models import Title
from cms.constants import PUBLISHER_STATE_DIRTY
from cms.signals import post_placeholder_operation, post_obj_operation, post_publish

from djangocms_misc.global_untranslated_placeholder.utils import get_untranslated_default_language

# published. if not default language, publish default as well
@receiver(
    post_publish,
    dispatch_uid="cms_global_untranslated_placeholder_post_publish",
)
def post_publish_handler(**kwargs):
    page_instance = kwargs.get('instance', None)
    if not page_instance:
        return
    published_language = kwargs.get('language', settings.LANGUAGE_CODE)
    default_language = get_untranslated_default_language()
    if not published_language == default_language:
        page_instance.publish(default_language)

# something has changed, if we are not on the default lang, mark current lang/title as dirty as well
@receiver(
    post_placeholder_operation,
    dispatch_uid="cms_global_untranslated_placeholder_post_placeholder_operation",
)
def post_placeholder_operation_handler(sender, operation, request, language, token, origin, **kwargs):
    if operation == 'change_plugin':
        plugin = kwargs.get('new_plugin', None)
    if not plugin:
        plugin = kwargs.get('plugin', None)
    if not plugin:
        plugin = kwargs.get('plugins', [None, ])[0]
    if plugin:
        placeholder = plugin.placeholder
        if not plugin.language == language:
            # mark current language Title as dirty as well!
            if placeholder.page:
                title = placeholder.page.get_title_obj(language)
                title.publisher_state = PUBLISHER_STATE_DIRTY
                title.save()
<|endoftext|>