<commit_before>#!/usr/bin/env python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Run a pinned gsutil."""

import argparse
import base64
import contextlib
import hashlib
import json
import os
import shutil
import subprocess
import sys
import tempfile
import time

try:
  import urllib2 as urllib
except ImportError:  # For Py3 compatibility
  import urllib.request as urllib

import zipfile

GSUTIL_URL = 'https://storage.googleapis.com/pub/'
API_URL = 'https://www.googleapis.com/storage/v1/b/pub/o/'

THIS_DIR = os.path.dirname(os.path.abspath(__file__))
DEFAULT_BIN_DIR = os.path.join(THIS_DIR, 'external_bin', 'gsutil')
DEFAULT_FALLBACK_GSUTIL = os.path.join(
    THIS_DIR, 'third_party', 'gsutil', 'gsutil')

IS_WINDOWS = os.name == 'nt'

class InvalidGsutilError(Exception):
  pass

def download_gsutil(version, target_dir):
  """Downloads gsutil into the target_dir."""
  filename = 'gsutil_%s.zip' % version
  target_filename = os.path.join(target_dir, filename)

  # Check if the target exists already.
  if os.path.exists(target_filename):
    md5_calc = hashlib.md5()
    with open(target_filename, 'rb') as f:
      while True:
        buf = f.read(4096)
        if not buf:
          break
        md5_calc.update(buf)
    local_md5 = md5_calc.hexdigest()

    metadata_url = '%s%s' % (API_URL, filename)
    metadata = json.load(urllib.urlopen(metadata_url))
    remote_md5 = base64.b64decode(metadata['md5Hash']).decode('utf-8')

    if local_md5 == remote_md5:
      return target_filename
    os.remove(target_filename)

  # Do the download.
  url = '%s%s' % (GSUTIL_URL, filename)
  u = urllib.urlopen(url)
  with open(target_filename, 'wb') as f:
    while True:
      buf = u.read(4096)
      if not buf:
        break
      f.write(buf)
  return target_filename

@contextlib.contextmanager
def temporary_directory(base):
  tmpdir = tempfile.mkdtemp(prefix='gsutil_py', dir=base)
  try:
    yield tmpdir
  finally:
    if os.path.isdir(tmpdir):
      shutil.rmtree(tmpdir)

def ensure_gsutil(version, target, clean):
  bin_dir = os.path.join(target, 'gsutil_%s' % version)
  gsutil_bin = os.path.join(bin_dir, 'gsutil', 'gsutil')
  gsutil_flag = os.path.join(bin_dir, 'gsutil', 'install.flag')
  # We assume that if gsutil_flag exists, then we have a good version
  # of the gsutil package.
  if not clean and os.path.isfile(gsutil_flag):
    # Everything is awesome! we're all done here.
    return gsutil_bin

  if not os.path.exists(target):
    os.makedirs(target)
  with temporary_directory(target) as instance_dir:
    # Clean up if we're redownloading a corrupted gsutil.
    cleanup_path = os.path.join(instance_dir, 'clean')
    try:
      os.rename(bin_dir, cleanup_path)
    except (OSError, IOError):
      cleanup_path = None
    if cleanup_path:
      shutil.rmtree(cleanup_path)

    download_dir = os.path.join(instance_dir, 'download')
    target_zip_filename = download_gsutil(version, instance_dir)
    with zipfile.ZipFile(target_zip_filename, 'r') as target_zip:
      target_zip.extractall(download_dir)

    try:
      os.rename(download_dir, bin_dir)
    except (OSError, IOError):
      # Something else did this in parallel.
      pass
    # Final check that the gsutil bin exists.  This should never fail.
    if not os.path.isfile(gsutil_bin):
      raise InvalidGsutilError()
    # Drop a flag file.
    with open(gsutil_flag, 'w') as f:
      f.write('This flag file is dropped by gsutil.py')

  return gsutil_bin

def run_gsutil(force_version, fallback, target, args, clean=False):
  if force_version:
    gsutil_bin = ensure_gsutil(force_version, target, clean)
  else:
    gsutil_bin = fallback
  disable_update = ['-o', 'GSUtil:software_update_check_period=0']

  if sys.platform == 'cygwin':
    # This script requires Windows Python, so invoke with depot_tools'
    # Python.
    def winpath(path):
      stdout = subprocess.check_output(['cygpath', '-w', path])
      return stdout.strip().decode('utf-8', 'replace')
    cmd = ['python.bat', winpath(__file__)]
    cmd.extend(args)
    sys.exit(subprocess.call(cmd))
  assert sys.platform != 'cygwin'

  # Run "gsutil" through "vpython". We need to do this because on GCE instances,
  # expectations are made about Python having access to "google-compute-engine"
  # and "boto" packages that are not met with non-system Python (e.g., bundles).
  cmd = [
      'vpython',
      '-vpython-spec', os.path.join(THIS_DIR, 'gsutil.vpython'),
      '--',
      gsutil_bin
  ] + disable_update + args
  return subprocess.call(cmd, shell=IS_WINDOWS)

def parse_args():
  bin_dir = os.environ.get('DEPOT_TOOLS_GSUTIL_BIN_DIR', DEFAULT_BIN_DIR)

  parser = argparse.ArgumentParser()
  parser.add_argument('--force-version', default='4.30')
  parser.add_argument('--clean', action='store_true',
      help='Clear any existing gsutil package, forcing a new download.')
  parser.add_argument('--fallback', default=DEFAULT_FALLBACK_GSUTIL)
  parser.add_argument('--target', default=bin_dir,
      help='The target directory to download/store a gsutil version in. '
           '(default is %(default)s).')
  parser.add_argument('args', nargs=argparse.REMAINDER)

  args, extras = parser.parse_known_args()
  if args.args and args.args[0] == '--':
    args.args.pop(0)
  if extras:
    args.args = extras + args.args
  return args

def main():
  args = parse_args()
  return run_gsutil(args.force_version, args.fallback, args.target, args.args,
                    clean=args.clean)

if __name__ == '__main__':
  sys.exit(main())
<commit_msg>Switch gsutil.py to py3<commit_after>#!/usr/bin/env python3
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Run a pinned gsutil."""

import argparse
import base64
import contextlib
import hashlib
import json
import os
import shutil
import subprocess
import sys
import tempfile
import time

try:
  import urllib2 as urllib
except ImportError:  # For Py3 compatibility
  import urllib.request as urllib

import zipfile

GSUTIL_URL = 'https://storage.googleapis.com/pub/'
API_URL = 'https://www.googleapis.com/storage/v1/b/pub/o/'

THIS_DIR = os.path.dirname(os.path.abspath(__file__))
DEFAULT_BIN_DIR = os.path.join(THIS_DIR, 'external_bin', 'gsutil')
DEFAULT_FALLBACK_GSUTIL = os.path.join(
    THIS_DIR, 'third_party', 'gsutil', 'gsutil')

IS_WINDOWS = os.name == 'nt'

class InvalidGsutilError(Exception):
  pass

def download_gsutil(version, target_dir):
  """Downloads gsutil into the target_dir."""
  filename = 'gsutil_%s.zip' % version
  target_filename = os.path.join(target_dir, filename)

  # Check if the target exists already.
  if os.path.exists(target_filename):
    md5_calc = hashlib.md5()
    with open(target_filename, 'rb') as f:
      while True:
        buf = f.read(4096)
        if not buf:
          break
        md5_calc.update(buf)
    local_md5 = md5_calc.hexdigest()

    metadata_url = '%s%s' % (API_URL, filename)
    metadata = json.load(urllib.urlopen(metadata_url))
    remote_md5 = base64.b64decode(metadata['md5Hash']).decode('utf-8')

    if local_md5 == remote_md5:
      return target_filename
    os.remove(target_filename)

  # Do the download.
  url = '%s%s' % (GSUTIL_URL, filename)
  u = urllib.urlopen(url)
  with open(target_filename, 'wb') as f:
    while True:
      buf = u.read(4096)
      if not buf:
        break
      f.write(buf)
  return target_filename

@contextlib.contextmanager
def temporary_directory(base):
  tmpdir = tempfile.mkdtemp(prefix='gsutil_py', dir=base)
  try:
    yield tmpdir
  finally:
    if os.path.isdir(tmpdir):
      shutil.rmtree(tmpdir)

def ensure_gsutil(version, target, clean):
  bin_dir = os.path.join(target, 'gsutil_%s' % version)
  gsutil_bin = os.path.join(bin_dir, 'gsutil', 'gsutil')
  gsutil_flag = os.path.join(bin_dir, 'gsutil', 'install.flag')
  # We assume that if gsutil_flag exists, then we have a good version
  # of the gsutil package.
  if not clean and os.path.isfile(gsutil_flag):
    # Everything is awesome! we're all done here.
    return gsutil_bin

  if not os.path.exists(target):
    os.makedirs(target)
  with temporary_directory(target) as instance_dir:
    # Clean up if we're redownloading a corrupted gsutil.
    cleanup_path = os.path.join(instance_dir, 'clean')
    try:
      os.rename(bin_dir, cleanup_path)
    except (OSError, IOError):
      cleanup_path = None
    if cleanup_path:
      shutil.rmtree(cleanup_path)

    download_dir = os.path.join(instance_dir, 'download')
    target_zip_filename = download_gsutil(version, instance_dir)
    with zipfile.ZipFile(target_zip_filename, 'r') as target_zip:
      target_zip.extractall(download_dir)

    try:
      os.rename(download_dir, bin_dir)
    except (OSError, IOError):
      # Something else did this in parallel.
      pass
    # Final check that the gsutil bin exists.  This should never fail.
    if not os.path.isfile(gsutil_bin):
      raise InvalidGsutilError()
    # Drop a flag file.
    with open(gsutil_flag, 'w') as f:
      f.write('This flag file is dropped by gsutil.py')

  return gsutil_bin

def run_gsutil(force_version, fallback, target, args, clean=False):
  if force_version:
    gsutil_bin = ensure_gsutil(force_version, target, clean)
  else:
    gsutil_bin = fallback
  disable_update = ['-o', 'GSUtil:software_update_check_period=0']

  if sys.platform == 'cygwin':
    # This script requires Windows Python, so invoke with depot_tools'
    # Python.
    def winpath(path):
      stdout = subprocess.check_output(['cygpath', '-w', path])
      return stdout.strip().decode('utf-8', 'replace')
    cmd = ['python.bat', winpath(__file__)]
    cmd.extend(args)
    sys.exit(subprocess.call(cmd))
  assert sys.platform != 'cygwin'

  # Run "gsutil" through "vpython". We need to do this because on GCE instances,
  # expectations are made about Python having access to "google-compute-engine"
  # and "boto" packages that are not met with non-system Python (e.g., bundles).
  cmd = [
      'vpython',
      '-vpython-spec', os.path.join(THIS_DIR, 'gsutil.vpython'),
      '--',
      gsutil_bin
  ] + disable_update + args
  return subprocess.call(cmd, shell=IS_WINDOWS)

def parse_args():
  bin_dir = os.environ.get('DEPOT_TOOLS_GSUTIL_BIN_DIR', DEFAULT_BIN_DIR)

  parser = argparse.ArgumentParser()
  parser.add_argument('--force-version', default='4.30')
  parser.add_argument('--clean', action='store_true',
      help='Clear any existing gsutil package, forcing a new download.')
  parser.add_argument('--fallback', default=DEFAULT_FALLBACK_GSUTIL)
  parser.add_argument('--target', default=bin_dir,
      help='The target directory to download/store a gsutil version in. '
           '(default is %(default)s).')
  parser.add_argument('args', nargs=argparse.REMAINDER)

  args, extras = parser.parse_known_args()
  if args.args and args.args[0] == '--':
    args.args.pop(0)
  if extras:
    args.args = extras + args.args
  return args

def main():
  args = parse_args()
  return run_gsutil(args.force_version, args.fallback, args.target, args.args,
                    clean=args.clean)

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


<commit_before># -*- coding: utf-8 -*-
import os
import re

from itertools import chain, product

import sublime
import sublime_plugin

def import_dir(name, fromlist=()):
    PACKAGE_EXT = '.sublime-package'
    dirname = os.path.basename(os.path.dirname(os.path.realpath(__file__)))
    if dirname.endswith(PACKAGE_EXT):
        dirname = dirname[:-len(PACKAGE_EXT)]
    return __import__('{0}.{1}'.format(dirname, name), fromlist=fromlist)

try:
    extract = import_dir('probe', ('extract',)).extract
except ImportError:
    from probe import extract

try:
    make_template = import_dir('templates', ('make_template',)).make_template
except ImportError:
    from templates import make_template

try:
    get_hayaku_options = import_dir('add_code_block', ('add_code_block',)).get_hayaku_options
except ImportError:
    from add_code_block import get_hayaku_options

try:
    get_values_by_property = import_dir('css_dict_driver', ('get_values_by_property',)).get_values_by_property
except ImportError:
    from css_dict_driver import get_values_by_property

# The maximum size of a single propery to limit the lookbehind
MAX_SIZE_CSS = len('-webkit-transition-timing-function')

ABBR_REGEX = re.compile(r'[\s|;|{]([\.:%#a-z-,\d]+!?)$', re.IGNORECASE)

class HayakuCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        cur_pos = self.view.sel()[0].begin()
        start_pos = cur_pos - MAX_SIZE_CSS
        if start_pos < 0:
            start_pos = 0
        # TODO: Move this to the contexts, it's not needed here
        probably_abbr = self.view.substr(sublime.Region(start_pos, cur_pos))
        match = ABBR_REGEX.search(probably_abbr)
        if match is None:
            self.view.insert(edit, cur_pos, '\t')
            return

        abbr = match.group(1)

        # Extracting the data from the abbr
        args = extract(abbr)

        if not args:
            return

        # Getting the options and making a snippet
        # from the extracted data
        get_hayaku_options(self)
        options = get_hayaku_options(self)
        template = make_template(args, options, sublime.get_clipboard())

        if template is None:
            return

        # Inserting the snippet
        new_cur_pos = cur_pos - len(abbr)
        assert cur_pos - len(abbr) >= 0
        self.view.erase(edit, sublime.Region(new_cur_pos, cur_pos))

        self.view.run_command("insert_snippet", {"contents": template})

# Helpers for getting the right indent for the Add Line Command
WHITE_SPACE_FINDER = re.compile(r'^(\s*)(-)?[\w]*')
def get_line_indent(line):
    return WHITE_SPACE_FINDER.match(line).group(1)

def is_prefixed_property(line):
    return WHITE_SPACE_FINDER.match(line).group(2) is not None

def get_previous_line(view, line_region):
    return view.line(line_region.a - 1)

def get_nearest_indent(view):
    line_region = view.line(view.sel()[0])
    line = view.substr(line_region)
    line_prev_region = get_previous_line(view,line_region)

    found_indent = None
    first_indent = None
    first_is_ok = True
    is_nested = False

    # Can we do smth with all those if-else noodles?
    if not is_prefixed_property(line):
        first_indent = get_line_indent(line)
        if not is_prefixed_property(view.substr(line_prev_region)):
            return first_indent
        if is_prefixed_property(view.substr(line_prev_region)):
            first_is_ok = False
    while not found_indent and line_prev_region != view.line(sublime.Region(0)):
        line_prev = view.substr(line_prev_region)
        if not first_indent:
            if not is_prefixed_property(line_prev):
                first_indent = get_line_indent(line_prev)
                if is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                    first_is_ok = False
        else:
            if not is_prefixed_property(line_prev) and not is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                found_indent = min(first_indent,get_line_indent(line_prev))

        line_prev_region = get_previous_line(view,line_prev_region)
        if line_prev.count("{"):
            is_nested = True

    if found_indent and found_indent < first_indent and not is_prefixed_property(view.substr(get_previous_line(view,line_region))) and first_is_ok or is_nested:
        found_indent = found_indent + "    "

    if not found_indent:
        if first_indent:
            found_indent = first_indent
        else:
            found_indent = ""
    return found_indent

class HayakuAddLineCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        nearest_indent = get_nearest_indent(self.view)

        # Saving current auto_indent setting
        # This hack fixes ST2's bug with incorrect auto_indent for snippets
        # It seems that with auto indent off it uses right auto_indent there lol.
        current_auto_indent = self.view.settings().get("auto_indent")
        self.view.settings().set("auto_indent",False)

        self.view.run_command('insert', {"characters": "\n"})
        self.view.erase(edit, sublime.Region(self.view.line(self.view.sel()[0]).a, self.view.sel()[0].a))
        self.view.run_command('insert', {"characters": nearest_indent})
        self.view.settings().set("auto_indent",current_auto_indent)

class HayakuCyclingThroughValues(sublime_plugin.TextCommand):
    def run(self, edit, direction, amount = 1):
        # Store the arguments
        self.edit = edit
        self.direction = direction
        self.amount = amount
        self.dirty_regions = []
        regions = enumerate(self.view.sel())

        for index, region in regions:
            self.region = region
            self.region_index = index

            # Check if the current region was in the area where the first one made changes to
            should_proceed = True
            for dirty_region in self.dirty_regions:
                if dirty_region.intersects(region):
                    should_proceed = False

            if should_proceed:
                self.handle_region()

    def handle_region(self):
        result = self.do_actual_stuff()
        if not result:
            return False

        # TODO: check if the region is multiline, do nothing in that case, or?

        region, text = result

        self.dirty_regions.append(region)

        # Get the proper offsets according to the rules
        old_position = self.view.sel()[self.region_index]
        offset = len(text) - len(self.view.substr(region))
        offset_start = old_position.begin()
        offset_end = old_position.end()
        region_range = range(region.begin() + 1, region.end())
        if old_position.begin() >= region.end():
            offset_start = offset_start + offset
        elif offset_start in region_range:
            offset_start = offset_start + offset
            if offset_start < region.begin():
                offset_start = region.begin()
        if old_position.end() >= region.end():
            offset_end = offset_end + offset
        elif offset_end in region_range:
            offset_end = offset_end + offset
            if offset_end < region.begin():
                offset_end = region.begin()

        new_position = sublime.Region(offset_start, offset_end)
        position_changed = old_position != new_position
        if position_changed:
            self.view.sel().subtract(old_position)
        self.view.replace(self.edit, region, text)
        if position_changed:
            self.view.sel().add(new_position)

    def do_actual_stuff(self):
        # 0. Getting the context
        region_begin = self.region.begin()
        region_end = self.region.end()

        line_region = self.view.line(self.region)
        line = self.view.substr(line_region)
        line_begin = line_region.begin()
        line_end = line_region.end()

        selection = self.view.substr(self.region)

        # 1. TODO: See if we're at CSS scope and stuff
        # https://github.com/hayaku/hayaku/wiki/Cycling-values
        if True:
            # Getting the proper context out of possible multiple declarations
            # TODO: handle multiline props, when lines ending with `[,\]`, etc?
            # TODO: handle selection somehow
            context_begin = line_begin
            declarations = re.findall(r'([^;]+;?)', line)
            context = None
            for declaration in declarations:
                proper_declaration = not re.match(r'^\s*\/\*|^\W+$', declaration)
                current_declaration = region_begin in range(context_begin, context_begin + len(declaration))

                if proper_declaration:
                    context = declaration

                if current_declaration:
                    if proper_declaration:
                        break
                    else:
                        context_begin = context_begin + len(declaration)

            # Parsed declaration                    prefix        property       delimiter    values
            parsed_declaration = re.search(r'^(\s*)(-[a-zA-Z]+-)?([a-zA-Z0-9-]+)(\s*(?: |\:))((?:(?!\!important).)+)', context)
            context_at_values = region_begin not in range(context_begin, context_begin + parsed_declaration.start(5))
            context_begin = context_begin + parsed_declaration.start(5)

            values = re.finditer(r'([^ ,\(\);]+)', parsed_declaration.group(5))
            prefix = parsed_declaration.group(2)
            prop = parsed_declaration.group(3)
            value = None
            value_context = None
            previous_value = None
            previous_value_begin = None
            previous_value_end = context_begin
            for subvalue in values:
                current_value = subvalue.group(1)
                initial_current_value_begin = context_begin + subvalue.start(1)
                # Adjust begin to the half of the gap with previous item
                current_value_begin = initial_current_value_begin - (initial_current_value_begin - previous_value_end + 1) // 2
                current_value_end = context_begin + subvalue.end(1) + 1

                if not value:
                    value = current_value
                    value_context = initial_current_value_begin
                else:
                    if region_begin in range(previous_value_end, current_value_begin):
                        value = previous_value
                        value_context = previous_value_begin
                        break
                    elif region_begin in range(current_value_begin, current_value_end):
                        value = current_value
                        value_context = initial_current_value_begin
                        break

                previous_value = current_value
                previous_value_end = current_value_end
                previous_value_begin = initial_current_value_begin

        props_values = get_values_by_property(prop)
        index = props_values.index(str(value))
        value_region = sublime.Region(value_context, value_context + len(value))
        assert self.direction in ('up', 'down')
        if self.direction == 'up':
            index += 1
        elif self.direction == 'down':
            index -= 1

        return [value_region, props_values[index % len(props_values)]]
<commit_msg>Check if the region is multiline<commit_after># -*- coding: utf-8 -*-
import os
import re

from itertools import chain, product

import sublime
import sublime_plugin

def import_dir(name, fromlist=()):
    PACKAGE_EXT = '.sublime-package'
    dirname = os.path.basename(os.path.dirname(os.path.realpath(__file__)))
    if dirname.endswith(PACKAGE_EXT):
        dirname = dirname[:-len(PACKAGE_EXT)]
    return __import__('{0}.{1}'.format(dirname, name), fromlist=fromlist)

try:
    extract = import_dir('probe', ('extract',)).extract
except ImportError:
    from probe import extract

try:
    make_template = import_dir('templates', ('make_template',)).make_template
except ImportError:
    from templates import make_template

try:
    get_hayaku_options = import_dir('add_code_block', ('add_code_block',)).get_hayaku_options
except ImportError:
    from add_code_block import get_hayaku_options

try:
    get_values_by_property = import_dir('css_dict_driver', ('get_values_by_property',)).get_values_by_property
except ImportError:
    from css_dict_driver import get_values_by_property

# The maximum size of a single propery to limit the lookbehind
MAX_SIZE_CSS = len('-webkit-transition-timing-function')

ABBR_REGEX = re.compile(r'[\s|;|{]([\.:%#a-z-,\d]+!?)$', re.IGNORECASE)

class HayakuCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        cur_pos = self.view.sel()[0].begin()
        start_pos = cur_pos - MAX_SIZE_CSS
        if start_pos < 0:
            start_pos = 0
        # TODO: Move this to the contexts, it's not needed here
        probably_abbr = self.view.substr(sublime.Region(start_pos, cur_pos))
        match = ABBR_REGEX.search(probably_abbr)
        if match is None:
            self.view.insert(edit, cur_pos, '\t')
            return

        abbr = match.group(1)

        # Extracting the data from the abbr
        args = extract(abbr)

        if not args:
            return

        # Getting the options and making a snippet
        # from the extracted data
        get_hayaku_options(self)
        options = get_hayaku_options(self)
        template = make_template(args, options, sublime.get_clipboard())

        if template is None:
            return

        # Inserting the snippet
        new_cur_pos = cur_pos - len(abbr)
        assert cur_pos - len(abbr) >= 0
        self.view.erase(edit, sublime.Region(new_cur_pos, cur_pos))

        self.view.run_command("insert_snippet", {"contents": template})

# Helpers for getting the right indent for the Add Line Command
WHITE_SPACE_FINDER = re.compile(r'^(\s*)(-)?[\w]*')
def get_line_indent(line):
    return WHITE_SPACE_FINDER.match(line).group(1)

def is_prefixed_property(line):
    return WHITE_SPACE_FINDER.match(line).group(2) is not None

def get_previous_line(view, line_region):
    return view.line(line_region.a - 1)

def get_nearest_indent(view):
    line_region = view.line(view.sel()[0])
    line = view.substr(line_region)
    line_prev_region = get_previous_line(view,line_region)

    found_indent = None
    first_indent = None
    first_is_ok = True
    is_nested = False

    # Can we do smth with all those if-else noodles?
    if not is_prefixed_property(line):
        first_indent = get_line_indent(line)
        if not is_prefixed_property(view.substr(line_prev_region)):
            return first_indent
        if is_prefixed_property(view.substr(line_prev_region)):
            first_is_ok = False
    while not found_indent and line_prev_region != view.line(sublime.Region(0)):
        line_prev = view.substr(line_prev_region)
        if not first_indent:
            if not is_prefixed_property(line_prev):
                first_indent = get_line_indent(line_prev)
                if is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                    first_is_ok = False
        else:
            if not is_prefixed_property(line_prev) and not is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                found_indent = min(first_indent,get_line_indent(line_prev))

        line_prev_region = get_previous_line(view,line_prev_region)
        if line_prev.count("{"):
            is_nested = True

    if found_indent and found_indent < first_indent and not is_prefixed_property(view.substr(get_previous_line(view,line_region))) and first_is_ok or is_nested:
        found_indent = found_indent + "    "

    if not found_indent:
        if first_indent:
            found_indent = first_indent
        else:
            found_indent = ""
    return found_indent

class HayakuAddLineCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        nearest_indent = get_nearest_indent(self.view)

        # Saving current auto_indent setting
        # This hack fixes ST2's bug with incorrect auto_indent for snippets
        # It seems that with auto indent off it uses right auto_indent there lol.
        current_auto_indent = self.view.settings().get("auto_indent")
        self.view.settings().set("auto_indent",False)

        self.view.run_command('insert', {"characters": "\n"})
        self.view.erase(edit, sublime.Region(self.view.line(self.view.sel()[0]).a, self.view.sel()[0].a))
        self.view.run_command('insert', {"characters": nearest_indent})
        self.view.settings().set("auto_indent",current_auto_indent)

class HayakuCyclingThroughValues(sublime_plugin.TextCommand):
    def run(self, edit, direction, amount = 1):
        # Store the arguments
        self.edit = edit
        self.direction = direction
        self.amount = amount
        self.dirty_regions = []
        regions = enumerate(self.view.sel())

        for index, region in regions:
            self.region = region
            self.region_index = index

            # Check if the current region was in the area where the first one made changes to
            should_proceed = True
            for dirty_region in self.dirty_regions:
                if dirty_region.intersects(region):
                    should_proceed = False

            # Check if the region is multiline
            if self.view.line(self.region) != self.view.line(self.region.begin()):
                should_proceed = False

            if should_proceed:
                self.handle_region()

    def handle_region(self):
        result = self.do_actual_stuff()
        if not result:
            return False

        region, text = result
        self.dirty_regions.append(region)

        # Get the proper offsets according to the rules
        old_position = self.view.sel()[self.region_index]
        offset = len(text) - len(self.view.substr(region))
        offset_start = old_position.begin()
        offset_end = old_position.end()
        region_range = range(region.begin() + 1, region.end())
        if old_position.begin() >= region.end():
            offset_start = offset_start + offset
        elif offset_start in region_range:
            offset_start = offset_start + offset
            if offset_start < region.begin():
                offset_start = region.begin()
        if old_position.end() >= region.end():
            offset_end = offset_end + offset
        elif offset_end in region_range:
            offset_end = offset_end + offset
            if offset_end < region.begin():
                offset_end = region.begin()

        new_position = sublime.Region(offset_start, offset_end)
        position_changed = old_position != new_position
        if position_changed:
            self.view.sel().subtract(old_position)
        self.view.replace(self.edit, region, text)
        if position_changed:
            self.view.sel().add(new_position)

    def do_actual_stuff(self):
        # 0. Getting the context
        region_begin = self.region.begin()
        region_end = self.region.end()

        line_region = self.view.line(self.region)
        line = self.view.substr(line_region)
        line_begin = line_region.begin()
        line_end = line_region.end()

        selection = self.view.substr(self.region)

        # 1. TODO: See if we're at CSS scope and stuff
        # https://github.com/hayaku/hayaku/wiki/Cycling-values
        if True:
            # Getting the proper context out of possible multiple declarations
            # TODO: handle multiline props, when lines ending with `[,\]`, etc?
            # TODO: handle selection somehow
            context_begin = line_begin
            declarations = re.findall(r'([^;]+;?)', line)
            context = None
            for declaration in declarations:
                proper_declaration = not re.match(r'^\s*\/\*|^\W+$', declaration)
                current_declaration = region_begin in range(context_begin, context_begin + len(declaration))

                if proper_declaration:
                    context = declaration

                if current_declaration:
                    if proper_declaration:
                        break
                    else:
                        context_begin = context_begin + len(declaration)

            # Parsed declaration                    prefix        property       delimiter    values
            parsed_declaration = re.search(r'^(\s*)(-[a-zA-Z]+-)?([a-zA-Z0-9-]+)(\s*(?: |\:))((?:(?!\!important).)+)', context)
            context_at_values = region_begin not in range(context_begin, context_begin + parsed_declaration.start(5))
            context_begin = context_begin + parsed_declaration.start(5)

            values = re.finditer(r'([^ ,\(\);]+)', parsed_declaration.group(5))
            prefix = parsed_declaration.group(2)
            prop = parsed_declaration.group(3)
            value = None
            value_context = None
            previous_value = None
            previous_value_begin = None
            previous_value_end = context_begin
            for subvalue in values:
                current_value = subvalue.group(1)
                initial_current_value_begin = context_begin + subvalue.start(1)
                # Adjust begin to the half of the gap with previous item
                current_value_begin = initial_current_value_begin - (initial_current_value_begin - previous_value_end + 1) // 2
                current_value_end = context_begin + subvalue.end(1) + 1

                if not value:
                    value = current_value
                    value_context = initial_current_value_begin
                else:
                    if region_begin in range(previous_value_end, current_value_begin):
                        value = previous_value
                        value_context = previous_value_begin
                        break
                    elif region_begin in range(current_value_begin, current_value_end):
                        value = current_value
                        value_context = initial_current_value_begin
                        break

                previous_value = current_value
                previous_value_end = current_value_end
                previous_value_begin = initial_current_value_begin

        props_values = get_values_by_property(prop)
        index = props_values.index(str(value))
        value_region = sublime.Region(value_context, value_context + len(value))
        assert self.direction in ('up', 'down')
        if self.direction == 'up':
            index += 1
        elif self.direction == 'down':
            index -= 1

        return [value_region, props_values[index % len(props_values)]]
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import re
import sublime
import sublime_plugin

from core.probe import extract
from core.templates import make_template

__all__ = [
    'HayakuCommand',
]

# The maximum size of a single propery to limit the lookbehind
MAX_SIZE_CSS = len('-webkit-transition-timing-function')

ABBR_REGEX = re.compile(r'[\s|;|{]([\.:%#a-z-,\d]+!?)$', re.IGNORECASE)

# Guessing the codestyle             1     2    3            4    5         6    7     8    9
GUESS_REGEX = re.compile(r'selector(\s*)(\{)?(\s*)property(:)?(\s*)value(;)?(\s*)(\})?(\s*)', re.IGNORECASE)

def get_hayaku_options(self):
    # Autoguessing the options
    settings = self.view.settings()
    options = {}
    match = {}
    if settings.get("hayaku_CSS_syntax_autoguess"):
        autoguess = settings.get("hayaku_CSS_syntax_autoguess")
        offset = len(autoguess[0]) - len(autoguess[0].lstrip())
        autoguess = [ s[offset:].rstrip() for s in autoguess]

        match = GUESS_REGEX.search('\n'.join(autoguess))

    def get_setting(setting, fallback, match_group = False):
        if match_group and match:
            fallback = match.group(match_group)
        single_setting = False
        if settings.has("hayaku_" + setting):
            single_setting = settings.get("hayaku_" + setting, fallback)
        options[setting] = single_setting or fallback

    scope_name = self.view.scope_name(self.view.sel()[0].a)
    is_sass = sublime.score_selector(scope_name, 'source.sass') > 0
    is_stylus = sublime.score_selector(scope_name, 'source.stylus') > 0

    disable_braces = is_stylus or is_sass
    if is_stylus and match and match.group(2) and match.group(8):
        disable_braces = False

    disable_colons = is_stylus
    if match and match.group(4):
        disable_colons = False

    disable_semicolons = is_stylus or is_sass
    if is_stylus and match and match.group(6):
        disable_semicolons = False

    get_setting("CSS_whitespace_block_start_before", " ",    1 )
    get_setting("CSS_whitespace_block_start_after",  "\n\t", 3 )
    get_setting("CSS_whitespace_block_end_before",   "\n",   7 )
    get_setting("CSS_whitespace_block_end_after",    "",     9 )
    get_setting("CSS_whitespace_after_colon",        " ",    5 )
    get_setting("CSS_syntax_no_curly_braces",        disable_braces )
    get_setting("CSS_syntax_no_colons",              disable_colons )
    get_setting("CSS_syntax_no_semicolons",          disable_semicolons )
    get_setting("CSS_prefixes_disable",              False     )
    get_setting("CSS_prefixes_align",                not (is_stylus or is_sass) )
    get_setting("CSS_prefixes_only",                 []        )
    get_setting("CSS_prefixes_no_unprefixed",        False     )
    get_setting("CSS_disable_postexpand",            False     )
    get_setting("CSS_colors_case",                   "uppercase" ) # or "lowercase" or "initial"
    get_setting("CSS_colors_length",                 "short"   )   # or "long"      or "initial"

    return options

class HayakuCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        cur_pos = self.view.sel()[0].begin()
        start_pos = cur_pos - MAX_SIZE_CSS
        if start_pos < 0:
            start_pos = 0
        probably_abbr = self.view.substr(sublime.Region(start_pos, cur_pos))
        match = ABBR_REGEX.search(probably_abbr)
        if match is None:
            self.view.insert(edit, cur_pos, '\t')
            return

        abbr = match.group(1)

        # Extracting the data from the abbr
        args = extract(abbr)

        if not args:
            return

        # Getting the options and making a snippet
        # from the extracted data
        get_hayaku_options(self)
        options = get_hayaku_options(self)
        template = make_template(args, options)

        if template is None:
            return

        new_cur_pos = cur_pos - len(abbr)
        assert cur_pos - len(abbr) >= 0
        self.view.erase(edit, sublime.Region(new_cur_pos, cur_pos))
        self.view.run_command("insert_snippet", {"contents": template})

# Helpers for getting the right indent for the Add Line Command
WHITE_SPACE_FINDER = re.compile(r'^(\s*)(-)?[\w]*')
def get_line_indent(line):
    return WHITE_SPACE_FINDER.match(line).group(1)

def is_prefixed_property(line):
    return WHITE_SPACE_FINDER.match(line).group(2) is not None

def get_previous_line(view, line_region):
    return view.line(line_region.a - 1)

def get_nearest_indent(view):
    line_region = view.line(view.sel()[0])
    line = view.substr(line_region)
    line_prev_region = get_previous_line(view,line_region)

    found_indent = None
    first_indent = None
    first_is_ok = True
    is_nested = False
    if not is_prefixed_property(line):
        first_indent = get_line_indent(line)
        if not is_prefixed_property(view.substr(line_prev_region)):
            return first_indent
        if is_prefixed_property(view.substr(line_prev_region)):
            first_is_ok = False
    while not found_indent and line_prev_region != view.line(sublime.Region(0)):
        line_prev = view.substr(line_prev_region)
        if not first_indent:
            if not is_prefixed_property(line_prev):
                first_indent = get_line_indent(line_prev)
                if is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                    first_is_ok = False
        else:
            if not is_prefixed_property(line_prev) and not is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                found_indent = min(first_indent,get_line_indent(line_prev))

        line_prev_region = get_previous_line(view,line_prev_region)
        if line_prev.count("{"):
            is_nested = True

    if found_indent < first_indent and not is_prefixed_property(view.substr(get_previous_line(view,line_region))) and first_is_ok or is_nested:
        found_indent = found_indent + "    "

    if not found_indent:
        if first_indent:
            found_indent = first_indent
        else:
            found_indent = ""
    return found_indent

class HayakuAddLineCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        regions = self.view.sel()
        nearest_indent = get_nearest_indent(self.view)
        if len(regions) > 1:
            align_regions = (self.view.line(r) for r in regions)
            strings = (self.view.substr(r) for r in align_regions)
            finders = (WHITE_SPACE_FINDER.search(s) for s in strings)
            min_size = min(len(g.group(1)) for g in finders if g is not None)
            max_pos = max(r.end() for r in regions)
            self.view.sel().clear()
            self.view.sel().add(sublime.Region(max_pos, max_pos))
            self.view.run_command('insert', {"characters": "\n"})
            erase_region = self.view.line(self.view.sel()[0])
            reg = sublime.Region(erase_region.a + min_size, erase_region.b)
            self.view.erase(edit, reg)
        else:
            self.view.run_command('insert', {"characters": "\n"})
            self.view.erase(edit, sublime.Region(self.view.line(self.view.sel()[0]).a, self.view.sel()[0].a))
            self.view.run_command('insert', {"characters": nearest_indent})
<commit_msg>More comments, removed unneded stuff, minor bug fixed<commit_after># -*- coding: utf-8 -*-
import re
import sublime
import sublime_plugin

from core.probe import extract
from core.templates import make_template

__all__ = [
    'HayakuCommand',
]

# The maximum size of a single propery to limit the lookbehind
MAX_SIZE_CSS = len('-webkit-transition-timing-function')

ABBR_REGEX = re.compile(r'[\s|;|{]([\.:%#a-z-,\d]+!?)$', re.IGNORECASE)

# Guessing the codestyle             1     2    3            4    5         6    7     8    9
GUESS_REGEX = re.compile(r'selector(\s*)(\{)?(\s*)property(:)?(\s*)value(;)?(\s*)(\})?(\s*)', re.IGNORECASE)

def get_hayaku_options(self):
    settings = self.view.settings()
    options = {}
    match = {}
    # Autoguessing the options
    if settings.get("hayaku_CSS_syntax_autoguess"):
        autoguess = settings.get("hayaku_CSS_syntax_autoguess")
        offset = len(autoguess[0]) - len(autoguess[0].lstrip())
        autoguess = [ s[offset:].rstrip() for s in autoguess]

        match = GUESS_REGEX.search('\n'.join(autoguess))

    # Helper to set an option got from multiple sources
    def get_setting(setting, fallback, match_group = False):
        if match_group and match:
            fallback = match.group(match_group)
        single_setting = False
        if settings.has("hayaku_" + setting):
            single_setting = settings.get("hayaku_" + setting, fallback)
        options[setting] = single_setting or fallback

    # Some hardcode for different scopes
    # (could this be defined better?)
    scope_name = self.view.scope_name(self.view.sel()[0].a)
    is_sass = sublime.score_selector(scope_name, 'source.sass') > 0
    is_stylus = sublime.score_selector(scope_name, 'source.stylus') > 0

    disable_braces = is_stylus or is_sass
    if is_stylus and match and match.group(2) and match.group(8):
        disable_braces = False

    disable_colons = is_stylus
    if match and match.group(4):
        disable_colons = False

    disable_semicolons = is_stylus or is_sass
    if is_stylus and match and match.group(6):
        disable_semicolons = False

    # Calling helper, getting all the needed options
    get_setting("CSS_whitespace_block_start_before", " ",    1 )
    get_setting("CSS_whitespace_block_start_after",  "\n\t", 3 )
    get_setting("CSS_whitespace_block_end_before",   "\n",   7 )
    get_setting("CSS_whitespace_block_end_after",    "",     9 )
    get_setting("CSS_whitespace_after_colon",        " ",    5 )
    get_setting("CSS_syntax_no_curly_braces",        disable_braces )
    get_setting("CSS_syntax_no_colons",              disable_colons )
    get_setting("CSS_syntax_no_semicolons",          disable_semicolons )
    get_setting("CSS_prefixes_disable",              False     )
    get_setting("CSS_prefixes_align",                not (is_stylus or is_sass) )
    get_setting("CSS_prefixes_only",                 []        )
    get_setting("CSS_prefixes_no_unprefixed",        False     )
    get_setting("CSS_disable_postexpand",            False     )
    get_setting("CSS_colors_case",                   "uppercase" ) # or "lowercase" or "initial"
    get_setting("CSS_colors_length",                 "short"   )   # or "long"      or "initial"

    return options

class HayakuCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        cur_pos = self.view.sel()[0].begin()
        start_pos = cur_pos - MAX_SIZE_CSS
        if start_pos < 0:
            start_pos = 0
        # TODO: Move this to the contexts, it's not needed here
        probably_abbr = self.view.substr(sublime.Region(start_pos, cur_pos))
        match = ABBR_REGEX.search(probably_abbr)
        if match is None:
            self.view.insert(edit, cur_pos, '\t')
            return

        abbr = match.group(1)

        # Extracting the data from the abbr
        args = extract(abbr)

        if not args:
            return

        # Getting the options and making a snippet
        # from the extracted data
        get_hayaku_options(self)
        options = get_hayaku_options(self)
        template = make_template(args, options)

        if template is None:
            return

        # Inserting the snippet
        new_cur_pos = cur_pos - len(abbr)
        assert cur_pos - len(abbr) >= 0
        self.view.erase(edit, sublime.Region(new_cur_pos, cur_pos))
        self.view.run_command("insert_snippet", {"contents": template})

# Helpers for getting the right indent for the Add Line Command
WHITE_SPACE_FINDER = re.compile(r'^(\s*)(-)?[\w]*')
def get_line_indent(line):
    return WHITE_SPACE_FINDER.match(line).group(1)

def is_prefixed_property(line):
    return WHITE_SPACE_FINDER.match(line).group(2) is not None

def get_previous_line(view, line_region):
    return view.line(line_region.a - 1)

def get_nearest_indent(view):
    line_region = view.line(view.sel()[0])
    line = view.substr(line_region)
    line_prev_region = get_previous_line(view,line_region)

    found_indent = None
    first_indent = None
    first_is_ok = True
    is_nested = False

    # Can we do smth with all those if-else noodles?
    if not is_prefixed_property(line):
        first_indent = get_line_indent(line)
        if not is_prefixed_property(view.substr(line_prev_region)):
            return first_indent
        if is_prefixed_property(view.substr(line_prev_region)):
            first_is_ok = False
    while not found_indent and line_prev_region != view.line(sublime.Region(0)):
        line_prev = view.substr(line_prev_region)
        if not first_indent:
            if not is_prefixed_property(line_prev):
                first_indent = get_line_indent(line_prev)
                if is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                    first_is_ok = False
        else:
            if not is_prefixed_property(line_prev) and not is_prefixed_property(view.substr(get_previous_line(view,line_prev_region))):
                found_indent = min(first_indent,get_line_indent(line_prev))

        line_prev_region = get_previous_line(view,line_prev_region)
        if line_prev.count("{"):
            is_nested = True

    if found_indent and found_indent < first_indent and not is_prefixed_property(view.substr(get_previous_line(view,line_region))) and first_is_ok or is_nested:
        found_indent = found_indent + "    "

    if not found_indent:
        if first_indent:
            found_indent = first_indent
        else:
            found_indent = ""
    return found_indent

class HayakuAddLineCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        nearest_indent = get_nearest_indent(self.view)
        self.view.run_command('insert', {"characters": "\n"})
        self.view.erase(edit, sublime.Region(self.view.line(self.view.sel()[0]).a, self.view.sel()[0].a))
        self.view.run_command('insert', {"characters": nearest_indent})
<|endoftext|>


<commit_before>import numpy as np
import itertools as itr
from collections import defaultdict

def create_BM_weight_matrix(N, M=1):
    Ntot = M*N
    W = np.zeros((Ntot, Ntot))
    for i in range(M):
        W[i*N:(i+1)*N, i*N:(i+1)*N] = 2. * (np.random.rand(N, N) - 0.5)
    for i in range(Ntot):
        for j in range(i):
            W[j, i] = W[i, j]
    W -= np.diag(W.diagonal())
    return W

def create_BM_biases(N, M=1):
    return 2. * (np.random.rand(M*N) - .5)

def create_connectivity_matrix(N, w, g, epsilon, gamma):
    W = np.zeros((N, N))
    NE = int(gamma * N)
    NI = int(N - NE)
    KE = int(epsilon * NE)
    KI = int(epsilon * NI)
    for i in range(N):
        if NE > 0:
            indE = np.arange(0, NE)
            indE = indE[indE != i]
            indE = np.random.permutation(indE)[:KE]
            W[i, indE] = w
        if NI > 0:
            indI = np.arange(NE, N)
            indI = indI[indI != i]
            indI = np.random.permutation(indI)[:KI]
            W[i, indI] = -g * w
    return W

def create_noise_connectivity_matrix(Nbm, Nnoise, gamma, g, w, epsilon):
    W = np.zeros((Nbm, Nnoise))
    NE = int(gamma * Nnoise)
    NI = int(Nnoise - NE)
    KE = int(epsilon * NE)
    KI = int(epsilon * NI)
    for l in range(Nbm):
        indE = np.random.permutation(np.arange(0, NE))[:KE]
        W[l, indE] = w
        indI = np.random.permutation(np.arange(NE, Nnoise))[:KI]
        W[l, indI] = -g * w
    return W

def get_energy(W, b, s, beta=1.):
    return -1. * beta * np.sum(0.5 * np.dot(s.T, np.dot(W, s)) + np.dot(b, s))

def get_states(N):
    return np.array([np.array(x) for x in itr.product([0, 1], repeat=N)])

def get_theo_marginals(W, b, beta):
    N = len(b)
    joints = get_theo_joints(W, b, beta)
    states = get_states(N)
    p = []
    for i in range(N):
        p.append(np.sum(joints[states[:, i] == 1]))
    return p

def get_theo_joints(W, b, beta, M=1):
    N = len(b)/M
    joints = []
    for i in range(M):
        p = []
        states = get_states(N)
        for state in states:
            p.append(
                np.exp(-1. * get_energy(np.array(W[i*N:(i+1)*N,i*N:(i+1)*N]), np.array(b[i*N:(i+1)*N]), np.array(state), beta)))
        joints.append(np.array(p)/np.sum(p))
    if M == 1:
        return joints[0]
    else:
        return joints

def get_sigma2(mu):
    """
    returns variance of activity mu
    """
    return mu * (1. - mu)

def get_sigma(mu):
    """
    returns standard deviation of activity mu
    """
    return np.sqrt(get_sigma2(mu))

def get_sigma_input_from_beta(beta):
    """returns standard deviation of input given inverse temperature
    beta, by requiring matching of erfc and sigmoidal activation
    functions at zero

    """
    return np.sqrt(8. / (np.pi * beta ** 2))

def get_beta_from_sigma_input(sigma_input):
    """returns inverse temperature beta from standard deviation of
    input, by requiring matching of erfc and sigmoidal activation
    functions at zero

    """
    return 4. / np.sqrt(2. * np.pi * sigma_input ** 2)

def get_joints(a_s, steps_warmup, M=1):
    steps_tot = len(a_s[steps_warmup:])
    N = len(a_s[0,:])/M
    a_joints = np.empty((M, 2**N))
    possible_states = get_states(N)
    states = {}
    for i in range(M):
        for s in possible_states:
            states[tuple(s)] = 0.
        for s in a_s[steps_warmup:, i*N:(i+1)*N]:
            states[tuple(s)] += 1
        states_sorted = np.array([it[1] for it in sorted(states.items())])
        a_joints[i,:] = 1.* states_sorted / steps_tot
    if M == 1:
        return a_joints[0,:]
    else:
        return a_joints

def get_joints_sparse(sinit, a_s, steps_warmup, M=1):
    steps_tot = len(a_s[steps_warmup:])
    N = len(sinit)/M
    a_joints = np.empty((M, 2**N))
    possible_states = get_states(N)
    states = {}
    for i in range(M):
        cstate = sinit.copy()
        for s in possible_states:
            states[tuple(s)] = 0.
        for step, (idx, sidx) in enumerate(a_s):
            cstate[idx] = sidx
            if step >= steps_warmup:
                states[tuple(cstate[i*N:(i+1)*N])] += 1
        states_sorted = np.array([it[1] for it in sorted(states.items())])
        a_joints[i,:] = 1.* states_sorted / steps_tot
    if M == 1:
        return a_joints[0]
    else:
        return a_joints

def get_marginals(a_s, steps_warmup, M=1):
    N = len(a_s[0, :]) / M
    a_marginals = np.empty((M, N))
    for j in range(M):
        for i in range(N):
            a_marginals[j, i] = np.mean(a_s[steps_warmup:, j*N+i])
    if M == 1:
        return a_marginals[0]
    else:
        return a_marginals

def get_DKL(p, q, M=1):
    """returns the Kullback-Leibler divergence of distributions p and q

    """
    assert(np.shape(p) == np.shape(q))
    if M == 1:
        p = [p]
        q = [q]
    DKL = []
    for j in range(M):
        if abs(np.sum(p[j]) - 1.) > 1e-15 or abs(np.sum(q[j]) - 1.) > 1e-15:
            raise ValueError('Joint densities must be normalized.')
        if np.any(p[j] <= 0) or np.any(q[j] <= 0):
            DKL.append(np.nan)
        else:
            DKL.append(np.sum([p[j][i] * np.log(p[j][i] / q[j][i]) for i in range(len(p[j]))]))
    if M == 1:
        return DKL[0]
    else:
        return DKL

def theta(x, beta=1.):
    if abs(x) < 1e-15:
        raise ValueError('Invalid value in ecountered in theta(x).')
    else:
        return 1. / 2. * (np.sign(x) + 1.)

def sigma(x, beta=1.):
    """sigmoidal activation function for stochastic binary neurons
    """
    return 1. / (1. + np.exp(-beta * x))

def Fsigma(x, beta=1.):
    return 0 if sigma(x, beta) < np.random.rand() else 1

def sigmainv(y, beta=1.):
    """returns bias b that leads to mean activity y of a stochastic binary
    neuron by inverting sigmoidal activation function

    """
    return 1. / beta * np.log(1. / (1. / y - 1.))

def get_mu_input(epsilon, N, gamma, g, w, mu):
    """returns mean input for given connection statistics and presynaptic
    activity

    """
    return (gamma - (1. - gamma) * g) * epsilon * N * w * mu

def get_sigma_input(epsilon, N, gamma, g, w, mu):
    """returns standard deviation of input for given connection statistics
    and presynaptic activity

    """
    sigma2 = get_sigma2(mu)
    return np.sqrt((gamma + (1. - gamma) * g ** 2) * epsilon * N * w ** 2 * sigma2)

def get_adjusted_weights_and_bias(W, b, b_eff, beta_eff, beta):
    """return adjusted weights matrix and bias vector for a Boltzmann
    machine, given the effective offset b_eff, the effective inverse
    temperature beta_eff and the target inverse termperature beta

    """
    return beta/beta_eff*W, beta/beta_eff*b+b_eff

def bin_binary_data(times, a_states, tbin, tmax):
    """returns a binned version of the input with binsize tbin from 0 to
    tmax. input are timestamps times and networks states (or field
    recordings) a_states, which have to have the same length

    """
    a_s = a_states.T.copy()
    times_bin = np.arange(0., tmax + tbin, tbin)
    st = np.zeros((len(a_s), len(times_bin)))
    Ntimes = len(times)
    for j, s in enumerate(a_s):
        idl = 0
        for i, tc in enumerate(times_bin):
            while idl < Ntimes - 1 and times[idl + 1] <= tc:
                idl += 1
            st[j][i] = s[idl]
    return times_bin, st

def autocorrf(times_bin, st, tmax):
    """returns the population averaged autocorrelation function of the
    binned signal st

    """
    times = np.hstack([-1. * times_bin[1:][::-1], 0, times_bin[1::]])
    Nbins = len(st[0])
    offset_edge = np.hstack(
        [np.arange(1, Nbins), Nbins, np.arange(1, Nbins)[::-1]])
    autof = np.mean(
        [np.correlate(s, s, 'full') / offset_edge - np.mean(s) ** 2 for s in st], axis=0)
    autof = autof[abs(times) <= tmax]
    times = times[abs(times) <= tmax]
    return times, autof

def crosscorrf(times_bin, st, tmax):
    """returns the population averaged autocorrelation function of the
    binned signal st

    """
    N = len(st)
    times_cauto, cauto = autocorrf(times_bin, [np.sum(st, axis=0)], tmax)
    times_autof, mu_autof = autocorrf(times_bin, st, tmax)
    mu_crossf = 1. / (N * (N - 1)) * (cauto - 1. * N * mu_autof)
    return times_autof, mu_autof, mu_crossf
<commit_msg>improved theta and sigma activation functions<commit_after>import numpy as np
import itertools as itr
from collections import defaultdict

def create_BM_weight_matrix(N, M=1):
    Ntot = M*N
    W = np.zeros((Ntot, Ntot))
    for i in range(M):
        W[i*N:(i+1)*N, i*N:(i+1)*N] = 2. * (np.random.rand(N, N) - 0.5)
    for i in range(Ntot):
        for j in range(i):
            W[j, i] = W[i, j]
    W -= np.diag(W.diagonal())
    return W

def create_BM_biases(N, M=1):
    return 2. * (np.random.rand(M*N) - .5)

def create_connectivity_matrix(N, w, g, epsilon, gamma):
    W = np.zeros((N, N))
    NE = int(gamma * N)
    NI = int(N - NE)
    KE = int(epsilon * NE)
    KI = int(epsilon * NI)
    for i in range(N):
        if NE > 0:
            indE = np.arange(0, NE)
            indE = indE[indE != i]
            indE = np.random.permutation(indE)[:KE]
            W[i, indE] = w
        if NI > 0:
            indI = np.arange(NE, N)
            indI = indI[indI != i]
            indI = np.random.permutation(indI)[:KI]
            W[i, indI] = -g * w
    return W

def create_noise_connectivity_matrix(Nbm, Nnoise, gamma, g, w, epsilon):
    W = np.zeros((Nbm, Nnoise))
    NE = int(gamma * Nnoise)
    NI = int(Nnoise - NE)
    KE = int(epsilon * NE)
    KI = int(epsilon * NI)
    for l in range(Nbm):
        indE = np.random.permutation(np.arange(0, NE))[:KE]
        W[l, indE] = w
        indI = np.random.permutation(np.arange(NE, Nnoise))[:KI]
        W[l, indI] = -g * w
    return W

def get_energy(W, b, s, beta=1.):
    return -1. * beta * np.sum(0.5 * np.dot(s.T, np.dot(W, s)) + np.dot(b, s))

def get_states(N):
    return np.array([np.array(x) for x in itr.product([0, 1], repeat=N)])

def get_theo_marginals(W, b, beta):
    N = len(b)
    joints = get_theo_joints(W, b, beta)
    states = get_states(N)
    p = []
    for i in range(N):
        p.append(np.sum(joints[states[:, i] == 1]))
    return p

def get_theo_joints(W, b, beta, M=1):
    N = len(b)/M
    joints = []
    for i in range(M):
        p = []
        states = get_states(N)
        for state in states:
            p.append(
                np.exp(-1. * get_energy(np.array(W[i*N:(i+1)*N,i*N:(i+1)*N]), np.array(b[i*N:(i+1)*N]), np.array(state), beta)))
        joints.append(np.array(p)/np.sum(p))
    if M == 1:
        return joints[0]
    else:
        return joints

def get_sigma2(mu):
    """
    returns variance of activity mu
    """
    return mu * (1. - mu)

def get_sigma(mu):
    """
    returns standard deviation of activity mu
    """
    return np.sqrt(get_sigma2(mu))

def get_sigma_input_from_beta(beta):
    """returns standard deviation of input given inverse temperature
    beta, by requiring matching of erfc and sigmoidal activation
    functions at zero

    """
    return np.sqrt(8. / (np.pi * beta ** 2))

def get_beta_from_sigma_input(sigma_input):
    """returns inverse temperature beta from standard deviation of
    input, by requiring matching of erfc and sigmoidal activation
    functions at zero

    """
    return 4. / np.sqrt(2. * np.pi * sigma_input ** 2)

def get_joints(a_s, steps_warmup, M=1):
    steps_tot = len(a_s[steps_warmup:])
    N = len(a_s[0,:])/M
    a_joints = np.empty((M, 2**N))
    possible_states = get_states(N)
    states = {}
    for i in range(M):
        for s in possible_states:
            states[tuple(s)] = 0.
        for s in a_s[steps_warmup:, i*N:(i+1)*N]:
            states[tuple(s)] += 1
        states_sorted = np.array([it[1] for it in sorted(states.items())])
        a_joints[i,:] = 1.* states_sorted / steps_tot
    if M == 1:
        return a_joints[0,:]
    else:
        return a_joints

def get_joints_sparse(sinit, a_s, steps_warmup, M=1):
    steps_tot = len(a_s[steps_warmup:])
    N = len(sinit)/M
    a_joints = np.empty((M, 2**N))
    possible_states = get_states(N)
    states = {}
    for i in range(M):
        cstate = sinit.copy()
        for s in possible_states:
            states[tuple(s)] = 0.
        for step, (idx, sidx) in enumerate(a_s):
            cstate[idx] = sidx
            if step >= steps_warmup:
                states[tuple(cstate[i*N:(i+1)*N])] += 1
        states_sorted = np.array([it[1] for it in sorted(states.items())])
        a_joints[i,:] = 1.* states_sorted / steps_tot
    if M == 1:
        return a_joints[0]
    else:
        return a_joints

def get_marginals(a_s, steps_warmup, M=1):
    N = len(a_s[0, :]) / M
    a_marginals = np.empty((M, N))
    for j in range(M):
        for i in range(N):
            a_marginals[j, i] = np.mean(a_s[steps_warmup:, j*N+i])
    if M == 1:
        return a_marginals[0]
    else:
        return a_marginals

def get_DKL(p, q, M=1):
    """returns the Kullback-Leibler divergence of distributions p and q

    """
    assert(np.shape(p) == np.shape(q))
    if M == 1:
        p = [p]
        q = [q]
    DKL = []
    for j in range(M):
        if abs(np.sum(p[j]) - 1.) > 1e-15 or abs(np.sum(q[j]) - 1.) > 1e-15:
            raise ValueError('Joint densities must be normalized.')
        if np.any(p[j] <= 0) or np.any(q[j] <= 0):
            DKL.append(np.nan)
        else:
            DKL.append(np.sum([p[j][i] * np.log(p[j][i] / q[j][i]) for i in range(len(p[j]))]))
    if M == 1:
        return DKL[0]
    else:
        return DKL

def theta(x, beta=1.):
    if abs(x) < 1e-15:
        raise ValueError('Invalid value in ecountered in theta(x).')
    else:
        return 0 if x < 0 else 1

def sigma(x, beta=1.):
    """sigmoidal function

    """
    return 1. / (1. + np.exp(-beta * x))

def Fsigma(x, beta=1.):
    """sigmoidal activation function for stochastic binary neurons

    """
    return 0 if 1. / (1. + np.exp(-beta * x)) < np.random.rand() else 1

def sigmainv(y, beta=1.):
    """returns bias b that leads to mean activity y of a stochastic binary
    neuron by inverting sigmoidal activation function

    """
    return 1. / beta * np.log(1. / (1. / y - 1.))

def get_mu_input(epsilon, N, gamma, g, w, mu):
    """returns mean input for given connection statistics and presynaptic
    activity

    """
    return (gamma - (1. - gamma) * g) * epsilon * N * w * mu

def get_sigma_input(epsilon, N, gamma, g, w, mu):
    """returns standard deviation of input for given connection statistics
    and presynaptic activity

    """
    sigma2 = get_sigma2(mu)
    return np.sqrt((gamma + (1. - gamma) * g ** 2) * epsilon * N * w ** 2 * sigma2)

def get_adjusted_weights_and_bias(W, b, b_eff, beta_eff, beta):
    """return adjusted weights matrix and bias vector for a Boltzmann
    machine, given the effective offset b_eff, the effective inverse
    temperature beta_eff and the target inverse termperature beta

    """
    return beta/beta_eff*W, beta/beta_eff*b+b_eff

def bin_binary_data(times, a_states, tbin, tmax):
    """returns a binned version of the input with binsize tbin from 0 to
    tmax. input are timestamps times and networks states (or field
    recordings) a_states, which have to have the same length

    """
    a_s = a_states.T.copy()
    times_bin = np.arange(0., tmax + tbin, tbin)
    st = np.zeros((len(a_s), len(times_bin)))
    Ntimes = len(times)
    for j, s in enumerate(a_s):
        idl = 0
        for i, tc in enumerate(times_bin):
            while idl < Ntimes - 1 and times[idl + 1] <= tc:
                idl += 1
            st[j][i] = s[idl]
    return times_bin, st

def autocorrf(times_bin, st, tmax):
    """returns the population averaged autocorrelation function of the
    binned signal st

    """
    times = np.hstack([-1. * times_bin[1:][::-1], 0, times_bin[1::]])
    Nbins = len(st[0])
    offset_edge = np.hstack(
        [np.arange(1, Nbins), Nbins, np.arange(1, Nbins)[::-1]])
    autof = np.mean(
        [np.correlate(s, s, 'full') / offset_edge - np.mean(s) ** 2 for s in st], axis=0)
    autof = autof[abs(times) <= tmax]
    times = times[abs(times) <= tmax]
    return times, autof

def crosscorrf(times_bin, st, tmax):
    """returns the population averaged autocorrelation function of the
    binned signal st

    """
    N = len(st)
    times_cauto, cauto = autocorrf(times_bin, [np.sum(st, axis=0)], tmax)
    times_autof, mu_autof = autocorrf(times_bin, st, tmax)
    mu_crossf = 1. / (N * (N - 1)) * (cauto - 1. * N * mu_autof)
    return times_autof, mu_autof, mu_crossf
<|endoftext|>


<commit_before>#/usr/bin/env python
import curses

import global_mod as g
import tx
import monitor
import peers
import wallet
import console
import net
import forks
import footer

def change_mode(block_viewer, state, window, mode, poller):
    try:
        g.modes.index(mode)
    except ValueError:
        return False

    state['mode'] = mode
    block_viewer._mode = mode

    if mode == 'monitor':
        monitor.draw_window(state, window)
    elif mode == 'tx':
        tx.draw_window(state, window)
    elif mode == 'peers':
        peers.draw_window(state, window)
    elif mode == 'wallet':
        wallet.draw_window(state, window)
    elif mode == 'block':
        block_viewer.draw()
    elif mode == 'console':
        console.draw_window(state, window)
    elif mode == 'net':
        net.draw_window(state, window)
    elif mode == 'forks':
        forks.draw_window(state, window)

    footer.draw_window(state)
    poller.set_mode(mode)

def key_left(block_viewer, state, window, rpcc, poller):
    try:
        index = g.modes.index(state['mode']) - 1
        if index < 0:
            index = len(g.modes) - 2
        change_mode(block_viewer, state, window, g.modes[index], poller)
    except:
        pass

def key_right(block_viewer, state, window, rpcc, poller):
    try:
        index = g.modes.index(state['mode']) + 1
        if index > len(g.modes) - 2: # last index item is 'quit'
            index = 0
        change_mode(block_viewer, state, window, g.modes[index], poller)
    except:
        pass

def key_g(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        state['mode'] = "transaction-input"
        tx.draw_input_window(state, window, rpcc)
    elif state['mode'] == "block":
        return
        state['mode'] = "block-input"
        block.draw_input_window(state, window, rpcc)
    elif state['mode'] == "console":
        console.draw_input_box(state, window, rpcc)

def go_to_latest_block(state, window, rpcc, poller):
    if state['mode'] == "block":
        if 'mininginfo' in state:
            if str(state['mininginfo']['blocks']) not in state['blocks']:
                rpcc.request("getblockhash", state["mininginfo"]["blocks"])
            else:
                state['blocks']['browse_height'] = state['mininginfo']['blocks']
                block.draw_window(state, window)

def scroll_down(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        if 'tx' in state:
            window_height = (state['y'] - 4) / 2
            if state['tx']['cursor'] < (len(state['tx']['vin']) - 1) and state['tx']['mode'] == 'inputs':
                state['tx']['cursor'] += 1

                if (state['tx']['cursor'] - state['tx']['offset']) > window_height-2:
                    state['tx']['offset'] += 1
                tx.draw_inputs(state)

            elif state['tx']['out_offset'] < (len(state['tx']['vout_string']) - (window_height-1)) and state['tx']['mode'] == 'outputs':
                state['tx']['out_offset'] += 1
                tx.draw_outputs(state)

    elif state['mode'] == "block":
        return
        if 'blocks' in state:
            height = str(state['blocks']['browse_height'])
            if height in state['blocks']:
                blockdata = state['blocks'][height]
                if state['blocks']['cursor'] < (len(blockdata['tx']) - 1):
                    state['blocks']['cursor'] += 1
                    window_height = state['y'] - 6
                    if (state['blocks']['cursor'] - state['blocks']['offset']) > window_height-2:
                        state['blocks']['offset'] += 1
                    block.draw_transactions(state)

    elif state['mode'] == "peers":
        if 'peerinfo' in state and 'peerinfo_offset' in state:
            window_height = state['y'] - 4
            if state['peerinfo_offset'] < (len(state['peerinfo']) - window_height):
                state['peerinfo_offset'] += 1
                peers.draw_peers(state)

    elif state['mode'] == "forks":
        if 'chaintips' in state and 'chaintips_offset' in state:
            window_height = state['y'] - 4
            if state['chaintips_offset'] < (len(state['chaintips']) - window_height):
                state['chaintips_offset'] += 1
                forks.draw_tips(state)

    elif state['mode'] == "wallet":
        if 'wallet' in state:
            if state['wallet']['cursor'] < (len(state['wallet']['transactions']) - 1):
                state['wallet']['cursor'] += 1
                window_height = state['y'] - 3
                if ( (state['wallet']['cursor']*4 +1 ) - state['wallet']['offset']) > window_height-2:
                    state['wallet']['offset'] += 4
                wallet.draw_transactions(state)

    elif state['mode'] == "console":
        if state['console']['offset'] > 0:
            state['console']['offset'] -= 1
            console.draw_buffer(state)

def scroll_up(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        if 'tx' in state:
            if state['tx']['cursor'] > 0 and state['tx']['mode'] == 'inputs':
                if (state['tx']['cursor'] - state['tx']['offset']) == 0:
                    state['tx']['offset'] -= 1
                state['tx']['cursor'] -= 1
                tx.draw_inputs(state)

            if state['tx']['out_offset'] > 0 and state['tx']['mode'] == 'outputs':
                state['tx']['out_offset'] -= 1
                tx.draw_outputs(state)

    elif state['mode'] == "block":
        return
        if 'blocks' in state:
            if state['blocks']['cursor'] > 0:
                if (state['blocks']['cursor'] - state['blocks']['offset']) == 0:
                    state['blocks']['offset'] -= 1
                state['blocks']['cursor'] -= 1
                block.draw_transactions(state)

    elif state['mode'] == "peers":
        if 'peerinfo' in state and 'peerinfo_offset' in state:
            if state['peerinfo_offset'] > 0:
                state['peerinfo_offset'] -= 1
                peers.draw_peers(state)

    elif state['mode'] == "forks":
        if 'chaintips' in state and 'chaintips_offset' in state:
            if state['chaintips_offset'] > 0:
                state['chaintips_offset'] -= 1
                forks.draw_tips(state)

    elif state['mode'] == "wallet":
        if 'wallet' in state:
            if state['wallet']['cursor'] > 0:
                state['wallet']['cursor'] -= 1
                if ((state['wallet']['cursor']*4 +1) - state['wallet']['offset']) == -3:
                    state['wallet']['offset'] -= 4
                wallet.draw_transactions(state)

    elif state['mode'] == "console":
        state['console']['offset'] += 1
        console.draw_buffer(state)

def scroll_up_page(state, window, rpcc, poller):
    if state['mode'] == "console":
        window_height = state['y'] - 3 - 2
        state['console']['offset'] += window_height
        console.draw_buffer(state)

def scroll_down_page(state, window, rpcc, poller):
    if state['mode'] == "console":
        window_height = state['y'] - 3 - 2
        if state['console']['offset'] > window_height:
            state['console']['offset'] -= window_height
        else:
            state['console']['offset'] = 0
        console.draw_buffer(state)

def toggle_inputs_outputs(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        if 'tx' in state:
            if 'mode' in state['tx']:
                if state['tx']['mode'] == 'inputs':
                    state['tx']['mode'] = 'outputs'
                else:
                    state['tx']['mode'] = 'inputs'
                tx.draw_window(state, window)

def load_transaction(block_viewer, state, window, rpcc, poller):
    # TODO: some sort of indicator that a transaction is loading
    if state['mode'] == 'tx':
        if 'tx' in state:
            if 'txid' in state['tx']['vin'][ state['tx']['cursor'] ]:
                if state['tx']['loaded']:
                    state['tx']['loaded'] = 0
                    rpcc.request("getrawtransaction", state["tx"]["vin"][state["tx"]["cursor"]]["txid"], 1)

    elif state['mode'] == "block":
        if 'blocks' in state:
            if state['blocks']['browse_height'] > 0: # block 0 is not indexed
                height = str(state['blocks']['browse_height'])
                if height in state['blocks']:
                    blockdata = state['blocks'][height]
                    rpcc.request("getrawtransaction", blockdata["tx"][state["blocks"]["cursor"]], 1)
                    change_mode(block_viewer, state, window, "tx", poller)

    elif state['mode'] == "wallet":
        if 'wallet' in state:
            if 'transactions' in state['wallet']:
                rpcc.request("getrawtransaction", state['wallet']['transactions'][ state['wallet']['cursor'] ]['txid'], 1)
                change_mode(state, window, "tx", poller)

def toggle_verbose_mode(state, window, rpcc, poller):
    # TODO: Re-implement verbose mode
    return

    if state['mode'] == 'tx':
        if 'tx' in state:
            if 'txid' in state['tx']:
                if state['tx']['loaded']:
                    state['tx']['loaded'] = 0

                    if 'total_inputs' not in state['tx']:
                        s = {'txid': state['tx']['txid'], 'verbose': 1}
                    else:
                        s = {'txid': state['tx']['txid']}

                    rpcc.request(s)

def block_seek_back_thousand(state, window, rpcc, poller):
    if state['mode'] == "block":
        if 'blocks' in state:
            if (state['blocks']['browse_height']) > 999:
                if state['blocks']['loaded'] == 1:
                    state['blocks']['loaded'] = 0
                    state['blocks']['browse_height'] -= 1000
                    state['blocks']['cursor'] = 0
                    state['blocks']['offset'] = 0
                    if str(state['blocks']['browse_height']) in state['blocks']:
                        block.draw_window(state, window)
                    else:
                        rpcc.request("getblockhash", state["blocks"]["browse_height"])

def block_seek_forward_thousand(state, window, rpcc, poller):
    if state['mode'] == "block":
        if 'blocks' in state:
            if (state['blocks']['browse_height']) < state['mininginfo']['blocks'] - 999:
                if state['blocks']['loaded'] == 1:
                    state['blocks']['loaded'] = 0
                    state['blocks']['browse_height'] += 1000
                    state['blocks']['cursor'] = 0
                    state['blocks']['offset'] = 0
                    if str(state['blocks']['browse_height']) in state['blocks']:
                        block.draw_window(state, window)
                    else:
                        rpcc.request("getblockhash", state["blocks"]["browse_height"])

keymap = {
    curses.KEY_LEFT: key_left,
    curses.KEY_RIGHT: key_right,
    curses.KEY_DOWN: scroll_down,
    curses.KEY_UP: scroll_up,
    curses.KEY_PPAGE: scroll_up_page,
    curses.KEY_NPAGE: scroll_down_page,

    curses.KEY_ENTER: load_transaction,
    ord('\n'): load_transaction,

    ord('g'): key_g,
    ord('G'): key_g,

    ord('\t'): toggle_inputs_outputs,
    9: toggle_inputs_outputs,

    ord("v"): toggle_verbose_mode,
    ord("V"): toggle_verbose_mode,
}

modemap = {
    ord('m'): 'monitor',
    ord('M'): 'monitor',

    ord('b'): 'block',
    ord('B'): 'block',

    ord('t'): 'tx',
    ord('T'): 'tx',

    ord('c'): 'console',
    ord('C'): 'console',

    ord('n'): 'net',
    ord('N'): 'net',

    ord('p'): 'peers',
    ord('P'): 'peers',

    ord('w'): 'wallet',
    ord('W'): 'wallet',

    ord('f'): 'forks',
    ord('F'): 'forks',
}

def check(block_viewer, state, window, rpcc, poller):
    key = window.getch()

    if key < 0 or state['mode'] == 'splash':
        return False

    if state['mode'] == "block":
        if block_viewer.handle_hotkey(key):
            return False

    if key in keymap:
        if key in (curses.KEY_LEFT, curses.KEY_RIGHT, curses.KEY_ENTER, ord('\n')):
            keymap[key](block_viewer, state, window, rpcc, poller)
        else:
            keymap[key](state, window, rpcc, poller)

    elif key in modemap:
        mode = modemap[key]

        if mode == "forks":
            rpcc.request('getchaintips')

        change_mode(block_viewer, state, window, mode, poller)

    elif key == ord('q') or key == ord('Q'): # quit
        return True

    return False
<commit_msg>Problem: Wallet transaction viewer was broken<commit_after>#/usr/bin/env python
import curses

import global_mod as g
import tx
import monitor
import peers
import wallet
import console
import net
import forks
import footer

def change_mode(block_viewer, state, window, mode, poller):
    try:
        g.modes.index(mode)
    except ValueError:
        return False

    state['mode'] = mode
    block_viewer._mode = mode

    if mode == 'monitor':
        monitor.draw_window(state, window)
    elif mode == 'tx':
        tx.draw_window(state, window)
    elif mode == 'peers':
        peers.draw_window(state, window)
    elif mode == 'wallet':
        wallet.draw_window(state, window)
    elif mode == 'block':
        block_viewer.draw()
    elif mode == 'console':
        console.draw_window(state, window)
    elif mode == 'net':
        net.draw_window(state, window)
    elif mode == 'forks':
        forks.draw_window(state, window)

    footer.draw_window(state)
    poller.set_mode(mode)

def key_left(block_viewer, state, window, rpcc, poller):
    try:
        index = g.modes.index(state['mode']) - 1
        if index < 0:
            index = len(g.modes) - 2
        change_mode(block_viewer, state, window, g.modes[index], poller)
    except:
        pass

def key_right(block_viewer, state, window, rpcc, poller):
    try:
        index = g.modes.index(state['mode']) + 1
        if index > len(g.modes) - 2: # last index item is 'quit'
            index = 0
        change_mode(block_viewer, state, window, g.modes[index], poller)
    except:
        pass

def key_g(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        state['mode'] = "transaction-input"
        tx.draw_input_window(state, window, rpcc)
    elif state['mode'] == "block":
        return
        state['mode'] = "block-input"
        block.draw_input_window(state, window, rpcc)
    elif state['mode'] == "console":
        console.draw_input_box(state, window, rpcc)

def go_to_latest_block(state, window, rpcc, poller):
    if state['mode'] == "block":
        if 'mininginfo' in state:
            if str(state['mininginfo']['blocks']) not in state['blocks']:
                rpcc.request("getblockhash", state["mininginfo"]["blocks"])
            else:
                state['blocks']['browse_height'] = state['mininginfo']['blocks']
                block.draw_window(state, window)

def scroll_down(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        if 'tx' in state:
            window_height = (state['y'] - 4) / 2
            if state['tx']['cursor'] < (len(state['tx']['vin']) - 1) and state['tx']['mode'] == 'inputs':
                state['tx']['cursor'] += 1

                if (state['tx']['cursor'] - state['tx']['offset']) > window_height-2:
                    state['tx']['offset'] += 1
                tx.draw_inputs(state)

            elif state['tx']['out_offset'] < (len(state['tx']['vout_string']) - (window_height-1)) and state['tx']['mode'] == 'outputs':
                state['tx']['out_offset'] += 1
                tx.draw_outputs(state)

    elif state['mode'] == "block":
        return
        if 'blocks' in state:
            height = str(state['blocks']['browse_height'])
            if height in state['blocks']:
                blockdata = state['blocks'][height]
                if state['blocks']['cursor'] < (len(blockdata['tx']) - 1):
                    state['blocks']['cursor'] += 1
                    window_height = state['y'] - 6
                    if (state['blocks']['cursor'] - state['blocks']['offset']) > window_height-2:
                        state['blocks']['offset'] += 1
                    block.draw_transactions(state)

    elif state['mode'] == "peers":
        if 'peerinfo' in state and 'peerinfo_offset' in state:
            window_height = state['y'] - 4
            if state['peerinfo_offset'] < (len(state['peerinfo']) - window_height):
                state['peerinfo_offset'] += 1
                peers.draw_peers(state)

    elif state['mode'] == "forks":
        if 'chaintips' in state and 'chaintips_offset' in state:
            window_height = state['y'] - 4
            if state['chaintips_offset'] < (len(state['chaintips']) - window_height):
                state['chaintips_offset'] += 1
                forks.draw_tips(state)

    elif state['mode'] == "wallet":
        if 'wallet' in state:
            if state['wallet']['cursor'] < (len(state['wallet']['transactions']) - 1):
                state['wallet']['cursor'] += 1
                window_height = state['y'] - 3
                if ( (state['wallet']['cursor']*4 +1 ) - state['wallet']['offset']) > window_height-2:
                    state['wallet']['offset'] += 4
                wallet.draw_transactions(state)

    elif state['mode'] == "console":
        if state['console']['offset'] > 0:
            state['console']['offset'] -= 1
            console.draw_buffer(state)

def scroll_up(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        if 'tx' in state:
            if state['tx']['cursor'] > 0 and state['tx']['mode'] == 'inputs':
                if (state['tx']['cursor'] - state['tx']['offset']) == 0:
                    state['tx']['offset'] -= 1
                state['tx']['cursor'] -= 1
                tx.draw_inputs(state)

            if state['tx']['out_offset'] > 0 and state['tx']['mode'] == 'outputs':
                state['tx']['out_offset'] -= 1
                tx.draw_outputs(state)

    elif state['mode'] == "block":
        return
        if 'blocks' in state:
            if state['blocks']['cursor'] > 0:
                if (state['blocks']['cursor'] - state['blocks']['offset']) == 0:
                    state['blocks']['offset'] -= 1
                state['blocks']['cursor'] -= 1
                block.draw_transactions(state)

    elif state['mode'] == "peers":
        if 'peerinfo' in state and 'peerinfo_offset' in state:
            if state['peerinfo_offset'] > 0:
                state['peerinfo_offset'] -= 1
                peers.draw_peers(state)

    elif state['mode'] == "forks":
        if 'chaintips' in state and 'chaintips_offset' in state:
            if state['chaintips_offset'] > 0:
                state['chaintips_offset'] -= 1
                forks.draw_tips(state)

    elif state['mode'] == "wallet":
        if 'wallet' in state:
            if state['wallet']['cursor'] > 0:
                state['wallet']['cursor'] -= 1
                if ((state['wallet']['cursor']*4 +1) - state['wallet']['offset']) == -3:
                    state['wallet']['offset'] -= 4
                wallet.draw_transactions(state)

    elif state['mode'] == "console":
        state['console']['offset'] += 1
        console.draw_buffer(state)

def scroll_up_page(state, window, rpcc, poller):
    if state['mode'] == "console":
        window_height = state['y'] - 3 - 2
        state['console']['offset'] += window_height
        console.draw_buffer(state)

def scroll_down_page(state, window, rpcc, poller):
    if state['mode'] == "console":
        window_height = state['y'] - 3 - 2
        if state['console']['offset'] > window_height:
            state['console']['offset'] -= window_height
        else:
            state['console']['offset'] = 0
        console.draw_buffer(state)

def toggle_inputs_outputs(state, window, rpcc, poller):
    if state['mode'] == 'tx':
        if 'tx' in state:
            if 'mode' in state['tx']:
                if state['tx']['mode'] == 'inputs':
                    state['tx']['mode'] = 'outputs'
                else:
                    state['tx']['mode'] = 'inputs'
                tx.draw_window(state, window)

def load_transaction(block_viewer, state, window, rpcc, poller):
    # TODO: some sort of indicator that a transaction is loading
    if state['mode'] == 'tx':
        if 'tx' in state:
            if 'txid' in state['tx']['vin'][ state['tx']['cursor'] ]:
                if state['tx']['loaded']:
                    state['tx']['loaded'] = 0
                    rpcc.request("getrawtransaction", state["tx"]["vin"][state["tx"]["cursor"]]["txid"], 1)

    elif state['mode'] == "block":
        if 'blocks' in state:
            if state['blocks']['browse_height'] > 0: # block 0 is not indexed
                height = str(state['blocks']['browse_height'])
                if height in state['blocks']:
                    blockdata = state['blocks'][height]
                    rpcc.request("getrawtransaction", blockdata["tx"][state["blocks"]["cursor"]], 1)
                    change_mode(block_viewer, state, window, "tx", poller)

    elif state['mode'] == "wallet":
        if 'wallet' in state:
            if 'transactions' in state['wallet']:
                rpcc.request("getrawtransaction", state['wallet']['transactions'][ state['wallet']['cursor'] ]['txid'], 1)
                change_mode(block_viewer, state, window, "tx", poller)

def toggle_verbose_mode(state, window, rpcc, poller):
    # TODO: Re-implement verbose mode
    return

    if state['mode'] == 'tx':
        if 'tx' in state:
            if 'txid' in state['tx']:
                if state['tx']['loaded']:
                    state['tx']['loaded'] = 0

                    if 'total_inputs' not in state['tx']:
                        s = {'txid': state['tx']['txid'], 'verbose': 1}
                    else:
                        s = {'txid': state['tx']['txid']}

                    rpcc.request(s)

def block_seek_back_thousand(state, window, rpcc, poller):
    if state['mode'] == "block":
        if 'blocks' in state:
            if (state['blocks']['browse_height']) > 999:
                if state['blocks']['loaded'] == 1:
                    state['blocks']['loaded'] = 0
                    state['blocks']['browse_height'] -= 1000
                    state['blocks']['cursor'] = 0
                    state['blocks']['offset'] = 0
                    if str(state['blocks']['browse_height']) in state['blocks']:
                        block.draw_window(state, window)
                    else:
                        rpcc.request("getblockhash", state["blocks"]["browse_height"])

def block_seek_forward_thousand(state, window, rpcc, poller):
    if state['mode'] == "block":
        if 'blocks' in state:
            if (state['blocks']['browse_height']) < state['mininginfo']['blocks'] - 999:
                if state['blocks']['loaded'] == 1:
                    state['blocks']['loaded'] = 0
                    state['blocks']['browse_height'] += 1000
                    state['blocks']['cursor'] = 0
                    state['blocks']['offset'] = 0
                    if str(state['blocks']['browse_height']) in state['blocks']:
                        block.draw_window(state, window)
                    else:
                        rpcc.request("getblockhash", state["blocks"]["browse_height"])

keymap = {
    curses.KEY_LEFT: key_left,
    curses.KEY_RIGHT: key_right,
    curses.KEY_DOWN: scroll_down,
    curses.KEY_UP: scroll_up,
    curses.KEY_PPAGE: scroll_up_page,
    curses.KEY_NPAGE: scroll_down_page,

    curses.KEY_ENTER: load_transaction,
    ord('\n'): load_transaction,

    ord('g'): key_g,
    ord('G'): key_g,

    ord('\t'): toggle_inputs_outputs,
    9: toggle_inputs_outputs,

    ord("v"): toggle_verbose_mode,
    ord("V"): toggle_verbose_mode,
}

modemap = {
    ord('m'): 'monitor',
    ord('M'): 'monitor',

    ord('b'): 'block',
    ord('B'): 'block',

    ord('t'): 'tx',
    ord('T'): 'tx',

    ord('c'): 'console',
    ord('C'): 'console',

    ord('n'): 'net',
    ord('N'): 'net',

    ord('p'): 'peers',
    ord('P'): 'peers',

    ord('w'): 'wallet',
    ord('W'): 'wallet',

    ord('f'): 'forks',
    ord('F'): 'forks',
}

def check(block_viewer, state, window, rpcc, poller):
    key = window.getch()

    if key < 0 or state['mode'] == 'splash':
        return False

    if state['mode'] == "block":
        if block_viewer.handle_hotkey(key):
            return False

    if key in keymap:
        if key in (curses.KEY_LEFT, curses.KEY_RIGHT, curses.KEY_ENTER, ord('\n')):
            keymap[key](block_viewer, state, window, rpcc, poller)
        else:
            keymap[key](state, window, rpcc, poller)

    elif key in modemap:
        mode = modemap[key]

        if mode == "forks":
            rpcc.request('getchaintips')

        change_mode(block_viewer, state, window, mode, poller)

    elif key == ord('q') or key == ord('Q'): # quit
        return True

    return False
<|endoftext|>


<commit_before>#! box/bin/python
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado import autoreload
from app import app
from config import SERVER_PORT

print "EmeraldBox is now running powered by Tornado Web Server on port " + str(SERVER_PORT) + " ..."

http_server = HTTPServer(WSGIContainer(app))
http_server.listen(server_port)
autoreload.start()
IOLoop.instance().start()<commit_msg>fix bug on ignite<commit_after>#! box/bin/python
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado import autoreload
from app import app
from config import SERVER_PORT

print "EmeraldBox is now running powered by Tornado Web Server on port " + str(SERVER_PORT) + " ..."

http_server = HTTPServer(WSGIContainer(app))
http_server.listen(SERVER_PORT)
autoreload.start()
IOLoop.instance().start()<|endoftext|>