<commit_before>## $Id$

## This file is part of CDS Invenio.
## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
##
## CDS Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## CDS Invenio 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
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with CDS Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

__revision__ = "$Id$"

import urllib
import time
import cgi
import gettext
import traceback
import sre
import urllib
import sys

from invenio.config import \
     version, \
     weburl
from invenio.messages import gettext_set_language, language_list_long

class Template:
    def tmpl_getnavtrail(self, ln, previous):
        """Get the navigation trail
          - 'previous' *string* - The previous navtrail"""
        _ = gettext_set_language(ln)
        navtrail = """Admin Area > BibHarvest Admin """ % (weburl, weburl)
        navtrail = navtrail + previous
        return navtrail

    def tmpl_draw_titlebar(self, ln, weburl, title, guideurl, extraname="", extraurl=""):
        """Draws an html title bar
          - 'title' *string* - The name of the titlebar
          - 'weburl' *string* - The general weburl root for this admin section (e.g. admin/bibharvest/guide.html#mi )
          - 'guideurl' *string* - The relative url of the guide relative to this section
          - 'extraname' *string* - The name of an extra function
          - 'extraurl' *string* - The relative url to an extra function
          """

        _ = gettext_set_language(ln)
        guidetitle = _("See Guide")

        titlebar = """
"""
        titlebar += """%s &nbsp [?]""" % (title, guidetitle, weburl, guideurl)
        if extraname and extraurl:
            titlebar += """ &nbsp  &nbsp  &nbsp  &nbsp  &nbsp [%s]""" % (weburl, extraurl, extraname)
        titlebar += """
"""
        return titlebar

    def tmpl_draw_subtitle(self, ln, weburl, title, subtitle, guideurl):
        """Draws an html title bar
          - 'title' *string* - The name of the titlebar
          - 'subtitle' *string* - The header name of the subtitle
          - 'weburl' *string* - The general weburl root for this admin section (e.g. admin/bibharvest/guide.html#mi )
          - 'guideurl' *string* - The relative url of the guide relative to this section
          """
        _ = gettext_set_language(ln)
        guidetitle = _("See Guide")

        titlebar = """""" % title
        titlebar += """ %s   """ % subtitle
        titlebar += """ [?]""" % (guidetitle, weburl, guideurl)
        return titlebar

    def tmpl_link_with_args(self, ln, weburl, funcurl, title, args):
        """Draws an html title bar
          - 'weburl' *string* - The general weburl root for this admin section (e.g. admin/bibharvest/guide.html#mi )
          - 'funcurl' *string* - The relative url to this section
          - 'title' *string* - The name of the link
          - 'args' *list* - The list of arguments to be appended to the url in the form [name, value]
          """
        _ = gettext_set_language(ln)
        initurl = '' + title + ''
        noargs = len(args)
        if noargs==0:
            # there are no arguments, close link and return
            return initurl + endurl
        else:
            # we have args. list them in the link, then close it and return it
            argsurl = '?'
            count = 1
            for arg in args:
                if count != noargs:
                    argsurl += arg[0] + '=' + arg[1] + '&'
                else:
                    argsurl += arg[0] + '=' + arg[1]
                count = count + 1
            return initurl+argsurl+endurl

    def tmpl_output_numbersources(self, ln, numbersources):
        """Get the navigation trail
          - 'number of sources' *int* - The number of sources in the database"""
        _ = gettext_set_language(ln)
        present = _("OAI sources currently present in the database")
        notpresent = _("No OAI sources currently present in the database")
        if (numbersources>0):
            output  = """ &nbsp  %s %s

""" % (numbersources, present)
            return output
        else:
            output  = """ &nbsp  %s

""" % notpresent
            return output

    def tmpl_output_schedule(self, ln, schtime, schstatus):
        _ = gettext_set_language(ln)
        msg_next = _("Next oaiharvest task")
        msg_sched = _("scheduled time:")
        msg_cur = _("current status:")
        msg_notask = _("No oaiharvest task currently scheduled.")
        if schtime and schstatus:
            output  = """ &nbsp  %s

                          &nbsp   &nbsp   &nbsp   - %s %s

                          &nbsp   &nbsp   &nbsp   - %s %s

""" % (msg_next, msg_sched, schtime, msg_cur, schstatus)
            return output
        else:
            output  = """ &nbsp  %s

""" % msg_notask
            return output

    def tmpl_admin_w200_text(self, ln, title, name, value):
        """Draws an html w200 text box
          - 'title' *string* - The name of the textbox
          - 'name' *string* - The name of the value in the textbox
          - 'value' *string* - The value in the textbox"""
        _ = gettext_set_language(ln)
        text = """%s""" % title
        text += """<input class="admin_w200" type="text" name="%s" value="%s" />
""" % (cgi.escape(name,1), cgi.escape(value, 1))
        return text

    def tmpl_admin_checkboxes(self, ln, title, name, values, labels, states):
        """Draws a list of HTML checkboxes
          - 'title' *string* - The name of the list of checkboxes
          - 'name' *string* - The name for this group of checkboxes
          - 'values' *list* - The values of the checkboxes
          - 'labels' *list* - The labels for the checkboxes
          - 'states' *list* - The previous state of each checkbox 1|0

          len(values) == len(labels) == len(states)
          """
        _ = gettext_set_language(ln)
        text = """

%s
""" % title
        text += """

"""
        text += '   (Leave all unchecked for non-selective' \
                ' harvesting)
'

        for i in range(len(values)):
            value = values[i]
            label = labels[i]
            state = states[i]
            chk_box_id = value + str(i)
            text += '   <input type="checkbox"' \
                    'name="%s" id="%s" value="%s" ' % (name, chk_box_id, value)
            if state:
                text += 'checked="checked "'
            text += "/>"

            text += """%s
""" % (chk_box_id, label)
        text += "

"
        return text

    def tmpl_admin_w200_select(self, ln, title, name, valuenil, values, lastval=""):
        """Draws an html w200 drop-down box
          - 'title' *string* - The name of the dd box
          - 'name' *string* - The name of the value in the dd box
          - 'value' *list* - The values in the textbox"""
        _ = gettext_set_language(ln)
        text = """%s""" % title
        text += """<select name="%s" class="admin_w200">""" % name
        text += """<option value="">%s</option>""" % valuenil
        try:
            for val in values:
                intval = int(lastval)
                if intval==int(val[0]): ## retrieve and display last value inputted into drop-down box
                    text += """<option value="%s" %s>%s</option>""" % (val[0], 'selected="selected"', str(val[1]))
                else:
                    text += """<option value="%s">%s</option>""" % (val[0], str(val[1]))
            text += """</select>
"""
        except StandardError, e:
            for val in values:
                if lastval==val[0]:
                    text += """<option value="%s" %s>%s</option>""" % (val[0], 'selected="selected"', str(val[1]))
                else:
                    text += """<option value="%s">%s</option>""" % (val[0], str(val[1]))
            text += """</select>
"""
        return text

### deprecated ###
#    def tmpl_print_src_add_tips(self):
#        """Outputs some tips for source adding and editing"""
#        text =     """

#        Frequency: how often do you intend to harvest from this repository?

#        Starting date: do you intend to harvest the whole repository (from beginning) or only newly added material (from today)? WARNING: harvesting large collections of material may take very long!

#        Postprocess: how is the harvested material be dealt with after harvesting?
#

h: harvest only
h-c: harvest and convert
h-c-u: harvest, convert and upload

#        BibConvert configuration file: if postprocess involves conversion, please include full path to a configuration file
#        """
#        return text

### deprecated ###
#    def tmpl_print_src_edit_tips(self):
#        """Outputs some tips for source adding and editing"""
#        text =     """

#        Frequency: how often do you intend to harvest from this repository?

#        Postprocess: how is the harvested material be dealt with after harvesting?
#

h: harvest only
h-c: harvest and convert
h-c-u: harvest, convert and upload

#        BibConvert configuration file: if postprocess involves conversion, please include full path to a configuration file
#        """
#        return text

### deprecated ###
#    def tmpl_print_validate_tips(self):
#        """Outputs some tips for source validation"""
#        text =     """
Validate: to check that the baseURL of the repository is OAI-compliant"""
#        return text

    def tmpl_print_info(self, ln, infotext):
        """Outputs some info"""
        _ = gettext_set_language(ln)
        text = """
%s""" % infotext
        return text

    def tmpl_print_warning(self, ln, warntext):
        """Outputs some info"""
        _ = gettext_set_language(ln)
        text = """%s""" % warntext
        return text

    def tmpl_print_brs(self, ln, howmany):
        """Outputs some
s"""
        _ = gettext_set_language(ln)
        text = ""
        while howmany>0:
            text += """
"""
            howmany = howmany - 1
        return text

    def tmpl_output_validate_info(self, ln, outcome, base):
        """Prints a message to say whether source was validated or not
          - 'outcome' *int* - 0=success, 1=fail
          - 'base' *string* - baseurl"""
        _ = gettext_set_language(ln)
        msg_success = _("successfully validated")
        msg_nosuccess = _("does not seem to be a OAI-compliant baseURL")
        if outcome==0:
            output = """
baseURL %s %s""" % (base, msg_success)
            return output
        else:
            output = """
baseURL %s %s""" % (base, msg_nosuccess)
            return output

    def tmpl_output_error_info(self, ln, base, error):
        """Prints a http error message"""
        _ = gettext_set_language(ln)
        msg_error = "returns the following HTTP error: "
        output = """
baseURL %s %s

%s
""" % (base, msg_error, error)
        return output
<commit_msg>Removed deprecated stuff.<commit_after>## $Id$

## This file is part of CDS Invenio.
## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
##
## CDS Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## CDS Invenio 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
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with CDS Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

__revision__ = "$Id$"

import urllib
import time
import cgi
import gettext
import traceback
import sre
import urllib
import sys

from invenio.config import \
     version, \
     weburl
from invenio.messages import gettext_set_language, language_list_long

class Template:
    def tmpl_getnavtrail(self, ln, previous):
        """Get the navigation trail
          - 'previous' *string* - The previous navtrail"""
        _ = gettext_set_language(ln)
        navtrail = """Admin Area > BibHarvest Admin """ % (weburl, weburl)
        navtrail = navtrail + previous
        return navtrail

    def tmpl_draw_titlebar(self, ln, weburl, title, guideurl, extraname="", extraurl=""):
        """Draws an html title bar
          - 'title' *string* - The name of the titlebar
          - 'weburl' *string* - The general weburl root for this admin section (e.g. admin/bibharvest/guide.html#mi )
          - 'guideurl' *string* - The relative url of the guide relative to this section
          - 'extraname' *string* - The name of an extra function
          - 'extraurl' *string* - The relative url to an extra function
          """

        _ = gettext_set_language(ln)
        guidetitle = _("See Guide")

        titlebar = """
"""
        titlebar += """%s &nbsp [?]""" % (title, guidetitle, weburl, guideurl)
        if extraname and extraurl:
            titlebar += """ &nbsp  &nbsp  &nbsp  &nbsp  &nbsp [%s]""" % (weburl, extraurl, extraname)
        titlebar += """
"""
        return titlebar

    def tmpl_draw_subtitle(self, ln, weburl, title, subtitle, guideurl):
        """Draws an html title bar
          - 'title' *string* - The name of the titlebar
          - 'subtitle' *string* - The header name of the subtitle
          - 'weburl' *string* - The general weburl root for this admin section (e.g. admin/bibharvest/guide.html#mi )
          - 'guideurl' *string* - The relative url of the guide relative to this section
          """
        _ = gettext_set_language(ln)
        guidetitle = _("See Guide")

        titlebar = """""" % title
        titlebar += """ %s   """ % subtitle
        titlebar += """ [?]""" % (guidetitle, weburl, guideurl)
        return titlebar

    def tmpl_link_with_args(self, ln, weburl, funcurl, title, args):
        """Draws an html title bar
          - 'weburl' *string* - The general weburl root for this admin section (e.g. admin/bibharvest/guide.html#mi )
          - 'funcurl' *string* - The relative url to this section
          - 'title' *string* - The name of the link
          - 'args' *list* - The list of arguments to be appended to the url in the form [name, value]
          """
        _ = gettext_set_language(ln)
        initurl = '' + title + ''
        noargs = len(args)
        if noargs==0:
            # there are no arguments, close link and return
            return initurl + endurl
        else:
            # we have args. list them in the link, then close it and return it
            argsurl = '?'
            count = 1
            for arg in args:
                if count != noargs:
                    argsurl += arg[0] + '=' + arg[1] + '&'
                else:
                    argsurl += arg[0] + '=' + arg[1]
                count = count + 1
            return initurl+argsurl+endurl

    def tmpl_output_numbersources(self, ln, numbersources):
        """Get the navigation trail
          - 'number of sources' *int* - The number of sources in the database"""
        _ = gettext_set_language(ln)
        present = _("OAI sources currently present in the database")
        notpresent = _("No OAI sources currently present in the database")
        if (numbersources>0):
            output  = """ &nbsp  %s %s

""" % (numbersources, present)
            return output
        else:
            output  = """ &nbsp  %s

""" % notpresent
            return output

    def tmpl_output_schedule(self, ln, schtime, schstatus):
        _ = gettext_set_language(ln)
        msg_next = _("Next oaiharvest task")
        msg_sched = _("scheduled time:")
        msg_cur = _("current status:")
        msg_notask = _("No oaiharvest task currently scheduled.")
        if schtime and schstatus:
            output  = """ &nbsp  %s

                          &nbsp   &nbsp   &nbsp   - %s %s

                          &nbsp   &nbsp   &nbsp   - %s %s

""" % (msg_next, msg_sched, schtime, msg_cur, schstatus)
            return output
        else:
            output  = """ &nbsp  %s

""" % msg_notask
            return output

    def tmpl_admin_w200_text(self, ln, title, name, value):
        """Draws an html w200 text box
          - 'title' *string* - The name of the textbox
          - 'name' *string* - The name of the value in the textbox
          - 'value' *string* - The value in the textbox"""
        _ = gettext_set_language(ln)
        text = """%s""" % title
        text += """<input class="admin_w200" type="text" name="%s" value="%s" />
""" % (cgi.escape(name,1), cgi.escape(value, 1))
        return text

    def tmpl_admin_checkboxes(self, ln, title, name, values, labels, states):
        """Draws a list of HTML checkboxes
          - 'title' *string* - The name of the list of checkboxes
          - 'name' *string* - The name for this group of checkboxes
          - 'values' *list* - The values of the checkboxes
          - 'labels' *list* - The labels for the checkboxes
          - 'states' *list* - The previous state of each checkbox 1|0

          len(values) == len(labels) == len(states)
          """
        _ = gettext_set_language(ln)
        text = """

%s
""" % title
        text += """

"""
        text += '   (Leave all unchecked for non-selective' \
                ' harvesting)
'

        for i in range(len(values)):
            value = values[i]
            label = labels[i]
            state = states[i]
            chk_box_id = value + str(i)
            text += '   <input type="checkbox"' \
                    'name="%s" id="%s" value="%s" ' % (name, chk_box_id, value)
            if state:
                text += 'checked="checked "'
            text += "/>"

            text += """%s
""" % (chk_box_id, label)
        text += "

"
        return text

    def tmpl_admin_w200_select(self, ln, title, name, valuenil, values, lastval=""):
        """Draws an html w200 drop-down box
          - 'title' *string* - The name of the dd box
          - 'name' *string* - The name of the value in the dd box
          - 'value' *list* - The values in the textbox"""
        _ = gettext_set_language(ln)
        text = """%s""" % title
        text += """<select name="%s" class="admin_w200">""" % name
        text += """<option value="">%s</option>""" % valuenil
        try:
            for val in values:
                intval = int(lastval)
                if intval==int(val[0]): ## retrieve and display last value inputted into drop-down box
                    text += """<option value="%s" %s>%s</option>""" % (val[0], 'selected="selected"', str(val[1]))
                else:
                    text += """<option value="%s">%s</option>""" % (val[0], str(val[1]))
            text += """</select>
"""
        except StandardError, e:
            for val in values:
                if lastval==val[0]:
                    text += """<option value="%s" %s>%s</option>""" % (val[0], 'selected="selected"', str(val[1]))
                else:
                    text += """<option value="%s">%s</option>""" % (val[0], str(val[1]))
            text += """</select>
"""
        return text

    def tmpl_print_info(self, ln, infotext):
        """Outputs some info"""
        _ = gettext_set_language(ln)
        text = """
%s""" % infotext
        return text

    def tmpl_print_warning(self, ln, warntext):
        """Outputs some info"""
        _ = gettext_set_language(ln)
        text = """%s""" % warntext
        return text

    def tmpl_print_brs(self, ln, howmany):
        """Outputs some
s"""
        _ = gettext_set_language(ln)
        text = ""
        while howmany>0:
            text += """
"""
            howmany = howmany - 1
        return text

    def tmpl_output_validate_info(self, ln, outcome, base):
        """Prints a message to say whether source was validated or not
          - 'outcome' *int* - 0=success, 1=fail
          - 'base' *string* - baseurl"""
        _ = gettext_set_language(ln)
        msg_success = _("successfully validated")
        msg_nosuccess = _("does not seem to be a OAI-compliant baseURL")
        if outcome==0:
            output = """
baseURL %s %s""" % (base, msg_success)
            return output
        else:
            output = """
baseURL %s %s""" % (base, msg_nosuccess)
            return output

    def tmpl_output_error_info(self, ln, base, error):
        """Prints a http error message"""
        _ = gettext_set_language(ln)
        msg_error = "returns the following HTTP error: "
        output = """
baseURL %s %s

%s
""" % (base, msg_error, error)
        return output
<|endoftext|>


<commit_before>from subprocess import Popen
import time
import os

#setup
os.system("rm -rf /boot/home/Dropbox/*")
os.system("rm log.txt lines_*")
os.system("touch log.txt")

# start dbclient
p = Popen(["../objects.x86-gcc2-release/hdbclient.exe"])
time.sleep(2)

#tell db_put what to say
putlines = open("lines_db_put.txt",'w+')
putlines.write("success")
putlines.close()

#create file
foo = open("/boot/home/Dropbox/foo",'w+')
foo.write("Hello,World")
foo.close()

#tell db_delta what to say
deltalines = open("lines_db_delta.txt",'w+')
deltalines.write("FILE /foo")
deltalines.close()

#wait for pull-deltas to finish
time.sleep(10)

# kill dbclient
p.kill()

# produce result
print "Checking Assertions:"
os.system("cat log.txt")

<commit_msg>Corrected db_put's lines to include parent revision<commit_after>from subprocess import Popen
import time
import os

#setup
os.system("rm -rf /boot/home/Dropbox/*")
os.system("rm log.txt lines_*")
os.system("touch log.txt")

# start dbclient
p = Popen(["../objects.x86-gcc2-release/hdbclient.exe"])
time.sleep(2)

#tell db_put what to say
putlines = open("lines_db_put.txt",'w+')
putlines.write("success AAAAA")
putlines.close()

#create file
foo = open("/boot/home/Dropbox/foo",'w+')
foo.write("Hello,World")
foo.close()

#tell db_delta what to say
deltalines = open("lines_db_delta.txt",'w+')
deltalines.write("FILE /foo")
deltalines.close()

#wait for pull-deltas to finish
time.sleep(10)

# kill dbclient
p.kill()

# produce result
print "Checking Assertions:"
os.system("cat log.txt")

<|endoftext|>


<commit_before># coding=UTF-8
"""
Decorator for debug-time typechecking
"""
from __future__ import print_function, absolute_import, division

import inspect
import itertools
import logging

import six
from copy import copy
try:
    import typing
except ImportError:
    from backports import typing
from collections import namedtuple
import functools

logger = logging.getLogger(__name__)

List = typing.List
Tuple = typing.Tuple
Dict = typing.Dict
NewType = typing.NewType
Callable = typing.Callable
Sequence = typing.Sequence
Number = six.integer_types + (float,)
TypeVar = typing.TypeVar
Generic = typing.Generic
Mapping = typing.Mapping
Iterable = typing.Iterable
Union = typing.Union
Any = typing.Any
Optional = typing.Optional

# Internal tokens - only instances will be
class _NotGiven(object):
    pass

class _NoDefault(object):
    pass

_CSArgument = namedtuple('_CSArgument', ('name', 'required', 'default_value'))

class CSArgument(_CSArgument):
    def __str__(self):
        p = ['Argument ' + self.name]
        if not self.required:
            p.append('optional with default %s' % (self.default_value,))
        return ' '.join(p)

    def __eq__(self, other):
        """
        Is other argument same as this, in name/default value if present?
        :param other: CSArgument
        :return: bool
        """
        return self.name == other.name and \
               self.required == other.required and \
               self.default_value == other.default_value

class CSVarargsPlaceholder(CSArgument):
    pass

class CSKwargsPlaceholder(CSArgument):
    pass

class TypeErrorReason(object):
    pass

class CSTypeError(TypeError):
    """
    A TypeError exception on steroids
    """

    def __str__(self):
        return 'Problem with argument %s' % (arg.name,)

    def __init__(self, arg):
        """
        :param arg: Argument definition
        :type arg: CSArgument
        """
        super(CSTypeError, self).__init__(str(self))
        self.arg = arg

class CSBadTypeError(CSTypeError):
    def __init__(self, arg, expected, got):
        super(CSBadTypeError, self).__init__(arg)

        self.expected = expected
        self.got = got

    def __str__(self):
        return 'Bad type given for arg %s, expected %s got %s' % (
            self.arg.name, self.expected, self.got)

class CSNotGivenError(CSTypeError):
    def __str__(self):
        return 'Value for argument %s not given' % (self.arg.name,)

class CSMultipleValuesGivenError(CSTypeError):
    def __str__(self):
        return 'Got multiple values for argument' % (self.arg.name,)

class CallSignature(object):
    """
    Call signature of a callable.

    Properties:
      - has_varargs (Bool) - if has varargs
      - has_kwargs (Bool) - if has kwargs
      - locals (Dict[str => CSArgument]) - list of locals this function call
        will generate
      - pos_args (List[CSArgument)] - list of positional arguments
      - varargs_name (Union[str, None]) - name of varargs argument, or None if
        not present
      - kwargs_name (Union[str, None]) - name of kwargs argument, or None if
        not present
    """

    def count_required_positionals(self):
        c = 0
        for a in self.pos_args:
            if a.required:
                c += 1
        return c

    def __eq__(self, other):
        """
        Compare if two call signatures are IDENTICAL
        :param other: CallSignature
        :return: bool
        """

        if any(a != b for a, b in zip(self.pos_args, other.pos_args)):
            return False

        return self.has_kwargs == other.has_kwargs and \
               self.has_varargs == other.has_varargs

    def __init__(self, callable):
        args, varargs, kwargs, defaults = inspect.getargspec(callable)

        defaults = defaults or ()
        # pad them
        while len(defaults) < len(args):
            defaults = [_NoDefault] + list(defaults)

        # process positionals
        self.pos_args = []
        self.locals = {}
        for arg, default in zip(args, defaults):
            cs_arg = CSArgument(arg,
                                default is _NoDefault,
                                default)
            self.pos_args.append(cs_arg)
            self.locals[arg] = cs_arg

        self.varargs_name = varargs
        if varargs is not None:
            self.has_varargs = True
            self.locals[self.varargs_name] = CSVarargsPlaceholder(
                self.varargs_name, False, [])
        else:
            self.has_varargs = False

        self.kwargs_name = kwargs
        if kwargs is not None:
            self.has_kwargs = True
            self.locals[self.kwargs_name] = CSKwargsPlaceholder(
                self.kwargs_name, False, {})
        else:
            self.has_kwargs = False

    def to_invocation(self, locals):
        """
        Return an invocation to the function reconstructed from its locals
        :param locals: as returned by .result()
        :return: tuple of (args, kwargs)
        """
        locals = copy(locals)
        args = []

        for arg in self.pos_args:
            if arg.name in locals:
                args.append(locals.pop(arg.name))
            elif not arg.required:
                args.append(arg.default_value)
                del locals[arg.name]

        return args, locals

    def result(self, *args, **kwargs):
        """
        Simulate a function call, see what locals are defined

        Return a dict of (local_variable_name => it's value),
        or TypeError

        :param args: function call parameters
        :param kwargs: function call parameters
        :return: dict
        :raise CSTypeError: call would raise a TypeError
        """
        assert len(args) >= self.count_required_positionals()

        locals = {}

        # positional
        for arg, value in itertools.izip_longest(self.pos_args,
                                                 args[:len(self.pos_args)],
                                                 fillvalue=_NotGiven):

            if value is _NotGiven:
                if arg.required:
                    raise CSNotGivenError(arg)
                else:
                    value = arg.default_value

            locals[arg.name] = value

        # varargs
        if self.has_varargs:
            locals[self.varargs_name] = args[len(self.pos_args):]

        # kwargs
        if self.has_kwargs:
            locals[self.kwargs_name] = kwargs

        return locals

    def is_match_amount(self, *args, **kwargs):
        """
        Would a function call with these arguments succeed, based solely on
        number and "keywordnessity" or parameters?
        """
        if len(args) > len(self.pos_args):
            if not self.has_varargs:
                return False  # *args expected

        if len(args) < self.count_required_positionals():
            return False  # Not enough posits

        if len(kwargs) > 0 and not self.has_kwargs:
            return False  # kwargs expected

        return True

def __typeinfo_to_tuple_of_types(typeinfo, operator=type):
    if typeinfo == 'self':
        return None
    elif typeinfo is None:
        return (operator(None),)
    elif typeinfo == int and six.PY2:
        return six.integer_types
    else:
        if isinstance(typeinfo, (tuple, list)):
            new_tup = []
            for elem in typeinfo:
                new_tup.extend(__typeinfo_to_tuple_of_types(elem))
            return tuple(new_tup)
        else:
            return (typeinfo,)

def _do_if_not_type(var, type_, fun='default'):

    if type_ in ((type(None), ), ) and (fun == 'default'):
        return None

    if type_ in (None, (None, ), 'self'):
        return var

    if not isinstance(var, type_):

        if fun == 'default':
            if type_[0] == type(None):
                return None
            else:
                print(var, 'to', type_[0])
                return type_[0](var)

        q = fun()
        if isinstance(q, Exception):
            raise q
        return q
    else:
        return var

def typed(*t_args, **t_kwargs):
    """
    Use like:

        @typed(int, six.text_type)
        def display(times, text):
            ...

    You can also check for return type with kw argument of "returns", ie.

        @typed(int, int, returns=int)
        def sum(a, b):
            return a+b

    Or
        @typed('self', a, b):
        def method(self, a, b):
        ..

    If you specify extra argument - mandatory=True - type will always be
    checked, regardless if debug mode is enabled

    Same rules apply.

    int will automatically include long for checking (Python 3 compatibility)
    If you want to check for None, type (None, )
    None for an argument means "do no checking", (None, ) means "type must be
    NoneType". You can pass tuples or lists to match for multiple types

    :param t_args:
    :param t_kwargs:
    """

    t_args = [(__typeinfo_to_tuple_of_types(x) if x is not None else None)
              for x in t_args]

    t_retarg = t_kwargs.get('returns', None)
    is_mandatory = t_kwargs.get('mandatory', False)

    if t_retarg is not None:
        t_retarg = __typeinfo_to_tuple_of_types(t_retarg)

    def outer(fun):
        if (not __debug__) and (not is_mandatory):
            return fun

        @functools.wraps(fun)
        def inner(*args, **kwargs):
            # add extra 'None' argument if unbound method
            for argument, typedescr in zip(args, t_args):
                _do_if_not_type(argument, typedescr, lambda: \
                    TypeError('Got %s, expected %s' % (
                            type(argument), typedescr)))

            rt = fun(*args, **kwargs)

            return _do_if_not_type(rt, t_retarg, lambda:
                    TypeError('Returned %s, expected %s' % (
                        type(rt), t_retarg)))

        return inner
    return outer

def coerce(*t_args, **t_kwargs):
    """
    Use like:

        @typed(int, six.text_type)
        def display(times, text):
            ...

    You can also check for return type with kw argument of "returns", ie.

        @typed(int, int, returns=int)
        def sum(a, b):
            return a+b

    Or
        @typed('self', a, b):
        def method(self, a, b):
        ..

    If you specify extra argument - mandatory=True - type will always be
    checked, regardless if debug mode is enabled

    Same rules apply.

    int will automatically include long for checking (Python 3 compatibility)
    If you want to check for None, type (None, )
    None for an argument means "do no checking", (None, ) means "type must be
    NoneType". You can pass tuples or lists to match for multiple types

    :param t_args:
    :param t_kwargs:
    """

    t_args = [(__typeinfo_to_tuple_of_types(x, operator=lambda x: x))
              for x in t_args]

    def argify(args):
        return [_do_if_not_type(argument, typedescr) \
                        for argument, typedescr in zip(args, t_args)]

    t_retarg = t_kwargs.get('returns', None)

    t_retarg = __typeinfo_to_tuple_of_types(t_retarg, operator=lambda x: x)

    def outer(fun):

        @functools.wraps(fun)
        def inner(*args, **kwargs):
            # add extra 'None' argument if unbound method
            new_args = argify(args)

            rt = fun(*new_args, **kwargs)
            return _do_if_not_type(rt, t_retarg)

        return inner

    return outer
<commit_msg>shorter coerces are OK too<commit_after># coding=UTF-8
"""
Decorator for debug-time typechecking
"""
from __future__ import print_function, absolute_import, division

import inspect
import itertools
import logging

import six
from copy import copy
try:
    import typing
except ImportError:
    from backports import typing
from collections import namedtuple
import functools
import itertools

logger = logging.getLogger(__name__)

List = typing.List
Tuple = typing.Tuple
Dict = typing.Dict
NewType = typing.NewType
Callable = typing.Callable
Sequence = typing.Sequence
Number = six.integer_types + (float,)
TypeVar = typing.TypeVar
Generic = typing.Generic
Mapping = typing.Mapping
Iterable = typing.Iterable
Union = typing.Union
Any = typing.Any
Optional = typing.Optional

# Internal tokens - only instances will be
class _NotGiven(object):
    pass

class _NoDefault(object):
    pass

_CSArgument = namedtuple('_CSArgument', ('name', 'required', 'default_value'))

class CSArgument(_CSArgument):
    def __str__(self):
        p = ['Argument ' + self.name]
        if not self.required:
            p.append('optional with default %s' % (self.default_value,))
        return ' '.join(p)

    def __eq__(self, other):
        """
        Is other argument same as this, in name/default value if present?
        :param other: CSArgument
        :return: bool
        """
        return self.name == other.name and \
               self.required == other.required and \
               self.default_value == other.default_value

class CSVarargsPlaceholder(CSArgument):
    pass

class CSKwargsPlaceholder(CSArgument):
    pass

class TypeErrorReason(object):
    pass

class CSTypeError(TypeError):
    """
    A TypeError exception on steroids
    """

    def __str__(self):
        return 'Problem with argument %s' % (arg.name,)

    def __init__(self, arg):
        """
        :param arg: Argument definition
        :type arg: CSArgument
        """
        super(CSTypeError, self).__init__(str(self))
        self.arg = arg

class CSBadTypeError(CSTypeError):
    def __init__(self, arg, expected, got):
        super(CSBadTypeError, self).__init__(arg)

        self.expected = expected
        self.got = got

    def __str__(self):
        return 'Bad type given for arg %s, expected %s got %s' % (
            self.arg.name, self.expected, self.got)

class CSNotGivenError(CSTypeError):
    def __str__(self):
        return 'Value for argument %s not given' % (self.arg.name,)

class CSMultipleValuesGivenError(CSTypeError):
    def __str__(self):
        return 'Got multiple values for argument' % (self.arg.name,)

class CallSignature(object):
    """
    Call signature of a callable.

    Properties:
      - has_varargs (Bool) - if has varargs
      - has_kwargs (Bool) - if has kwargs
      - locals (Dict[str => CSArgument]) - list of locals this function call
        will generate
      - pos_args (List[CSArgument)] - list of positional arguments
      - varargs_name (Union[str, None]) - name of varargs argument, or None if
        not present
      - kwargs_name (Union[str, None]) - name of kwargs argument, or None if
        not present
    """

    def count_required_positionals(self):
        c = 0
        for a in self.pos_args:
            if a.required:
                c += 1
        return c

    def __eq__(self, other):
        """
        Compare if two call signatures are IDENTICAL
        :param other: CallSignature
        :return: bool
        """

        if any(a != b for a, b in zip(self.pos_args, other.pos_args)):
            return False

        return self.has_kwargs == other.has_kwargs and \
               self.has_varargs == other.has_varargs

    def __init__(self, callable):
        args, varargs, kwargs, defaults = inspect.getargspec(callable)

        defaults = defaults or ()
        # pad them
        while len(defaults) < len(args):
            defaults = [_NoDefault] + list(defaults)

        # process positionals
        self.pos_args = []
        self.locals = {}
        for arg, default in zip(args, defaults):
            cs_arg = CSArgument(arg,
                                default is _NoDefault,
                                default)
            self.pos_args.append(cs_arg)
            self.locals[arg] = cs_arg

        self.varargs_name = varargs
        if varargs is not None:
            self.has_varargs = True
            self.locals[self.varargs_name] = CSVarargsPlaceholder(
                self.varargs_name, False, [])
        else:
            self.has_varargs = False

        self.kwargs_name = kwargs
        if kwargs is not None:
            self.has_kwargs = True
            self.locals[self.kwargs_name] = CSKwargsPlaceholder(
                self.kwargs_name, False, {})
        else:
            self.has_kwargs = False

    def to_invocation(self, locals):
        """
        Return an invocation to the function reconstructed from its locals
        :param locals: as returned by .result()
        :return: tuple of (args, kwargs)
        """
        locals = copy(locals)
        args = []

        for arg in self.pos_args:
            if arg.name in locals:
                args.append(locals.pop(arg.name))
            elif not arg.required:
                args.append(arg.default_value)
                del locals[arg.name]

        return args, locals

    def result(self, *args, **kwargs):
        """
        Simulate a function call, see what locals are defined

        Return a dict of (local_variable_name => it's value),
        or TypeError

        :param args: function call parameters
        :param kwargs: function call parameters
        :return: dict
        :raise CSTypeError: call would raise a TypeError
        """
        assert len(args) >= self.count_required_positionals()

        locals = {}

        # positional
        for arg, value in itertools.izip_longest(self.pos_args,
                                                 args[:len(self.pos_args)],
                                                 fillvalue=_NotGiven):

            if value is _NotGiven:
                if arg.required:
                    raise CSNotGivenError(arg)
                else:
                    value = arg.default_value

            locals[arg.name] = value

        # varargs
        if self.has_varargs:
            locals[self.varargs_name] = args[len(self.pos_args):]

        # kwargs
        if self.has_kwargs:
            locals[self.kwargs_name] = kwargs

        return locals

    def is_match_amount(self, *args, **kwargs):
        """
        Would a function call with these arguments succeed, based solely on
        number and "keywordnessity" or parameters?
        """
        if len(args) > len(self.pos_args):
            if not self.has_varargs:
                return False  # *args expected

        if len(args) < self.count_required_positionals():
            return False  # Not enough posits

        if len(kwargs) > 0 and not self.has_kwargs:
            return False  # kwargs expected

        return True

def __typeinfo_to_tuple_of_types(typeinfo, operator=type):
    if typeinfo == 'self':
        return None
    elif typeinfo is None:
        return (operator(None),)
    elif typeinfo == int and six.PY2:
        return six.integer_types
    else:
        if isinstance(typeinfo, (tuple, list)):
            new_tup = []
            for elem in typeinfo:
                new_tup.extend(__typeinfo_to_tuple_of_types(elem))
            return tuple(new_tup)
        else:
            return (typeinfo,)

def _do_if_not_type(var, type_, fun='default'):

    if type_ in ((type(None), ), ) and (fun == 'default'):
        return None

    if type_ in (None, (None, ), 'self'):
        return var

    if not isinstance(var, type_):

        if fun == 'default':
            if type_[0] == type(None):
                return None
            else:
                print(var, 'to', type_[0])
                return type_[0](var)

        q = fun()
        if isinstance(q, Exception):
            raise q
        return q
    else:
        return var

def typed(*t_args, **t_kwargs):
    """
    Use like:

        @typed(int, six.text_type)
        def display(times, text):
            ...

    You can also check for return type with kw argument of "returns", ie.

        @typed(int, int, returns=int)
        def sum(a, b):
            return a+b

    Or
        @typed('self', a, b):
        def method(self, a, b):
        ..

    If you specify extra argument - mandatory=True - type will always be
    checked, regardless if debug mode is enabled

    Same rules apply.

    int will automatically include long for checking (Python 3 compatibility)
    If you want to check for None, type (None, )
    None for an argument means "do no checking", (None, ) means "type must be
    NoneType". You can pass tuples or lists to match for multiple types

    :param t_args:
    :param t_kwargs:
    """

    t_args = [(__typeinfo_to_tuple_of_types(x) if x is not None else None)
              for x in t_args]

    t_retarg = t_kwargs.get('returns', None)
    is_mandatory = t_kwargs.get('mandatory', False)

    if t_retarg is not None:
        t_retarg = __typeinfo_to_tuple_of_types(t_retarg)

    def outer(fun):
        if (not __debug__) and (not is_mandatory):
            return fun

        @functools.wraps(fun)
        def inner(*args, **kwargs):
            # add extra 'None' argument if unbound method
            for argument, typedescr in zip(args, t_args):
                _do_if_not_type(argument, typedescr, lambda: \
                    TypeError('Got %s, expected %s' % (
                            type(argument), typedescr)))

            rt = fun(*args, **kwargs)

            return _do_if_not_type(rt, t_retarg, lambda:
                    TypeError('Returned %s, expected %s' % (
                        type(rt), t_retarg)))

        return inner
    return outer

def coerce(*t_args, **t_kwargs):
    """
    Use like:

        @typed(int, six.text_type)
        def display(times, text):
            ...

    You can also check for return type with kw argument of "returns", ie.

        @typed(int, int, returns=int)
        def sum(a, b):
            return a+b

    Or
        @typed('self', a, b):
        def method(self, a, b):
        ..

    If you specify extra argument - mandatory=True - type will always be
    checked, regardless if debug mode is enabled

    Same rules apply.

    int will automatically include long for checking (Python 3 compatibility)
    If you want to check for None, type (None, )
    None for an argument means "do no checking", (None, ) means "type must be
    NoneType". You can pass tuples or lists to match for multiple types

    :param t_args:
    :param t_kwargs:
    """

    t_args = [(__typeinfo_to_tuple_of_types(x, operator=lambda x: x))
              for x in t_args]

    def argify(args):
        return [_do_if_not_type(argument, typedescr) \
                        for argument, typedescr in itertools.zip_longest(args, t_args)]

    t_retarg = t_kwargs.get('returns', None)

    t_retarg = __typeinfo_to_tuple_of_types(t_retarg, operator=lambda x: x)

    def outer(fun):

        @functools.wraps(fun)
        def inner(*args, **kwargs):
            # add extra 'None' argument if unbound method

            new_args = argify(args)

            rt = fun(*new_args, **kwargs)
            return _do_if_not_type(rt, t_retarg)

        return inner

    return outer
<|endoftext|>


<commit_before>import io
import os
import urlparse

import markdown2
import html2text

from flask import Markup

from . import download
from . import instapaper
from . import newspaper

from saulify.sitespec import load_rules

def clean_url(url):
    """ Extract article from given url using `scraper_cascade`

    Args:
        url (str): Url of article to be scraped.

    Returns:
        Dictionary detailing the extracted article, or `None` if no scrapers
        could extract the article
    """

    content = download.download_url(url)
    result = scraper_cascade(url, content)

    return result

def scraper_cascade(url, content):
    """ Extract article using a fallback sequence of scrapers.

    Args:
        url (str): Url of article being scraped.

        content (str): Html source of the article page.

    Returns:
        Dictionary detailing the extracted article, or `None` if no scrapers
        could extract the article
    """

    hostname = urlparse.urlparse(url).hostname
    spec = load_superdomains(hostname)

    if spec is not None:
        # Instapaper scraper
        scraper = instapaper.InstapaperScraper(spec)
        result = scraper.clean_article(content)
    else:
        # Fallback: newspaper
        result = newspaper.clean_source(url, content)

    if result is None:
        return None

    # Add markdown (and plaintext)
    result["markdown"] = html2text.HTML2Text().handle(result["html"])
    result["markdown_html"] = Markup(markdown2.markdown(result["markdown"]))
    # TODO: Investigate the most appropriate method of converting markdown
    # to plaintext.
    result["plaintext"] = result["markdown"].replace('\n', ' ')

    return result

def load_superdomains(hostname):
    """ Load the most specific spec file applicable to the given hostname.

    Peels off sub-hosts one at a time and searches for spec files defined for
    each level. Does not accept spec files that contain no rules.

    Args:
        hostname (str): Hostname for which to find an applicable spec file.

    Returns:
        The result of the first call to `load_sitespec` that succeeds,
        or `None` if no spec files were available for the given host.
    """

    def recurse():
        super_domain = hostname.partition(".")[2]
        if super_domain:
            return load_superdomains(super_domain)
        else:
            return None

    try:
        d = load_sitespec(hostname)
        if d:
            return d
        else:
            return recurse()
    except IOError:
        return recurse()

def load_sitespec(hostname):
    """ Load sitespec file for a given host.

    Args:
        hostname (str): Hostname for which to load associated spec file.

    Raises:
        IOError if there is no sitespec file for the exact hostname.
    """

    fpath = os.path.join("sitespecs", hostname + ".txt")

    with io.open(fpath) as f:
        return load_rules(f)
<commit_msg>Change scraper cascade behaviour<commit_after>import io
import os
import urlparse

import markdown2
import html2text

from flask import Markup

from . import download
from . import instapaper
from . import newspaper

from saulify.sitespec import load_rules

def clean_url(url):
    """ Extract article from given url using `scraper_cascade`

    Args:
        url (str): Url of article to be scraped.

    Returns:
        Dictionary detailing the extracted article, or `None` if no scrapers
        could extract the article
    """

    content = download.download_url(url)
    result = scraper_cascade(url, content)

    return result

def scraper_cascade(url, content):
    """ Extract article using a fallback sequence of scrapers.

    If no scrapers are able to extract the article body, the original page
    will be converted to markdown.

    Args:
        url (str): Url of article being scraped.

        content (str): Html source of the article page.

    Returns:
        Dictionary detailing the extracted article.
    """

    hostname = urlparse.urlparse(url).hostname
    spec = load_superdomains(hostname)

    # Pre-populate fields such as author and title using newspaper,
    # and return complete html page by default if newspaper does not work.
    result = newspaper.clean_source(url, content) or {"html": content}

    if spec is not None:
        # Instapaper scraper
        scraper = instapaper.InstapaperScraper(spec)
        for k, v in scraper.clean_article(content).items():
            if v:
                result[k] = v

    # Add markdown (and plaintext)
    result["markdown"] = html2text.HTML2Text().handle(result["html"])
    result["markdown_html"] = Markup(markdown2.markdown(result["markdown"]))
    # TODO: Investigate the most appropriate method of converting markdown
    # to plaintext.
    result["plaintext"] = result["markdown"].replace('\n', ' ')

    return result

def load_superdomains(hostname):
    """ Load the most specific spec file applicable to the given hostname.

    Peels off sub-hosts one at a time and searches for spec files defined for
    each level. Does not accept spec files that contain no rules.

    Args:
        hostname (str): Hostname for which to find an applicable spec file.

    Returns:
        The result of the first call to `load_sitespec` that succeeds,
        or `None` if no spec files were available for the given host.
    """

    def recurse():
        super_domain = hostname.partition(".")[2]
        if super_domain:
            return load_superdomains(super_domain)
        else:
            return None

    try:
        d = load_sitespec(hostname)
        if d:
            return d
        else:
            return recurse()
    except IOError:
        return recurse()

def load_sitespec(hostname):
    """ Load sitespec file for a given host.

    Args:
        hostname (str): Hostname for which to load associated spec file.

    Raises:
        IOError if there is no sitespec file for the exact hostname.
    """

    fpath = os.path.join("sitespecs", hostname + ".txt")

    with io.open(fpath) as f:
        return load_rules(f)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import absolute_import

import json
import functools
from collections import defaultdict

from sc2reader import log_utils
from sc2reader.utils import Length
from sc2reader.events import SelectionEvent, HotkeyEvent, AddToHotkeyEvent, GetFromHotkeyEvent, SetToHotkeyEvent
from sc2reader.plugins.utils import PlayerSelection, GameState, JSONDateEncoder, plugin

@plugin
def toJSON(replay, **user_options):
    options = dict(cls=JSONDateEncoder)
    options.update(user_options)
    return json.dumps(toDict()(replay), **options)

@plugin
def toDict(replay):
    # Build observers into dictionary
    observers = list()
    for observer in replay.observers:
        messages = list()
        for message in getattr(observer,'messages',list()):
            messages.append({
                'time': message.time.seconds,
                'text': message.text,
                'is_public': message.to_all
            })
        observers.append({
            'name': getattr(observer, 'name', None),
            'pid': getattr(observer, 'pid', None),
            'messages': messages,
        })

    # Build players into dictionary
    players = list()
    for player in replay.players:
        messages = list()
        for message in player.messages:
            messages.append({
                'time': message.time.seconds,
                'text': message.text,
                'is_public': message.to_all
            })
        players.append({
            'avg_apm': getattr(player, 'avg_apm', None),
            'color': getattr(player, 'color', None),
            'name': getattr(player, 'name', None),
            'pick_race': getattr(player, 'pick_race', None),
            'pid': getattr(player, 'pid', None),
            'play_race': getattr(player, 'play_race', None),
            'result': getattr(player, 'result', None),
            'type': getattr(player, 'type', None),
            'uid': getattr(player, 'uid', None),
            'url': getattr(player, 'url', None),
            'messages': messages,
        })

    # Consolidate replay metadata into dictionary
    return {
        'gateway': getattr(replay, 'gateway', None),
        'map': getattr(replay, 'map', None),
        'file_time': getattr(replay, 'file_time', None),
        'unix_timestamp': getattr(replay, 'unix_timestamp', None),
        'date': getattr(replay, 'date', None),
        'utc_date': getattr(replay, 'utc_date', None),
        'speed': getattr(replay, 'speed', None),
        'category': getattr(replay, 'category', None),
        'type': getattr(replay, 'type', None),
        'is_ladder': getattr(replay, 'is_ladder', False),
        'is_private': getattr(replay, 'is_private', False),
        'filename': getattr(replay, 'filename', None),
        'file_time': getattr(replay, 'file_time', None),
        'frames': getattr(replay, 'frames', None),
        'build': getattr(replay, 'build', None),
        'release': getattr(replay, 'release_string', None),
        'length': getattr(getattr(replay, 'length', None),'seconds', None),
        'players': players,
        'observers': observers
    }

@plugin
def APMTracker(replay):
    efilter = lambda event: getattr(event,'is_player_action',False)
    for player in replay.players:
        player.aps = defaultdict(int)
        player.apm = defaultdict(int)
        for event in filter(efilter, player.events):
            player.aps[event.second] += 1
            player.apm[event.second/60] += 1
        if len(player.apm.keys()) > 0:
            player.avg_apm = sum(player.apm.values())/float(len(player.apm.keys()))
        else:
            player.avg_apm = 0

    return replay

@plugin
def SelectionTracker(replay):
    debug = replay.opt.debug
    logger = log_utils.get_logger(SelectionTracker)

    for person in replay.people:
        # TODO: A more robust person interface might be nice
        person.selection_errors = 0
        player_selection = GameState(PlayerSelection())
        for event in person.selection_events:
            if debug: logger.debug("Event bytes: "+event.bytes.encode("hex"))

            error = False
            selection = player_selection[event.frame]

            if isinstance(event, SelectionEvent):
                selection[event.bank] = selection[event.bank].copy()
                error = not selection[event.bank].deselect(*event.deselect)
                selection[event.bank].select(event.objects)
                if debug: logger.info("[{0}] {1} selected {2} units: {3}".format(Length(seconds=event.second),person.name,len(selection[0x0A].objects),selection[0x0A]))

            elif isinstance(event, GetFromHotkeyEvent):
                # For some reason they leave the hotkey buffer unmodified so make a copy
                selection[0x0A] = selection[event.hotkey].copy()
                error = not selection[0x0A].deselect(*event.deselect)
                if debug: logger.info("[{0}] {1} retrieved hotkey {2}, {3} units: {4}".format(Length(seconds=event.second),person.name,event.hotkey,len(selection[0x0A].objects),selection[0x0A]))

            elif isinstance(event, SetToHotkeyEvent):
                # Make a copy to decouple the hotkey from primary selection
                selection[event.hotkey] = selection[0x0A].copy()
                if debug: logger.info("[{0}] {1} set hotkey {2} to current selection".format(Length(seconds=event.second),person.name,event.hotkey))

            elif isinstance(event, AddToHotkeyEvent):
                selection[event.hotkey] = selection[event.hotkey].copy()
                error = not selection[event.hotkey].deselect(*event.deselect)
                selection[event.hotkey].select(selection[0x0A].objects)
                if debug: logger.info("[{0}] {1} added current selection to hotkey {2}".format(Length(seconds=event.second),person.name,event.hotkey))

            # TODO: The event level interface here should be improved
            #       Possibly use 'added' and 'removed' unit lists as well
            event.selected = selection[0x0A].objects
            if error:
                person.selection_errors += 1
                if debug:
                    logger.warn("Error detected in deselection mode {0}.".format(event.deselect[0]))

        person.selection = player_selection
        # Not a real lock, so don't change it!
        person.selection.locked = True

    return replay
<commit_msg>Fix the toJSON plugin to work with revised Color class.<commit_after># -*- coding: utf-8 -*-
from __future__ import absolute_import

import json
import functools
from collections import defaultdict

from sc2reader import log_utils
from sc2reader.utils import Length
from sc2reader.events import SelectionEvent, HotkeyEvent, AddToHotkeyEvent, GetFromHotkeyEvent, SetToHotkeyEvent
from sc2reader.plugins.utils import PlayerSelection, GameState, JSONDateEncoder, plugin

@plugin
def toJSON(replay, **user_options):
    options = dict(cls=JSONDateEncoder)
    options.update(user_options)
    return json.dumps(toDict()(replay), **options)

@plugin
def toDict(replay):
    # Build observers into dictionary
    observers = list()
    for observer in replay.observers:
        messages = list()
        for message in getattr(observer,'messages',list()):
            messages.append({
                'time': message.time.seconds,
                'text': message.text,
                'is_public': message.to_all
            })
        observers.append({
            'name': getattr(observer, 'name', None),
            'pid': getattr(observer, 'pid', None),
            'messages': messages,
        })

    # Build players into dictionary
    players = list()
    for player in replay.players:
        messages = list()
        for message in player.messages:
            messages.append({
                'time': message.time.seconds,
                'text': message.text,
                'is_public': message.to_all
            })
        players.append({
            'avg_apm': getattr(player, 'avg_apm', None),
            'color': player.color.__dict__ if hasattr(player, 'color') else None,
            'name': getattr(player, 'name', None),
            'pick_race': getattr(player, 'pick_race', None),
            'pid': getattr(player, 'pid', None),
            'play_race': getattr(player, 'play_race', None),
            'result': getattr(player, 'result', None),
            'type': getattr(player, 'type', None),
            'uid': getattr(player, 'uid', None),
            'url': getattr(player, 'url', None),
            'messages': messages,
        })

    # Consolidate replay metadata into dictionary
    return {
        'gateway': getattr(replay, 'gateway', None),
        'map': getattr(replay, 'map', None),
        'file_time': getattr(replay, 'file_time', None),
        'unix_timestamp': getattr(replay, 'unix_timestamp', None),
        'date': getattr(replay, 'date', None),
        'utc_date': getattr(replay, 'utc_date', None),
        'speed': getattr(replay, 'speed', None),
        'category': getattr(replay, 'category', None),
        'type': getattr(replay, 'type', None),
        'is_ladder': getattr(replay, 'is_ladder', False),
        'is_private': getattr(replay, 'is_private', False),
        'filename': getattr(replay, 'filename', None),
        'file_time': getattr(replay, 'file_time', None),
        'frames': getattr(replay, 'frames', None),
        'build': getattr(replay, 'build', None),
        'release': getattr(replay, 'release_string', None),
        'length': getattr(getattr(replay, 'length', None),'seconds', None),
        'players': players,
        'observers': observers
    }

@plugin
def APMTracker(replay):
    efilter = lambda event: getattr(event,'is_player_action',False)
    for player in replay.players:
        player.aps = defaultdict(int)
        player.apm = defaultdict(int)
        for event in filter(efilter, player.events):
            player.aps[event.second] += 1
            player.apm[event.second/60] += 1
        if len(player.apm.keys()) > 0:
            player.avg_apm = sum(player.apm.values())/float(len(player.apm.keys()))
        else:
            player.avg_apm = 0

    return replay

@plugin
def SelectionTracker(replay):
    debug = replay.opt.debug
    logger = log_utils.get_logger(SelectionTracker)

    for person in replay.people:
        # TODO: A more robust person interface might be nice
        person.selection_errors = 0
        player_selection = GameState(PlayerSelection())
        for event in person.selection_events:
            if debug: logger.debug("Event bytes: "+event.bytes.encode("hex"))

            error = False
            selection = player_selection[event.frame]

            if isinstance(event, SelectionEvent):
                selection[event.bank] = selection[event.bank].copy()
                error = not selection[event.bank].deselect(*event.deselect)
                selection[event.bank].select(event.objects)
                if debug: logger.info("[{0}] {1} selected {2} units: {3}".format(Length(seconds=event.second),person.name,len(selection[0x0A].objects),selection[0x0A]))

            elif isinstance(event, GetFromHotkeyEvent):
                # For some reason they leave the hotkey buffer unmodified so make a copy
                selection[0x0A] = selection[event.hotkey].copy()
                error = not selection[0x0A].deselect(*event.deselect)
                if debug: logger.info("[{0}] {1} retrieved hotkey {2}, {3} units: {4}".format(Length(seconds=event.second),person.name,event.hotkey,len(selection[0x0A].objects),selection[0x0A]))

            elif isinstance(event, SetToHotkeyEvent):
                # Make a copy to decouple the hotkey from primary selection
                selection[event.hotkey] = selection[0x0A].copy()
                if debug: logger.info("[{0}] {1} set hotkey {2} to current selection".format(Length(seconds=event.second),person.name,event.hotkey))

            elif isinstance(event, AddToHotkeyEvent):
                selection[event.hotkey] = selection[event.hotkey].copy()
                error = not selection[event.hotkey].deselect(*event.deselect)
                selection[event.hotkey].select(selection[0x0A].objects)
                if debug: logger.info("[{0}] {1} added current selection to hotkey {2}".format(Length(seconds=event.second),person.name,event.hotkey))

            # TODO: The event level interface here should be improved
            #       Possibly use 'added' and 'removed' unit lists as well
            event.selected = selection[0x0A].objects
            if error:
                person.selection_errors += 1
                if debug:
                    logger.warn("Error detected in deselection mode {0}.".format(event.deselect[0]))

        person.selection = player_selection
        # Not a real lock, so don't change it!
        person.selection.locked = True

    return replay
<|endoftext|>


<commit_before>#!/usr/bin/env python

from scadasim.devices import Device

# Sensors
class Sensor(Device):
    def __init__(self, worker_frequency=1, **kwargs):
        self.fluid = None
        super(Sensor, self).__init__(device_type="sensor", worker_frequency=worker_frequency, **kwargs)

    def output(self, to_device, volume):
        """Output used for pass-through sensors.
            If a connected device requests output, pass it upstream to the next device
        """
        available_volume = 0
        for i in self.inputs:
            available_volume = self.inputs[i].output(self, volume=volume)
        return available_volume

    def input(self, fluid, volume):
        """When fluid comes in, store the fluid context, and pass it downstream to all connected devices
        """
        self.fluid = fluid
        accepted_volume = 0
        for o in self.outputs:
            # Send the fluid on to all outputs
            #log.debug("%s sending fluid to %s" % (self, self.outputs[o]))
            accepted_volume = self.outputs[o].input(fluid, volume)
        return accepted_volume

    def worker(self):
        """Do something at `worker_frequency` rate
        """
        log.debug("%s fluid: %s" % (self, self.fluid))
        pass

    def read_sensor(self):
        """ Report sensor value
        """
        return self.fluid

class pHSensor(Sensor):
    def __init__(self, **kwargs):
        self.ph = None
        super(Sensor, self).__init__(device_type="sensor", worker_frequency=1, **kwargs)

    def input(self, fluid, volume):
        """When fluid comes in, store the fluid context, and pass it downstream to all connected devices
        """
        self.ph = fluid.ph

        log.debug("ph: ", self.ph)

        accepted_volume = 0
        for o in self.outputs:
            # Send the fluid on to all outputs
            #log.debug("%s sending fluid to %s" % (self, self.outputs[o]))
            accepted_volume = self.outputs[o].input(fluid, volume)
        return accepted_volume

    def read_sensor(self):
        """ Report sensor value
        """
        return self.ph
<commit_msg>Fixed logging bug<commit_after>#!/usr/bin/env python

from scadasim.devices import Device
import logging

logging.basicConfig()
log = logging.getLogger()

# Sensors
class Sensor(Device):
    def __init__(self, worker_frequency=1, **kwargs):
        self.fluid = None
        super(Sensor, self).__init__(device_type="sensor", worker_frequency=worker_frequency, **kwargs)

    def output(self, to_device, volume):
        """Output used for pass-through sensors.
            If a connected device requests output, pass it upstream to the next device
        """
        available_volume = 0
        for i in self.inputs:
            available_volume = self.inputs[i].output(self, volume=volume)
        return available_volume

    def input(self, fluid, volume):
        """When fluid comes in, store the fluid context, and pass it downstream to all connected devices
        """
        self.fluid = fluid
        accepted_volume = 0
        for o in self.outputs:
            # Send the fluid on to all outputs
            #log.debug("%s sending fluid to %s" % (self, self.outputs[o]))
            accepted_volume = self.outputs[o].input(fluid, volume)
        return accepted_volume

    def worker(self):
        """Do something at `worker_frequency` rate
        """
        log.debug("%s fluid: %s" % (self, self.fluid))
        pass

    def read_sensor(self):
        """ Report sensor value
        """
        return self.fluid

class pHSensor(Sensor):
    def __init__(self, **kwargs):
        self.ph = None
        super(Sensor, self).__init__(device_type="sensor", worker_frequency=1, **kwargs)

    def input(self, fluid, volume):
        """When fluid comes in, store the fluid context, and pass it downstream to all connected devices
        """
        self.ph = fluid.ph

        log.debug("ph: ", self.ph)

        accepted_volume = 0
        for o in self.outputs:
            # Send the fluid on to all outputs
            #log.debug("%s sending fluid to %s" % (self, self.outputs[o]))
            accepted_volume = self.outputs[o].input(fluid, volume)
        return accepted_volume

    def read_sensor(self):
        """ Report sensor value
        """
        return self.ph
<|endoftext|>


<commit_before>#!/usr/bin/env python

# 2048 code originally from http://www.thetaranights.com/make-a-2048-game-in-python/
# there is a bug/missing logic that needs to be fixed where it will quit the game
# even if there is still a valid move left when the grid is completely full.
# but other than that it works.

import unicornhat as unicorn
import getch, random

unicorn.rotation(90)
unicorn.brightness(0.4)

grid = [[0,0,0,0],
        [0,0,0,0],
        [0,0,0,0],
        [0,0,0,0]]

index = {0:0,2:1,4:2,8:3,16:4,32:5,64:6,128:7,256:8,512:9,1024:10,2048:11}
colour=((0,0,0),(0,127,0),(0,255,0),(0,0,127),(0,0,255),(127,0,0),(255,0,0),
        (127,127,0),(127,127,127),(255,127,127),(255,255,127),(255,255,255))

def drawTile(y, x, value):
    rgb=colour[(index[value])]
    unicorn.set_pixel((x*2),(y*2),rgb[0],rgb[1],rgb[2])
    unicorn.set_pixel((x*2)+1,(y*2),rgb[0],rgb[1],rgb[2])
    unicorn.set_pixel((x*2),(y*2)+1,rgb[0],rgb[1],rgb[2])
    unicorn.set_pixel((x*2)+1,(y*2)+1,rgb[0],rgb[1],rgb[2])
    unicorn.show()

def updateGrid(keypressed):
    if keypressed == "u":
        row=0
        for column in range(0,4):
            if grid[row][column]!=0 or grid[row+1][column]!=0 or grid[row+2][column]!=0 or grid[row+3][column]!=0:
                if grid[row][column]==0:
                    while grid[row][column]==0:
                        grid[row][column]=grid[row+1][column]
                        grid[row+1][column]=grid[row+2][column]
                        grid[row+2][column]=grid[row+3][column]
                        grid[row+3][column]=0
                if grid[row+1][column]==0 and (grid[row+2][column]!=0 or grid[row+3][column]!=0):
                    while grid[row+1][column]==0:

                        grid[row+1][column]=grid[row+2][column]
                        grid[row+2][column]=grid[row+3][column]
                        grid[row+3][column]=0
                if grid[row+2][column]==0 and (grid[row+3][column]!=0):
                    while grid[row+2][column]==0:
                        grid[row+2][column]=grid[row+3][column]
                        grid[row+3][column]=0
        i=0
        for column in range(0,4):
            if grid[row][column]==grid[row+1][column]:
                grid[row][column]=grid[row][column]+grid[row+1][column]
                grid[row+1][column]=grid[row+2][column]
                grid[row+2][column]=grid[row+3][column]
                grid[row+3][column]=0
            if grid[row+1][column]==grid[row+2][column]:
                grid[row+1][column]=grid[row+1][column]+grid[row+2][column]
                grid[row+2][column]=grid[row+3][column]
                grid[row+3][column]=0
            if grid[row+2][column]==grid[row+3][column]:
                grid[row+2][column]=grid[row+2][column]+grid[row+3][column]
                grid[row+3][column]=0

    elif keypressed == "d":
        i=0
        for column in range(0,4):
            if grid[row][column]!=0 or grid[row+1][column]!=0 or grid[row+2][column]!=0 or grid[row+3][column]!=0:
                if grid[row+3][column]==0:
                    while grid[row+3][column]==0:
                        grid[row+3][column]=grid[row+2][column]
                        grid[row+2][column]=grid[row+1][column]
                        grid[row+1][column]=grid[row][column]
                        grid[row][column]=0
                if grid[row+2][column]==0 and (grid[row+1][column]!=0 or grid[row][column]!=0):
                    while grid[row+2][column]==0:
                        grid[row+2][column]=grid[row+1][column]
                        grid[row+1][column]=grid[row][column]
                        grid[row][column]=0

                if grid[row+1][column]==0 and grid[row][column]!=0:
                    while grid[row+1][column]==0:
                        grid[row+1][column]=grid[row][column]
                        grid[row][column]=0
        i=0
        for column in range(0,4):
            if grid[row+3][column]==grid[row+2][column]:
                grid[row+3][column]=grid[row+3][column] + grid[row+2][column]
                grid[row+2][column]=grid[row+1][column]
                grid[row+1][column]=grid[row][column]
                grid[row][column]=0
            if grid[row+2][column]==grid[row+1][column]:
                grid[row+2][column]=grid[row+2][column]+grid[row+1][column]
                grid[row+1][column]=grid[row][column]
                grid[row][column]=0
            if grid[row+1][column]==grid[row][column]:
                grid[row+1][column]=grid[row+1][column]+grid[row][column]
                grid[row][column]=0

    elif keypressed == "l":
        column=0
        for row in range(0,4):

            if grid[row][column]!=0 or grid[row][column+1]!=0 or grid[row][column+2]!=0 or grid[row][column+3]!=0:
                if grid[row][column]==0:
                    while grid[row][column]==0:
                        grid[row][column]=grid[row][column+1]
                        grid[row][column+1]=grid[row][column+2]
                        grid[row][column+2] = grid[row][column+3]
                        grid[row][column+3]=0
                if grid[row][column+1]==0 and (grid[row][column+2]!=0 or grid[row][column+3]!=0):
                    while grid[row][column+1]==0:
                        grid[row][column+1]=grid[row][column+2]
                        grid[row][column+2]=grid[row][column+3]
                        grid[row][column+3]=0
                if grid[row][column+2]==0 and (grid[row][column+3]!=0):
                    while grid[row][column+2]==0:
                        grid[row][column+2]=grid[row][column+3]
                        grid[row][column+3]=0
        column=0
        for row in range(0,4):
            if grid[row][column]==grid[row][column+1]:
                grid[row][column]=grid[row][column]+grid[row][column+1]
                grid[row][column+1]=grid[row][column+2]
                grid[row][column+2]=grid[row][column+3]
                grid[row][column+3]=0
            if grid[row][column+1]==grid[row][column+2]:
                grid[row][column+1]=grid[row][column+1]+grid[row][column+2]
                grid[row][column+2]=grid[row][column+3]
                grid[row][column+3]=0
            if grid[row][column+2]==grid[row][column+3]:
                grid[row][column+2]=grid[row][column+2]+grid[row][column+3]
                grid[row][column+3]=0
    elif keypressed == "r":
        column=0
        for row in range(0,4):
            if grid[row][column]!=0 or grid[row][column+1]!=0 or grid[row][column+2]!=0 or grid[row][column+3]!=0:
                if grid[row][column+3]==0:
                    while grid[row][column+3]==0:
                        grid[row][column+3]=grid[row][column+2]
                        grid[row][column+2]=grid[row][column+1]
                        grid[row][column+1]=grid[row][column]
                        grid[row][column]=0
                if grid[row][column+2]==0 and (grid[row][column+1]!=0 or grid[row][column]!=0):
                    while grid[row][column+2]==0:
                        grid[row][column+2]=grid[row][column+1]
                        grid[row][column+1]=grid[row][column]
                        grid[row][column]=0

                if grid[row][column+1]==0 and grid[row][column]!=0:
                    while grid[row][column+1]==0:
                        grid[row][column+1]=grid[row][column]
                        grid[row][column]=0
        column=0
        for row in range(0,4):
            if grid[row][column+3]==grid[row][column+2]:
                grid[row][column+3]=grid[row][column+3] + grid[row][column+2]
                grid[row][column+2]=grid[row][column+1]
                grid[row][column+1]=grid[row][column]
                grid[row][column]=0
            if grid[row][column+2]==grid[row][column+1]:
                grid[row][column+2]=grid[row][column+2]+grid[row][column+1]
                grid[row][column+1]=grid[row][column]
                grid[row][column]=0
            if grid[row][column+1]==grid[row][column]:
                grid[row][column+1]=grid[row][column+1]+grid[row][column]
                grid[row][column]=0

grid[random.choice([0,1,2,3])][random.choice([0,1,2,3])]=2

while True:
    for y in range(4):
        for x in range(4):
           drawTile(y,x,grid[y][x])

    keypressed=""
    while keypressed=="":
        keypressed = getch.getch().lower()
        if (keypressed!="u") and (keypressed!="d") and (keypressed!="l") and (keypressed!="r") and (keypressed!="q"):
            keypressed=""

    if keypressed!="q":
        updateGrid(keypressed)
        listForRow = []
        listForColumnn = []
        count = 0
        for row in range(0,4):
            for column in range(0,4):
                if grid[row][column]==0:
                    count+=1
                    listForRow.append(row)
                    listForColumnn.append(column)
        if count > 0:
            if count > 1:
                randomIndex = listForRow.index(random.choice(listForRow))
                grid[listForRow[randomIndex]][listForColumnn[randomIndex]]=2
            else:
                grid[listForRow[0]][listForColumnn[0]]=2
        else:
            break
    else:
        break
print "Game over"
<commit_msg>fix row= in uni2048<commit_after>#!/usr/bin/env python

# 2048 code originally from http://www.thetaranights.com/make-a-2048-game-in-python/
# there is a bug/missing logic that needs to be fixed where it will quit the game
# even if there is still a valid move left when the grid is completely full.
# but other than that it works.

import unicornhat as unicorn
import getch, random

unicorn.rotation(90)
unicorn.brightness(0.4)

grid = [[0,0,0,0],
        [0,0,0,0],
        [0,0,0,0],
        [0,0,0,0]]

index = {0:0,2:1,4:2,8:3,16:4,32:5,64:6,128:7,256:8,512:9,1024:10,2048:11}
colour=((0,0,0),(0,127,0),(0,255,0),(0,0,127),(0,0,255),(127,0,0),(255,0,0),
        (127,127,0),(127,127,127),(255,127,127),(255,255,127),(255,255,255))

def drawTile(y, x, value):
    rgb=colour[(index[value])]
    unicorn.set_pixel((x*2),(y*2),rgb[0],rgb[1],rgb[2])
    unicorn.set_pixel((x*2)+1,(y*2),rgb[0],rgb[1],rgb[2])
    unicorn.set_pixel((x*2),(y*2)+1,rgb[0],rgb[1],rgb[2])
    unicorn.set_pixel((x*2)+1,(y*2)+1,rgb[0],rgb[1],rgb[2])
    unicorn.show()

def updateGrid(keypressed):
    if keypressed == "u":
        row=0
        for column in range(0,4):
            if grid[row][column]!=0 or grid[row+1][column]!=0 or grid[row+2][column]!=0 or grid[row+3][column]!=0:
                if grid[row][column]==0:
                    while grid[row][column]==0:
                        grid[row][column]=grid[row+1][column]
                        grid[row+1][column]=grid[row+2][column]
                        grid[row+2][column]=grid[row+3][column]
                        grid[row+3][column]=0
                if grid[row+1][column]==0 and (grid[row+2][column]!=0 or grid[row+3][column]!=0):
                    while grid[row+1][column]==0:

                        grid[row+1][column]=grid[row+2][column]
                        grid[row+2][column]=grid[row+3][column]
                        grid[row+3][column]=0
                if grid[row+2][column]==0 and (grid[row+3][column]!=0):
                    while grid[row+2][column]==0:
                        grid[row+2][column]=grid[row+3][column]
                        grid[row+3][column]=0
        row=0
        for column in range(0,4):
            if grid[row][column]==grid[row+1][column]:
                grid[row][column]=grid[row][column]+grid[row+1][column]
                grid[row+1][column]=grid[row+2][column]
                grid[row+2][column]=grid[row+3][column]
                grid[row+3][column]=0
            if grid[row+1][column]==grid[row+2][column]:
                grid[row+1][column]=grid[row+1][column]+grid[row+2][column]
                grid[row+2][column]=grid[row+3][column]
                grid[row+3][column]=0
            if grid[row+2][column]==grid[row+3][column]:
                grid[row+2][column]=grid[row+2][column]+grid[row+3][column]
                grid[row+3][column]=0

    elif keypressed == "d":
        row=0
        for column in range(0,4):
            if grid[row][column]!=0 or grid[row+1][column]!=0 or grid[row+2][column]!=0 or grid[row+3][column]!=0:
                if grid[row+3][column]==0:
                    while grid[row+3][column]==0:
                        grid[row+3][column]=grid[row+2][column]
                        grid[row+2][column]=grid[row+1][column]
                        grid[row+1][column]=grid[row][column]
                        grid[row][column]=0
                if grid[row+2][column]==0 and (grid[row+1][column]!=0 or grid[row][column]!=0):
                    while grid[row+2][column]==0:
                        grid[row+2][column]=grid[row+1][column]
                        grid[row+1][column]=grid[row][column]
                        grid[row][column]=0

                if grid[row+1][column]==0 and grid[row][column]!=0:
                    while grid[row+1][column]==0:
                        grid[row+1][column]=grid[row][column]
                        grid[row][column]=0
        row=0
        for column in range(0,4):
            if grid[row+3][column]==grid[row+2][column]:
                grid[row+3][column]=grid[row+3][column] + grid[row+2][column]
                grid[row+2][column]=grid[row+1][column]
                grid[row+1][column]=grid[row][column]
                grid[row][column]=0
            if grid[row+2][column]==grid[row+1][column]:
                grid[row+2][column]=grid[row+2][column]+grid[row+1][column]
                grid[row+1][column]=grid[row][column]
                grid[row][column]=0
            if grid[row+1][column]==grid[row][column]:
                grid[row+1][column]=grid[row+1][column]+grid[row][column]
                grid[row][column]=0

    elif keypressed == "l":
        column=0
        for row in range(0,4):

            if grid[row][column]!=0 or grid[row][column+1]!=0 or grid[row][column+2]!=0 or grid[row][column+3]!=0:
                if grid[row][column]==0:
                    while grid[row][column]==0:
                        grid[row][column]=grid[row][column+1]
                        grid[row][column+1]=grid[row][column+2]
                        grid[row][column+2] = grid[row][column+3]
                        grid[row][column+3]=0
                if grid[row][column+1]==0 and (grid[row][column+2]!=0 or grid[row][column+3]!=0):
                    while grid[row][column+1]==0:
                        grid[row][column+1]=grid[row][column+2]
                        grid[row][column+2]=grid[row][column+3]
                        grid[row][column+3]=0
                if grid[row][column+2]==0 and (grid[row][column+3]!=0):
                    while grid[row][column+2]==0:
                        grid[row][column+2]=grid[row][column+3]
                        grid[row][column+3]=0
        column=0
        for row in range(0,4):
            if grid[row][column]==grid[row][column+1]:
                grid[row][column]=grid[row][column]+grid[row][column+1]
                grid[row][column+1]=grid[row][column+2]
                grid[row][column+2]=grid[row][column+3]
                grid[row][column+3]=0
            if grid[row][column+1]==grid[row][column+2]:
                grid[row][column+1]=grid[row][column+1]+grid[row][column+2]
                grid[row][column+2]=grid[row][column+3]
                grid[row][column+3]=0
            if grid[row][column+2]==grid[row][column+3]:
                grid[row][column+2]=grid[row][column+2]+grid[row][column+3]
                grid[row][column+3]=0
    elif keypressed == "r":
        column=0
        for row in range(0,4):
            if grid[row][column]!=0 or grid[row][column+1]!=0 or grid[row][column+2]!=0 or grid[row][column+3]!=0:
                if grid[row][column+3]==0:
                    while grid[row][column+3]==0:
                        grid[row][column+3]=grid[row][column+2]
                        grid[row][column+2]=grid[row][column+1]
                        grid[row][column+1]=grid[row][column]
                        grid[row][column]=0
                if grid[row][column+2]==0 and (grid[row][column+1]!=0 or grid[row][column]!=0):
                    while grid[row][column+2]==0:
                        grid[row][column+2]=grid[row][column+1]
                        grid[row][column+1]=grid[row][column]
                        grid[row][column]=0

                if grid[row][column+1]==0 and grid[row][column]!=0:
                    while grid[row][column+1]==0:
                        grid[row][column+1]=grid[row][column]
                        grid[row][column]=0
        column=0
        for row in range(0,4):
            if grid[row][column+3]==grid[row][column+2]:
                grid[row][column+3]=grid[row][column+3] + grid[row][column+2]
                grid[row][column+2]=grid[row][column+1]
                grid[row][column+1]=grid[row][column]
                grid[row][column]=0
            if grid[row][column+2]==grid[row][column+1]:
                grid[row][column+2]=grid[row][column+2]+grid[row][column+1]
                grid[row][column+1]=grid[row][column]
                grid[row][column]=0
            if grid[row][column+1]==grid[row][column]:
                grid[row][column+1]=grid[row][column+1]+grid[row][column]
                grid[row][column]=0

grid[random.choice([0,1,2,3])][random.choice([0,1,2,3])]=2

while True:
    for y in range(4):
        for x in range(4):
           drawTile(y,x,grid[y][x])

    keypressed=""
    while keypressed=="":
        keypressed = getch.getch().lower()
        if (keypressed!="u") and (keypressed!="d") and (keypressed!="l") and (keypressed!="r") and (keypressed!="q"):
            keypressed=""

    if keypressed!="q":
        updateGrid(keypressed)
        listForRow = []
        listForColumnn = []
        count = 0
        for row in range(0,4):
            for column in range(0,4):
                if grid[row][column]==0:
                    count+=1
                    listForRow.append(row)
                    listForColumnn.append(column)
        if count > 0:
            if count > 1:
                randomIndex = listForRow.index(random.choice(listForRow))
                grid[listForRow[randomIndex]][listForColumnn[randomIndex]]=2
            else:
                grid[listForRow[0]][listForColumnn[0]]=2
        else:
            break
    else:
        break
print "Game over"
<|endoftext|>