<commit_before>"""
Tk-based graphical user interface (GUI).

This package implements a Topographica GUI based on the Tk toolkit,
through the Tkinter interface to Python.  The rest of Topographica
does not depend on this package or any module in it, and thus other
GUIs or other types of interfaces can also be used.

$Id$
"""
__version__='$Revision$'

import sys
import os
import platform
import Tkinter

import param.tk

import topo

from topoconsole import TopoConsole,ControllableMenu

#### notes about tkgui ####
#
## Geometry management
# In several places we use pack() when grid() would probably be
# simpler. Check you know which fits a task better rather than copying
# existing code.
#
## Dialogs
# Don't know how to theme them (can't make them inherit from
# our own class, for instance). Consider making our own dialog
# boxes (subclass of Tkguiwindow) using transient and grab_set:
# http://thread.gmane.org/gmane.comp.python.tkinter/657/focus=659
#
## Mainloop
# Because we don't call mainloop(), it's necessary to call
# update() or update_idletasks() sometimes. Also, I think that sometimes
# current graphics do not update properly (but I'm not sure - I don't
# have a specific example yet). Need to clean up all the scattered
# update() and update_idletasks()...
#
## Window or Frame?
# Maybe one day everything (PlotGroupPanels, ParametersFrameWithApplys,
# ModelEditor, ...) will be Frames inside one master window (for
# e.g. a matlab-like workspace).  Nobody's been worrying too much
# about whether something's a Frame or a window when they've been
# implementing things, so 'close' buttons, title methods, and so on
# are a bit of a mix. This needs to be cleaned up when we have a
# final window organization method in mind.

# When not using the GUI, Topographica does not ordinarily import any of
# the classes in the separate Topographica packages. For example, none
# of the pattern types in topo.patterns is imported in Topographica by
# default.  But for the GUI, we want all such things to be available
# as lists from which the user can select.  To do this, we import all
# pattern types and other such classes here. User-defined classes will
# also appear in the GUI menus if they are derived from any class
# derived from the one specified in each widget, and imported before
# the relevant GUI window starts.
from topo.coordmapper import *
from topo.ep import *
from topo.learningfn import *
from topo.transferfn import *
from topo.pattern import *
from topo.projection import *
from topo.responsefn import *
from topo.sheet import *

##########
### Which os is being used (for gui purposes)?
#
# system_plaform can be:
# "linux"
# "mac"
# "win"
# "unknown"
#
# If you are programming tkgui and need to do something special
# for some other platform (or to further distinguish the above
# platforms), please modify this code.
#
# Right now tkgui only needs to detect if the platform is linux (do I
# mean any kind of non-OS X unix*?) or mac, because there is some
# special-purpose code for both those two: the mac code below, and the
# menu-activating code in topoconsole.  We might have some Windows-
# specific code for the window icons later on, too.
# * actually it's the window manager that's important, right?
# Does tkinter/tk itself give any useful information?
# What about root.tk.call("tk","windowingsystem")?

system_platform = 'unknown'
if platform.system()=='Linux':
    system_platform = 'linux'
elif platform.system()=='Darwin' or platform.mac_ver()[0]:
    system_platform = 'mac'
elif platform.system()=='Windows':
    system_platform = 'win'
##########

#
# Define up the right click (context menu) events. These variables can
# be appended or overridden in .topographicarc, if the user has some
# crazy input device.
#

if system_platform=='mac':
    # if it's on the mac, these are the context-menu events
    right_click_events = ['<Button-2>','<Control-Button-1>']
    right_click_release_events = ['ButtonRelease-2', 'Control-ButtonRelease-1']
else:
    # everywhere else (I think) it's Button-3
    right_click_events = ['<Button-3>']
    right_click_release_events = ['ButtonRelease-2']

global TK_SUPPORTS_DOCK
TK_SUPPORTS_DOCK = True

# CEBALERT: this function needs some cleaning up.
# Some stuff should be moved out to param.tk,
# which could also make this file much simpler.

# gets set to the TopoConsole instance created by start.
console = None
def start(mainloop=False,banner=True):
    """
    Start Tk and read in an options_database file (if present), then
    open a TopoConsole.

    Does nothing if the method has previously been called (i.e. the
    module-level console variable is not None).

    mainloop: If True, then the command-line is frozen while the GUI
    is open.  If False, then commands can be entered at the command-line
    even while the GUI is operational.  Default is False.
    """
    global console

    ### Return immediately if console already set
    # (console itself might have been destroyed but we still want to
    # quit this function before starting another Tk instance, etc)
    if console is not None: return

    if banner: print 'Launching GUI'

    # tcl equivalent of 'if not hasattr(wm,forget)' would be better
    if system_platform=='mac' or Tkinter.TkVersion<8.5:
        global TK_SUPPORTS_DOCK
        TK_SUPPORTS_DOCK=False

    param.tk.initialize()
    param.tk.root.menubar = ControllableMenu(param.tk.root)
    param.tk.root.configure(menu=param.tk.root.menubar)

    # default,clam,alt,classic
    try:
        param.tk.root.tk.call("ttk::style","theme","use","classic")
    except:
        pass

    # Try to read in options from an options_database file
    # (see http://www.itworld.com/AppDev/1243/UIR000616regex/
    # or p. 49 Grayson)
    try:
        options_database = os.path.join(sys.path[0],"topo","tkgui","options_database")
        param.tk.root.option_readfile(options_database)
        print "Read options database from",options_database
    except Tkinter.TclError:
        pass

    console = TopoConsole(param.tk.root)

    # Provide a way for other code to access the GUI when necessary
    # CEBALERT: why is this import necessary? Need to cleanup this method.
    import topo
    topo.guimain=console

    # This alows context menus to work on the Mac.  Widget code should bind
    # contextual menus to the virtual event <<right-click>>, not
    # <Button-3>.
    console.event_add('<<right-click>>',*right_click_events)
    console.event_add('<<right-click-release>>',*right_click_release_events)

    # GUI/threads:
    # http://thread.gmane.org/gmane.comp.python.scientific.user/4153
    # (inc. ipython info)
    # (Also http://mail.python.org/pipermail/python-list/2000-January/021250.html)

    # mainloop() freezes the commandline until the GUI window exits.
    # Without this line the command-line remains responsive.
    if mainloop: param.tk.root.mainloop()

#######################

if __name__ == '__main__':
    start(mainloop=True)

<commit_msg>Corrected Mac right click button codes.<commit_after>"""
Tk-based graphical user interface (GUI).

This package implements a Topographica GUI based on the Tk toolkit,
through the Tkinter interface to Python.  The rest of Topographica
does not depend on this package or any module in it, and thus other
GUIs or other types of interfaces can also be used.

$Id$
"""
__version__='$Revision$'

import sys
import os
import platform
import Tkinter

import param.tk

import topo

from topoconsole import TopoConsole,ControllableMenu

#### notes about tkgui ####
#
## Geometry management
# In several places we use pack() when grid() would probably be
# simpler. Check you know which fits a task better rather than copying
# existing code.
#
## Dialogs
# Don't know how to theme them (can't make them inherit from
# our own class, for instance). Consider making our own dialog
# boxes (subclass of Tkguiwindow) using transient and grab_set:
# http://thread.gmane.org/gmane.comp.python.tkinter/657/focus=659
#
## Mainloop
# Because we don't call mainloop(), it's necessary to call
# update() or update_idletasks() sometimes. Also, I think that sometimes
# current graphics do not update properly (but I'm not sure - I don't
# have a specific example yet). Need to clean up all the scattered
# update() and update_idletasks()...
#
## Window or Frame?
# Maybe one day everything (PlotGroupPanels, ParametersFrameWithApplys,
# ModelEditor, ...) will be Frames inside one master window (for
# e.g. a matlab-like workspace).  Nobody's been worrying too much
# about whether something's a Frame or a window when they've been
# implementing things, so 'close' buttons, title methods, and so on
# are a bit of a mix. This needs to be cleaned up when we have a
# final window organization method in mind.

# When not using the GUI, Topographica does not ordinarily import any of
# the classes in the separate Topographica packages. For example, none
# of the pattern types in topo.patterns is imported in Topographica by
# default.  But for the GUI, we want all such things to be available
# as lists from which the user can select.  To do this, we import all
# pattern types and other such classes here. User-defined classes will
# also appear in the GUI menus if they are derived from any class
# derived from the one specified in each widget, and imported before
# the relevant GUI window starts.
from topo.coordmapper import *
from topo.ep import *
from topo.learningfn import *
from topo.transferfn import *
from topo.pattern import *
from topo.projection import *
from topo.responsefn import *
from topo.sheet import *

##########
### Which os is being used (for gui purposes)?
#
# system_plaform can be:
# "linux"
# "mac"
# "win"
# "unknown"
#
# If you are programming tkgui and need to do something special
# for some other platform (or to further distinguish the above
# platforms), please modify this code.
#
# Right now tkgui only needs to detect if the platform is linux (do I
# mean any kind of non-OS X unix*?) or mac, because there is some
# special-purpose code for both those two: the mac code below, and the
# menu-activating code in topoconsole.  We might have some Windows-
# specific code for the window icons later on, too.
# * actually it's the window manager that's important, right?
# Does tkinter/tk itself give any useful information?
# What about root.tk.call("tk","windowingsystem")?

system_platform = 'unknown'
if platform.system()=='Linux':
    system_platform = 'linux'
elif platform.system()=='Darwin' or platform.mac_ver()[0]:
    system_platform = 'mac'
elif platform.system()=='Windows':
    system_platform = 'win'
##########

#
# Define up the right click (context menu) events. These variables can
# be appended or overridden in .topographicarc, if the user has some
# crazy input device.
#

if system_platform=='mac':
    # if it's on the mac, these are the context-menu events
    right_click_events = ['<Button-3>','<Control-Button-1>']
    right_click_release_events = ['ButtonRelease-3', 'Control-ButtonRelease-1']
else:
    # everywhere else (I think) it's Button-3
    right_click_events = ['<Button-3>']
    right_click_release_events = ['ButtonRelease-3']

global TK_SUPPORTS_DOCK
TK_SUPPORTS_DOCK = True

# CEBALERT: this function needs some cleaning up.
# Some stuff should be moved out to param.tk,
# which could also make this file much simpler.

# gets set to the TopoConsole instance created by start.
console = None
def start(mainloop=False,banner=True):
    """
    Start Tk and read in an options_database file (if present), then
    open a TopoConsole.

    Does nothing if the method has previously been called (i.e. the
    module-level console variable is not None).

    mainloop: If True, then the command-line is frozen while the GUI
    is open.  If False, then commands can be entered at the command-line
    even while the GUI is operational.  Default is False.
    """
    global console

    ### Return immediately if console already set
    # (console itself might have been destroyed but we still want to
    # quit this function before starting another Tk instance, etc)
    if console is not None: return

    if banner: print 'Launching GUI'

    # tcl equivalent of 'if not hasattr(wm,forget)' would be better
    if system_platform=='mac' or Tkinter.TkVersion<8.5:
        global TK_SUPPORTS_DOCK
        TK_SUPPORTS_DOCK=False

    param.tk.initialize()
    param.tk.root.menubar = ControllableMenu(param.tk.root)
    param.tk.root.configure(menu=param.tk.root.menubar)

    # default,clam,alt,classic
    try:
        param.tk.root.tk.call("ttk::style","theme","use","classic")
    except:
        pass

    # Try to read in options from an options_database file
    # (see http://www.itworld.com/AppDev/1243/UIR000616regex/
    # or p. 49 Grayson)
    try:
        options_database = os.path.join(sys.path[0],"topo","tkgui","options_database")
        param.tk.root.option_readfile(options_database)
        print "Read options database from",options_database
    except Tkinter.TclError:
        pass

    console = TopoConsole(param.tk.root)

    # Provide a way for other code to access the GUI when necessary
    # CEBALERT: why is this import necessary? Need to cleanup this method.
    import topo
    topo.guimain=console

    # This alows context menus to work on the Mac.  Widget code should bind
    # contextual menus to the virtual event <<right-click>>, not
    # <Button-3>.
    console.event_add('<<right-click>>',*right_click_events)
    console.event_add('<<right-click-release>>',*right_click_release_events)

    # GUI/threads:
    # http://thread.gmane.org/gmane.comp.python.scientific.user/4153
    # (inc. ipython info)
    # (Also http://mail.python.org/pipermail/python-list/2000-January/021250.html)

    # mainloop() freezes the commandline until the GUI window exits.
    # Without this line the command-line remains responsive.
    if mainloop: param.tk.root.mainloop()

#######################

if __name__ == '__main__':
    start(mainloop=True)

<|endoftext|>


<commit_before># This file is part of BenchExec, a framework for reliable benchmarking:
# https://github.com/sosy-lab/benchexec
#
# SPDX-FileCopyrightText: 2007-2020 Dirk Beyer <https://www.sosy-lab.org>
#
# SPDX-License-Identifier: Apache-2.0

import benchexec
import benchexec.result as result

class Tool(benchexec.tools.template.BaseTool2):
    """
    Tool info for Vampire.
    https://github.com/vprover/vampire
    """

    def name(self):
        return "Vampire"

    def executable(self, tool_locator):
        return tool_locator.find_executable("vampire")

    def version(self, executable):
        line = self._version_from_tool(executable, line_prefix="Vampire")
        line = line.strip()
        line = line.split(" ")[0]
        return line.strip()

    def environment(self, executable):
        return {"keepEnv": {"TPTP": 1}}

    def cmdline(self, executable, options, task, rlimits):
        if "-t" not in options and "--time_limit" not in options:
            if rlimits.walltime is None:
                # Default timeout of Vampire is 60s,
                # so we set value of 0 explicitly (means unlimited)
                options += ["-t", "0"]
            else:
                options += ["-t", f"{rlimits.walltime}s"]

        if "-m" not in options and "--memory_limit" not in options:
            if rlimits.memory is None:
                # No memory limit has been set
                # TODO: should we warn in this case? Vampire is going to use the default of 3000MiB
                pass
            else:
                # Vampire's option '--memory_limit/-m' takes the value in MiB
                memory_mib = rlimits.memory // (1024 * 1024)
                options += ["-m", str(memory_mib)]

        return [executable, *options, task.single_input_file]

    def determine_result(self, run):
        status = self.get_szs_status(run.output)
        if run.exit_code:
            if status == "Timeout":
                return "TIMEOUT"
            if run.exit_code.value == 4:
                # Some kind of system error happened
                if run.output.text.startswith("Parsing Error"):
                    return "PARSING ERROR"
            if run.exit_code.value == 1:
                # Error during portfolio mode
                if run.output.text.startswith("% Exception at proof search level\n"):
                    if any(line.startswith("Parsing Error") for line in run.output):
                        return "PARSING ERROR"
                # Not really an error but unable to finish
                reasons = self.get_other_termination_reasons(run.output)
                if reasons == ["Time limit"]:
                    return "TIMEOUT"
                if reasons == ["Memory limit"]:
                    return "OUT OF MEMORY"
                if reasons == ["Refutation not found, incomplete strategy"]:
                    return "INCOMPLETE"
                if reasons == ["Refutation not found, non-redundant clauses discarded"]:
                    return "INCOMPLETE"
            # Some other error
            return result.RESULT_ERROR
        else:
            # Successfully finished
            if status in self.SZS_UNSAT:
                return result.RESULT_TRUE_PROP
            elif status in self.SZS_SAT:
                return result.RESULT_FALSE_PROP
            else:
                return result.RESULT_UNKNOWN

    # SZS status values that Vampire returns
    SZS_UNSAT = ["ContradictoryAxioms", "Theorem", "Unsatisfiable"]
    SZS_SAT = ["CounterSatisfiable", "Satisfiable"]
    SZS_FAIL = ["Timeout", "GaveUp", "User"]

    def get_szs_status(self, output):
        """
        Extract the SZS status from the output.
        @param output: The output of the tool as instance of class RunOutput.
        @return a non-empty string, or None if no unique SZS status was found
        """
        status = None
        for line in output:
            if line.startswith("% SZS status"):
                if status is None:
                    words = line.split()
                    status = words[3] if len(words) >= 4 else None
                else:
                    # More than one SZS status => this is an error!
                    return None
        return status

    def get_other_termination_reasons(self, output):
        """
        Extract termination reasons from the output from lines starting with '% Termination reason'.
        @param output: The output of the tool as instance of class RunOutput.
        @return List of strings, the termination found in the output (without prefix).
        """
        prefix = "% Termination reason: "
        reasons = []
        for line in output:
            if line.startswith(prefix):
                reasons.append(line[len(prefix) :])
        return reasons

    def get_value_from_output(self, output, identifier):
        if identifier == "szs-status":
            return self.get_szs_status(output)
        return None
<commit_msg>Changes suggested by review<commit_after># This file is part of BenchExec, a framework for reliable benchmarking:
# https://github.com/sosy-lab/benchexec
#
# SPDX-FileCopyrightText: 2007-2020 Dirk Beyer <https://www.sosy-lab.org>
#
# SPDX-License-Identifier: Apache-2.0

import benchexec
import benchexec.result as result

class Tool(benchexec.tools.template.BaseTool2):
    """
    Tool info for Vampire.
    https://github.com/vprover/vampire
    """

    def name(self):
        return "Vampire"

    def executable(self, tool_locator):
        return tool_locator.find_executable("vampire")

    def version(self, executable):
        line = self._version_from_tool(executable, line_prefix="Vampire")
        line = line.strip()
        line = line.split(" ")[0]
        return line.strip()

    def environment(self, executable):
        return {"keepEnv": {"TPTP": 1}}

    def cmdline(self, executable, options, task, rlimits):
        if "-t" not in options and "--time_limit" not in options:
            # Default timeout of Vampire is 60s, so we set value of 0
            # explicitly (i.e. unlimited) if rlimits.walltime is None
            options += ["-t", f"{rlimits.walltime or 0}s"]

        # TODO: should we warn if the memory is not set explicitly?
        # Vampire is going to use the default of 3000MiB in this case
        if "-m" not in options and "--memory_limit" not in options and rlimits.memory:
            # Vampire's option '--memory_limit/-m' takes the value in MiB
            memory_mib = rlimits.memory // (1024 * 1024)
            options += ["-m", str(memory_mib)]

        return [executable, *options, task.single_input_file]

    def determine_result(self, run):
        status = self.get_szs_status(run.output)
        if run.exit_code:
            if status == "Timeout":
                return "TIMEOUT"
            if run.exit_code.value == 4:
                # Some kind of system error happened
                if run.output.text.startswith("Parsing Error"):
                    return "PARSING ERROR"
            if run.exit_code.value == 1:
                # Error during portfolio mode
                if run.output.text.startswith("% Exception at proof search level\n"):
                    if any(line.startswith("Parsing Error") for line in run.output):
                        return "PARSING ERROR"
                # Not really an error but unable to finish
                reasons = self.get_other_termination_reasons(run.output)
                if reasons == ["Time limit"]:
                    return "TIMEOUT"
                if reasons == ["Memory limit"]:
                    return "OUT OF MEMORY"
                if reasons == ["Refutation not found, incomplete strategy"]:
                    return "INCOMPLETE"
                if reasons == ["Refutation not found, non-redundant clauses discarded"]:
                    return "INCOMPLETE"
            # Some other error
            return result.RESULT_ERROR
        else:
            # Successfully finished
            if status in self.SZS_UNSAT:
                return result.RESULT_TRUE_PROP
            elif status in self.SZS_SAT:
                return result.RESULT_FALSE_PROP
            else:
                return result.RESULT_UNKNOWN

    # SZS status values that Vampire returns
    SZS_UNSAT = ["ContradictoryAxioms", "Theorem", "Unsatisfiable"]
    SZS_SAT = ["CounterSatisfiable", "Satisfiable"]
    SZS_FAIL = ["Timeout", "GaveUp", "User"]

    def get_szs_status(self, output):
        """
        Extract the SZS status from the output.
        @param output: The output of the tool as instance of class RunOutput.
        @return a non-empty string, or None if no unique SZS status was found
        """
        status = None
        for line in output:
            if line.startswith("% SZS status"):
                if status is None:
                    words = line.split()
                    status = words[3] if len(words) >= 4 else None
                else:
                    # More than one SZS status => this is an error!
                    return None
        return status

    def get_other_termination_reasons(self, output):
        """
        Extract termination reasons from the output from lines starting with '% Termination reason'.
        @param output: The output of the tool as instance of class RunOutput.
        @return List of strings, the termination found in the output (without prefix).
        """
        prefix = "% Termination reason: "
        reasons = []
        for line in output:
            if line.startswith(prefix):
                reasons.append(line[len(prefix) :])
        return reasons

    def get_value_from_output(self, output, identifier):
        if identifier == "szs-status":
            return self.get_szs_status(output)
        return None
<|endoftext|>


<commit_before>"""
Tk-based graphical user interface (GUI).

This package implements a Topographica GUI based on the Tk toolkit,
through the Tkinter interface to Python.  The rest of Topographica
does not depend on this package or any module in it, and thus other
GUIs or other types of interfaces can also be used.

$Id$
"""
__version__='$Revision$'

import Pmw, sys, Tkinter, platform
import topo.base.parameterizedobject

from topoconsole import TopoConsole

#### notes about tkgui ####
#
## Fonts
# I think we should setup some named font instances here to use
# throughout tkgui, and avoid all the various local specifications
# (which will become very tedious to maintain).  Doing this will give
# other advantages, too, like maybe allowing a user to say "make all
# the fonts a bit bigger", and so on.
# Some font links:
# http://www.pythonware.com/library/tkinter/introduction/x444-fonts.htm
# http://www.astro.washington.edu/owen/ROTKFolklore.html
#
## Geometry management
# In several places we use pack() when grid() would probably be
# simpler. Check you know which fits a task better rather than copying
# existing code.
#
## Pmw
# Not being maintained, and incompatible with some improvements to
# tk (like Tile). Everything we use from Pmw is available from
# other packages (like bwidget, Tix, etc). So maybe try to avoid
# adding more Pmw.
#
## Dialogs
# Don't know how to theme them (can't make them inherit from
# our own class, for instance). Consider making our own dialog
# boxes (subclass of Tkguiwindow) using transient and grab_set:
# http://thread.gmane.org/gmane.comp.python.tkinter/657/focus=659
#
## Mainloop
# Because we don't call mainloop(), it's necessary to call
# update() or update_idletasks() sometimes. Also, I think that sometimes
# current graphics do not update properly (but I'm not sure - I don't
# have a specific example yet). Need to clean up all the scattered
# update() and update_idletasks()...

# When not using the GUI, Topographica does not ordinarily import any of
# the classes in the separate Topographica packages. For example, none
# of the pattern types in topo.patterns is imported in Topographica by
# default.  But for the GUI, we want all such things to be available
# as lists from which the user can select.  To do this, we import all
# pattern types and other such classes here. User-defined classes will
# also appear in the GUI menus if they are derived from any class
# derived from the one specified in each widget, and imported before
# the relevant GUI window starts.
from topo.coordmapperfns import *
from topo.eps import *
from topo.learningfns import *
from topo.outputfns import *
from topo.patterns import *
from topo.projections import *
from topo.responsefns import *
from topo.sheets import *

from topo.base.cf import CFPLearningFnParameter,CFPOutputFnParameter,CFPResponseFnParameter
from topo.base.functionfamilies import LearningFnParameter,OutputFnParameter,ResponseFnParameter
from topo.base.patterngenerator import PatternGeneratorParameter

##########
### Which os is being used (for gui purposes)?
#
# system_plaform can be:
# "linux"
# "mac"
# "win"
# "unknown"
#
# If you are programming tkgui and need to do something special
# for some other platform (or to further distinguish the above
# platforms), please modify this code.
#
# Right now tkgui only needs to detect if the platform is linux (do I
# mean any kind of non-OS X unix*?) or mac, because there is some
# special-purpose code for both those two: the mac code below, and the
# menu-activating code in topoconsole.  We might have some Windows-
# specific code for the window icons later on, too.
# * actually it's the window manager that's important, right?
# Does tkinter/tk itself give any useful information?
# What about root.tk.call("tk","windowingsystem")?
system_platform = 'unknown'
if platform.system()=='Linux':
    system_platform = 'linux'
elif platform.system()=='Darwin' or platform.mac_ver()[0]:
    system_platform = 'mac'
elif platform.system()=='Windows':
    system_platform = 'win'
##########

#
# Define up the right click (context menu) events. These variables can
# be appended or overridden in .topographicarc, if the user has some
# crazy input device.
#
if system_platform is 'mac':
    # if it's on the mac, these are the context-menu events
    right_click_events = ['<Button-2>','<Control-Button-1>']
    right_click_release_events = ['ButtonRelease-2', 'Control-ButtonRelease-1']
else:
    # everywhere else (I think) it's Button-3
    right_click_events = ['<Button-3>']
    right_click_release_events = ['ButtonRelease-2']

def show_cmd_prompt():
    """
    Small helper to print the sys.ps1 prompt to the command-line.
    Useful after a bunch of output has been displayed to stdout,
    so as to let the user know that the command-line is still
    active.
    """
    if topo.base.parameterizedobject.min_print_level >= topo.base.parameterizedobject.MESSAGE:
        print "\n", sys.ps1,
        sys.stdout.flush()

def start(mainloop=False):
    """
    Startup code for GUI.

    mainloop: If True, then the command-line is frozen while the GUI
    is open.  If False, then commands can be entered at the command-line
    even while the GUI is operational.  Default is False.
    """

    # Creating an initial Tk() instance and then withdrawing the
    # window is a common technique. Instead of doing this, having
    # TopoConsole itself be a subclass of Tk would make sense - since
    # it is the main application window - but then we could not have a
    # hierarchy in which all windows are given some common properties.
    root = Tkinter.Tk()
    root.withdraw()
    Pmw.initialise(root)

    console = TopoConsole()

    # This alows context menus to work on the Mac.  Widget code should bind
    # contextual menus to the virtual event <<right-click>>, not
    # <Button-3>.
    console.event_add('<<right-click>>',*right_click_events)
    console.event_add('<<right-click-release>>',*right_click_release_events)

    # GUI/threads:
    # http://thread.gmane.org/gmane.comp.python.scientific.user/4153
    # (inc. ipython info)
    # (Also http://mail.python.org/pipermail/python-list/2000-January/021250.html)

    # mainloop() freezes the commandline until the GUI window exits.
    # Without this line the command-line remains responsive.
    if mainloop:
        console.mainloop()

    return console

#######################

if __name__ == '__main__':
    start(mainloop=True)

<commit_msg>Pasted in code for using Tile from an old copy of Topographica (here for reference).<commit_after>"""
Tk-based graphical user interface (GUI).

This package implements a Topographica GUI based on the Tk toolkit,
through the Tkinter interface to Python.  The rest of Topographica
does not depend on this package or any module in it, and thus other
GUIs or other types of interfaces can also be used.

$Id$
"""
__version__='$Revision$'

import Pmw, sys, Tkinter, platform
import topo.base.parameterizedobject

from topoconsole import TopoConsole

#### notes about tkgui ####
#
## Fonts
# I think we should setup some named font instances here to use
# throughout tkgui, and avoid all the various local specifications
# (which will become very tedious to maintain).  Doing this will give
# other advantages, too, like maybe allowing a user to say "make all
# the fonts a bit bigger", and so on.
# Some font links:
# http://www.pythonware.com/library/tkinter/introduction/x444-fonts.htm
# http://www.astro.washington.edu/owen/ROTKFolklore.html
#
## Geometry management
# In several places we use pack() when grid() would probably be
# simpler. Check you know which fits a task better rather than copying
# existing code.
#
## Pmw
# Not being maintained, and incompatible with some improvements to
# tk (like Tile). Everything we use from Pmw is available from
# other packages (like bwidget, Tix, etc). So maybe try to avoid
# adding more Pmw.
#
## Dialogs
# Don't know how to theme them (can't make them inherit from
# our own class, for instance). Consider making our own dialog
# boxes (subclass of Tkguiwindow) using transient and grab_set:
# http://thread.gmane.org/gmane.comp.python.tkinter/657/focus=659
#
## Mainloop
# Because we don't call mainloop(), it's necessary to call
# update() or update_idletasks() sometimes. Also, I think that sometimes
# current graphics do not update properly (but I'm not sure - I don't
# have a specific example yet). Need to clean up all the scattered
# update() and update_idletasks()...

# When not using the GUI, Topographica does not ordinarily import any of
# the classes in the separate Topographica packages. For example, none
# of the pattern types in topo.patterns is imported in Topographica by
# default.  But for the GUI, we want all such things to be available
# as lists from which the user can select.  To do this, we import all
# pattern types and other such classes here. User-defined classes will
# also appear in the GUI menus if they are derived from any class
# derived from the one specified in each widget, and imported before
# the relevant GUI window starts.
from topo.coordmapperfns import *
from topo.eps import *
from topo.learningfns import *
from topo.outputfns import *
from topo.patterns import *
from topo.projections import *
from topo.responsefns import *
from topo.sheets import *

from topo.base.cf import CFPLearningFnParameter,CFPOutputFnParameter,CFPResponseFnParameter
from topo.base.functionfamilies import LearningFnParameter,OutputFnParameter,ResponseFnParameter
from topo.base.patterngenerator import PatternGeneratorParameter

##########
### Which os is being used (for gui purposes)?
#
# system_plaform can be:
# "linux"
# "mac"
# "win"
# "unknown"
#
# If you are programming tkgui and need to do something special
# for some other platform (or to further distinguish the above
# platforms), please modify this code.
#
# Right now tkgui only needs to detect if the platform is linux (do I
# mean any kind of non-OS X unix*?) or mac, because there is some
# special-purpose code for both those two: the mac code below, and the
# menu-activating code in topoconsole.  We might have some Windows-
# specific code for the window icons later on, too.
# * actually it's the window manager that's important, right?
# Does tkinter/tk itself give any useful information?
# What about root.tk.call("tk","windowingsystem")?
system_platform = 'unknown'
if platform.system()=='Linux':
    system_platform = 'linux'
elif platform.system()=='Darwin' or platform.mac_ver()[0]:
    system_platform = 'mac'
elif platform.system()=='Windows':
    system_platform = 'win'
##########

#
# Define up the right click (context menu) events. These variables can
# be appended or overridden in .topographicarc, if the user has some
# crazy input device.
#
if system_platform is 'mac':
    # if it's on the mac, these are the context-menu events
    right_click_events = ['<Button-2>','<Control-Button-1>']
    right_click_release_events = ['ButtonRelease-2', 'Control-ButtonRelease-1']
else:
    # everywhere else (I think) it's Button-3
    right_click_events = ['<Button-3>']
    right_click_release_events = ['ButtonRelease-2']

def show_cmd_prompt():
    """
    Small helper to print the sys.ps1 prompt to the command-line.
    Useful after a bunch of output has been displayed to stdout,
    so as to let the user know that the command-line is still
    active.
    """
    if topo.base.parameterizedobject.min_print_level >= topo.base.parameterizedobject.MESSAGE:
        print "\n", sys.ps1,
        sys.stdout.flush()

## def ttkify(root,widget):
##     la = "ttk::"+widget
##     root.tk.call('namespace', 'import', '-force', la)

def start(mainloop=False):
    """
    Startup code for GUI.

    mainloop: If True, then the command-line is frozen while the GUI
    is open.  If False, then commands can be entered at the command-line
    even while the GUI is operational.  Default is False.
    """

    # Creating an initial Tk() instance and then withdrawing the
    # window is a common technique. Instead of doing this, having
    # TopoConsole itself be a subclass of Tk would make sense - since
    # it is the main application window - but then we could not have a
    # hierarchy in which all windows are given some common properties.
    root = Tkinter.Tk()
    root.withdraw()

##     root.tk.call('package', 'require', 'tile')
##     widgets_to_ttkify = ['button'] #,'scrollbar','frame','labelframe','label','text','combobox']

##     for w in widgets_to_ttkify:
##         ttkify(root,w)

##     #root.tk.call('namespace', 'import','-force','ttk::button')  # ,'force'
##     root.tk.call('tile::setTheme', 'default')

    Pmw.initialise(root)

    console = TopoConsole()

    # This alows context menus to work on the Mac.  Widget code should bind
    # contextual menus to the virtual event <<right-click>>, not
    # <Button-3>.
    console.event_add('<<right-click>>',*right_click_events)
    console.event_add('<<right-click-release>>',*right_click_release_events)

    # GUI/threads:
    # http://thread.gmane.org/gmane.comp.python.scientific.user/4153
    # (inc. ipython info)
    # (Also http://mail.python.org/pipermail/python-list/2000-January/021250.html)

    # mainloop() freezes the commandline until the GUI window exits.
    # Without this line the command-line remains responsive.
    if mainloop:
        console.mainloop()

    return console

#######################

if __name__ == '__main__':
    start(mainloop=True)

<|endoftext|>


<commit_before>from chess_move import ChessMove
from chess_position import ChessPosition

import chess.uci

class ChessLibrary():
    def __init__(self):
        # Setup Stockfish engine
        self.board = chess.Board()
        self.engine = chess.uci.popen_engine("stockfish_8")
        self.engine.uci()

    """Gives a ChessMove object to the third-party library, which is then pushed to the board if ok
    Arg:
        - move: A ChessMove object which is then translated into a UCI move
    Raises:
        - ValueError: Raised if the move given is illegal
        - TypeError: Raised if parameter 'move' is not of type ChessMove
    """
    def hand_off(self, move):
        if isinstance(move, ChessMove):
            try:
                self.board.push_uci(move.__str__())
                self.engine.position(self.board)
            except ValueError:
                print("Invalid move: {}!".format(str(move)))
        else:
            raise TypeError("Parameter of hand_off must be of type ChessMove")

    """Asks Chess Library for a move, pushes it to board, and returns it as a ChessMove object
    Returns:
        - A ChessMove object which shows where the chess engine decided to move
    """
    def get_move(self):
        command = self.engine.go(movetime=2000, async_callback=True)
        best_move, ponder = command.result()
        bm = str(best_move)

        # Converts UCI protocol to ChessPosition via slicing
        init = ChessPosition(str(bm[:1]), int(bm[1:-2]))
        final = ChessPosition(str(bm[2:-1]), int(bm[3:]))

        return ChessMove(init, final)

    """Evaluates whether the game is over or not
    Returns:
        - A boolean which is true if the game has ended, false if not
    """
    def is_game_over(self):
        return self.board.is_game_over()

    """Sets difficulty. Must be between 0 and 20, 20 being hardest
    Raises:
        - ValueError: Raised if the difficulty is not within legal boundaries
    """
    def set_difficulty(self, difficulty):
        if difficulty < 0 or difficulty > 20:
            raise ValueError("Difficulty must be between 0 and 20 inclusive")
        else:
            new_options = {'Skill Level': difficulty}
            self.engine.setoption(new_options)
<commit_msg>Added documentation to chess_library<commit_after>from chess_move import ChessMove
from chess_position import ChessPosition

import chess.uci

class ChessLibrary():
    def __init__(self):
        # Setup Stockfish engine
        self.board = chess.Board()
        self.engine = chess.uci.popen_engine("stockfish_8")
        self.engine.uci()

    """Gives a ChessMove object to the third-party library, which is then pushed to the board if ok
    Arg:
        - move: A ChessMove object which is then translated into a UCI move
    Raises:
        - ValueError: Raised if the move given is illegal
        - TypeError: Raised if parameter 'move' is not of type ChessMove
    """
    def hand_off(self, move):
        if isinstance(move, ChessMove):
            try:
                self.board.push_uci(move.__str__())
                self.engine.position(self.board)
            except ValueError:
                print("Invalid move: {}!".format(str(move)))
        else:
            raise TypeError("Parameter of hand_off must be of type ChessMove")

    """Asks Chess Library for a move, pushes it to board, and then returns it as a ChessMove object
    Returns:
        - A ChessMove object which shows where the chess engine decided to move
    """
    def get_move(self):
        command = self.engine.go(movetime=2000, async_callback=True)
        best_move, ponder = command.result()
        bm = str(best_move)

        # Converts UCI protocol to ChessPosition via slicing
        init = ChessPosition(str(bm[:1]), int(bm[1:-2]))
        final = ChessPosition(str(bm[2:-1]), int(bm[3:]))

        return ChessMove(init, final)

    """Evaluates whether the game is over or not
    Returns:
        - A boolean which is true if the game has ended, false if not
    """
    def is_game_over(self):
        return self.board.is_game_over()

    """Sets difficulty. Must be between 0 and 20, 20 being hardest
    Raises:
        - ValueError: Raised if the difficulty is not within legal boundaries
    """
    def set_difficulty(self, difficulty):
        if difficulty < 0 or difficulty > 20:
            raise ValueError("Difficulty must be between 0 and 20 inclusive")
        else:
            new_options = {'Skill Level': difficulty}
            self.engine.setoption(new_options)
<|endoftext|>


<commit_before># coding=utf-8
from __future__ import print_function, unicode_literals

import os
import re
import time as Time
import urllib

import requests
from bs4 import BeautifulSoup

from bgmi.config import (MAX_PAGE, SHARE_DMHY_URL, IS_PYTHON3)
from bgmi.utils import print_error
from bgmi.website.base import BaseWebsite

if IS_PYTHON3:
    unquote = urllib.parse.unquote
else:
    unquote = urllib.unquote

base_url = SHARE_DMHY_URL

def fetch_url(url, **kwargs):
    ret = None
    try:
        ret = requests.get(url, **kwargs).text
    except requests.ConnectionError:
        print_error('Create connection to {site}... failed'.format(site=SHARE_DMHY_URL), exit_=False)
        print_error('Check internet connection or try to set a DMHY mirror site via: bgmi config SHARE_DMHY_URL <site url>')

    return ret

def parse_bangumi_with_week_days(content, update_time, array_name):
    r = re.compile(array_name + '\.push\(\[\'(.*?)\',\'(.*?)\',\'(.*?)\',\'(.*?)\',\'(.*?)\'\]\)')
    ret = r.findall(content)

    bangumi_list = []
    subtitle_list = []

    for bangumi_row in ret:
        bangumi = {
            "status": 0,
            "subtitle_group": [],
            "name": "",
            "keyword": "",  # bangumi id
            "update_time": "",
            "cover": ""
        }
        (cover_url, name, keyword, subtitle_raw, _) = bangumi_row
        cover = re.findall('(/images/.*)$', cover_url)[0]

        bs = BeautifulSoup(subtitle_raw, 'lxml')
        a_list = bs.find_all('a')

        for a in a_list:
            subtitle_group_name = a.get_text(strip=True)
            subtitle_group_id_raw = re.findall('team_id%3A(.+)$', a['href'])

            if (len(subtitle_group_id_raw) == 0) or subtitle_group_name == '':
                continue

            subtitle_group_id = subtitle_group_id_raw[0]
            # append to subtitle_list
            subtitle_list.append({
                'id': subtitle_group_id,
                'name': subtitle_group_name
            })

            bangumi['subtitle_group'].append(subtitle_group_id)
            pass

        bangumi['name'] = name
        bangumi['update_time'] = update_time
        bangumi['keyword'] = keyword
        bangumi['cover'] = cover

        # append to bangumi_list
        bangumi_list.append(bangumi)

    return bangumi_list, subtitle_list

def parse_subtitle_list(content):
    subtitle_list = []

    bs = BeautifulSoup(content, 'lxml')
    li_list = bs.find_all('li', {'class': 'team-item'})

    for li in li_list:
        subtitle_group_name = li.span.a.get('title')
        subtitle_group_id_raw = re.findall('team_id\/(.+)$', li.span.a.get('href'))

        if (len(subtitle_group_id_raw) == 0) or subtitle_group_name == '':
            continue

        subtitle_group_id = subtitle_group_id_raw[0]
        # append to subtitle_list
        subtitle_list.append({
            'id': subtitle_group_id,
            'name': subtitle_group_name
        })

    return subtitle_list

def unique_subtitle_list(raw_list):
    ret = []
    id_list = list({i['id'] for i in raw_list})
    for row in raw_list:
        if row['id'] in id_list:
            ret.append(row)
            del id_list[id_list.index(row['id'])]

    return ret

class DmhySource(BaseWebsite):
    cover_url = SHARE_DMHY_URL

    def search_by_keyword(self, keyword, count=None):
        """
        return a list of dict with at least 4 key: download, name, title, episode
        example:
        ```
            [
                {
                    'name':"路人女主的养成方法",
                    'download': 'magnet:?xt=urn:btih:what ever',
                    'title': "[澄空学园] 路人女主的养成方法 第12话 MP4 720p  完",
                    'episode': 12
                },
            ]
        ```
        :param keyword: search key word
        :type keyword: str
        :param count: how many page to fetch from website
        :type count: int

        :return: list of episode search result
        :rtype: list[dict]
        """
        if count == None:
            count = 3

        result = []
        search_url = base_url + '/topics/list/'
        for i in range(count):

            params = {'keyword': keyword, 'page': i + 1}

            if os.environ.get('DEBUG', False):  # pragma: no cover
                print(search_url, params)

            r = fetch_url(search_url, params=params)
            bs = BeautifulSoup(r, 'lxml')

            table = bs.find('table', {'id': 'topic_list'})
            if table == None:
                break
            tr_list = table.tbody.find_all('tr', {'class': ''})
            for tr in tr_list:

                td_list = tr.find_all('td')

                if td_list[1].a['class'][0] != 'sort-2':
                    continue

                time_string = td_list[0].span.string
                name = keyword
                title = td_list[2].find('a', {'target': '_blank'}).get_text(strip=True)
                download = td_list[3].a['href']
                episode = self.parse_episode(title)
                time = int(Time.mktime(Time.strptime(time_string, "%Y/%m/%d %H:%M")))

                result.append({
                    'name': name,
                    'title': title,
                    'download': download,
                    'episode': episode,
                    'time': time,
                })

        return result

    def fetch_bangumi_calendar_and_subtitle_group(self):
        """
        return a list of all bangumi and a list of all subtitle group

        list of bangumi dict:
        update time should be one of ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
        example:
        ```
            [
                {
                    "status": 0,
                    "subtitle_group": [
                        "123",
                        "456"
                    ],
                    "name": "名侦探柯南",
                    "keyword": "1234", #bangumi id
                    "update_time": "Sat",
                    "cover": "data/images/cover1.jpg"
                },
            ]
        ```

        list of subtitle group dict:
        example:
        ```
            [
                {
                    'id': '233',
                    'name': 'bgmi字幕组'
                }
            ]
        ```

        :return: list of bangumi, list of subtitile group
        :rtype: (list[dict], list[dict])
        """
        week_days_mapping = [
            ('Sun', 'sunarray'),
            ('Mon', 'monarray'),
            ('Tue', 'tuearray'),
            ('Wed', 'wedarray'),
            ('Thu', 'thuarray'),
            ('Fri', 'friarray'),
            ('Sat', 'satarray'),
        ]

        bangumi_list = []
        subtitle_list = []

        url = base_url + '/cms/page/name/programme.html'

        r = fetch_url(url)

        for update_time, array_name in week_days_mapping:
            (b_list, s_list) = parse_bangumi_with_week_days(r, update_time, array_name)
            bangumi_list.extend(b_list)
            subtitle_list.extend(s_list)
            pass

        # fetch subtitle
        url = base_url + '/team/navigate/'

        r = fetch_url(url)

        subtitle_list.extend(parse_subtitle_list(r))

        # unique
        subtitle_list = unique_subtitle_list(subtitle_list)

        if os.environ.get('DEBUG', False):  # pragma: no cover
            print(subtitle_list)

        return (bangumi_list, subtitle_list)

    def fetch_episode_of_bangumi(self, bangumi_id, subtitle_list=None, max_page=MAX_PAGE):
        """
        get all episode by bangumi id
        example
        ```
            [
                {
                    "download": "magnet:?xt=urn:btih:e43b3b6b53dd9fd6af1199e112d3c7ff15cab82c",
                    "subtitle_group": "58a9c1c9f5dc363606ab42ec",
                    "title": "【喵萌奶茶屋】★七月新番★[来自深渊/Made in Abyss][07][GB][720P]",
                    "episode": 0,
                    "time": 1503301292
                },
            ]
        ```

        :param bangumi_id: bangumi_id
        :param subtitle_list: list of subtitle group
        :type subtitle_list: list
        :param max_page: how many page you want to crawl if there is no subtitle list
        :type max_page: int
        :return: list of bangumi
        :rtype: list[dict]
        """
        result = []
        keyword = bangumi_id
        search_url = base_url + '/topics/list/'
        for i in range(max_page):

            # params = {'keyword': keyword, 'page': i + 1}

            url = search_url+'?keyword='+keyword+'&page='+str(i + 1)

            if os.environ.get('DEBUG', False):  # pragma: no cover
                print(url)

            r = fetch_url(url)
            bs = BeautifulSoup(r, 'lxml')

            table = bs.find('table', {'id': 'topic_list'})
            if table == None:
                break
            tr_list = table.tbody.find_all('tr', {'class': ''})
            for tr in tr_list:

                td_list = tr.find_all('td')

                if td_list[1].a['class'][0] != 'sort-2':
                    continue

                time_string = td_list[0].span.string
                name = keyword
                title = td_list[2].find('a', {'target': '_blank'}).get_text(strip=True)
                download = td_list[3].a['href']
                episode = self.parse_episode(title)
                time = int(Time.mktime(Time.strptime(time_string, "%Y/%m/%d %H:%M")))
                subtitle_group = ''

                tag_list = td_list[2].find_all('span', {'class': 'tag'})

                for tag in tag_list:

                    href = tag.a.get('href')
                    if href == None:
                        continue

                    team_id_raw = re.findall('team_id\/(.*)$', href)
                    if len(team_id_raw) == 0:
                        continue
                    subtitle_group = team_id_raw[0]

                if subtitle_list:
                    if subtitle_group not in subtitle_list:
                        continue

                if os.environ.get('DEBUG', False):  # pragma: no cover
                    print(name, title, subtitle_group, download, episode, time)

                result.append({
                    'name': name,
                    'title': title,
                    'subtitle_group': subtitle_group,
                    'download': download,
                    'episode': episode,
                    'time': time,
                })

        return result

    pass
<commit_msg>bug fix<commit_after># coding=utf-8
from __future__ import print_function, unicode_literals

import os
import re
import time as Time
import urllib

import requests
from bs4 import BeautifulSoup

from bgmi.config import (MAX_PAGE, SHARE_DMHY_URL, IS_PYTHON3)
from bgmi.utils import print_error
from bgmi.website.base import BaseWebsite

if IS_PYTHON3:
    unquote = urllib.parse.unquote
else:
    unquote = urllib.unquote

base_url = SHARE_DMHY_URL

def fetch_url(url, **kwargs):
    ret = None
    try:
        ret = requests.get(url, **kwargs).text
    except requests.ConnectionError:
        print_error('Create connection to {site}... failed'.format(site=SHARE_DMHY_URL), exit_=False)
        print_error(
            'Check internet connection or try to set a DMHY mirror site via: bgmi config SHARE_DMHY_URL <site url>')

    return ret

def parse_bangumi_with_week_days(content, update_time, array_name):
    r = re.compile(array_name + '\.push\(\[\'(.*?)\',\'(.*?)\',\'(.*?)\',\'(.*?)\',\'(.*?)\'\]\)')
    ret = r.findall(content)

    bangumi_list = []
    subtitle_list = []

    for bangumi_row in ret:
        bangumi = {
            "status": 0,
            "subtitle_group": [],
            "name": "",
            "keyword": "",  # bangumi id
            "update_time": "",
            "cover": ""
        }
        (cover_url, name, keyword, subtitle_raw, _) = bangumi_row
        cover = re.findall('(/images/.*)$', cover_url)[0]

        bs = BeautifulSoup(subtitle_raw, 'lxml')
        a_list = bs.find_all('a')

        for a in a_list:
            subtitle_group_name = a.get_text(strip=True)
            subtitle_group_id_raw = re.findall('team_id%3A(.+)$', a['href'])

            if (len(subtitle_group_id_raw) == 0) or subtitle_group_name == '':
                continue

            subtitle_group_id = subtitle_group_id_raw[0]
            # append to subtitle_list
            subtitle_list.append({
                'id': subtitle_group_id,
                'name': subtitle_group_name
            })

            bangumi['subtitle_group'].append(subtitle_group_id)
            pass

        bangumi['name'] = name
        bangumi['update_time'] = update_time
        bangumi['keyword'] = keyword
        bangumi['cover'] = cover

        # append to bangumi_list
        bangumi_list.append(bangumi)

    return bangumi_list, subtitle_list

def parse_subtitle_list(content):
    subtitle_list = []

    bs = BeautifulSoup(content, 'lxml')
    li_list = bs.find_all('li', {'class': 'team-item'})

    for li in li_list:
        subtitle_group_name = li.span.a.get('title')
        subtitle_group_id_raw = re.findall('team_id\/(.+)$', li.span.a.get('href'))

        if (len(subtitle_group_id_raw) == 0) or subtitle_group_name == '':
            continue

        subtitle_group_id = subtitle_group_id_raw[0]
        # append to subtitle_list
        subtitle_list.append({
            'id': subtitle_group_id,
            'name': subtitle_group_name
        })

    return subtitle_list

def unique_subtitle_list(raw_list):
    ret = []
    id_list = list({i['id'] for i in raw_list})
    for row in raw_list:
        if row['id'] in id_list:
            ret.append(row)
            del id_list[id_list.index(row['id'])]

    return ret

class DmhySource(BaseWebsite):
    cover_url = SHARE_DMHY_URL

    def search_by_keyword(self, keyword, count=None):
        """
        return a list of dict with at least 4 key: download, name, title, episode
        example:
        ```
            [
                {
                    'name':"路人女主的养成方法",
                    'download': 'magnet:?xt=urn:btih:what ever',
                    'title': "[澄空学园] 路人女主的养成方法 第12话 MP4 720p  完",
                    'episode': 12
                },
            ]
        ```
        :param keyword: search key word
        :type keyword: str
        :param count: how many page to fetch from website
        :type count: int

        :return: list of episode search result
        :rtype: list[dict]
        """
        if count == None:
            count = 3

        result = []
        search_url = base_url + '/topics/list/'
        for i in range(count):

            params = {'keyword': keyword, 'page': i + 1}

            if os.environ.get('DEBUG', False):  # pragma: no cover
                print(search_url, params)

            r = fetch_url(search_url, params=params)
            bs = BeautifulSoup(r, 'lxml')

            table = bs.find('table', {'id': 'topic_list'})
            if table == None:
                break
            tr_list = table.tbody.find_all('tr', {'class': ''})
            for tr in tr_list:

                td_list = tr.find_all('td')

                if td_list[1].a['class'][0] != 'sort-2':
                    continue

                time_string = td_list[0].span.string
                name = keyword
                title = td_list[2].find('a', {'target': '_blank'}).get_text(strip=True)
                download = td_list[3].a['href']
                episode = self.parse_episode(title)
                time = int(Time.mktime(Time.strptime(time_string, "%Y/%m/%d %H:%M")))

                result.append({
                    'name': name,
                    'title': title,
                    'download': download,
                    'episode': episode,
                    'time': time,
                })

        return result

    def fetch_bangumi_calendar_and_subtitle_group(self):
        """
        return a list of all bangumi and a list of all subtitle group

        list of bangumi dict:
        update time should be one of ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
        example:
        ```
            [
                {
                    "status": 0,
                    "subtitle_group": [
                        "123",
                        "456"
                    ],
                    "name": "名侦探柯南",
                    "keyword": "1234", #bangumi id
                    "update_time": "Sat",
                    "cover": "data/images/cover1.jpg"
                },
            ]
        ```

        list of subtitle group dict:
        example:
        ```
            [
                {
                    'id': '233',
                    'name': 'bgmi字幕组'
                }
            ]
        ```

        :return: list of bangumi, list of subtitile group
        :rtype: (list[dict], list[dict])
        """
        week_days_mapping = [
            ('Sun', 'sunarray'),
            ('Mon', 'monarray'),
            ('Tue', 'tuearray'),
            ('Wed', 'wedarray'),
            ('Thu', 'thuarray'),
            ('Fri', 'friarray'),
            ('Sat', 'satarray'),
        ]

        bangumi_list = []
        subtitle_list = []

        url = base_url + '/cms/page/name/programme.html'

        r = fetch_url(url)

        for update_time, array_name in week_days_mapping:
            (b_list, s_list) = parse_bangumi_with_week_days(r, update_time, array_name)
            bangumi_list.extend(b_list)
            subtitle_list.extend(s_list)
            pass

        # fetch subtitle
        url = base_url + '/team/navigate/'

        r = fetch_url(url)

        subtitle_list.extend(parse_subtitle_list(r))

        # unique
        subtitle_list = unique_subtitle_list(subtitle_list)

        if os.environ.get('DEBUG', False):  # pragma: no cover
            print(subtitle_list)

        return (bangumi_list, subtitle_list)

    def fetch_episode_of_bangumi(self, bangumi_id, subtitle_list=None, max_page=int(MAX_PAGE)):
        """
        get all episode by bangumi id
        example
        ```
            [
                {
                    "download": "magnet:?xt=urn:btih:e43b3b6b53dd9fd6af1199e112d3c7ff15cab82c",
                    "subtitle_group": "58a9c1c9f5dc363606ab42ec",
                    "title": "【喵萌奶茶屋】★七月新番★[来自深渊/Made in Abyss][07][GB][720P]",
                    "episode": 0,
                    "time": 1503301292
                },
            ]
        ```

        :param bangumi_id: bangumi_id
        :param subtitle_list: list of subtitle group
        :type subtitle_list: list
        :param max_page: how many page you want to crawl if there is no subtitle list
        :type max_page: int
        :return: list of bangumi
        :rtype: list[dict]
        """
        result = []
        keyword = bangumi_id
        search_url = base_url + '/topics/list/'
        for i in range(max_page):

            # params = {'keyword': keyword, 'page': i + 1}

            url = search_url + '?keyword=' + keyword + '&page=' + str(i + 1)

            if os.environ.get('DEBUG', False):  # pragma: no cover
                print(url)

            r = fetch_url(url)
            bs = BeautifulSoup(r, 'lxml')

            table = bs.find('table', {'id': 'topic_list'})
            if table == None:
                break
            tr_list = table.tbody.find_all('tr', {'class': ''})
            for tr in tr_list:

                td_list = tr.find_all('td')

                if td_list[1].a['class'][0] != 'sort-2':
                    continue

                time_string = td_list[0].span.string
                name = keyword
                title = td_list[2].find('a', {'target': '_blank'}).get_text(strip=True)
                download = td_list[3].a['href']
                episode = self.parse_episode(title)
                time = int(Time.mktime(Time.strptime(time_string, "%Y/%m/%d %H:%M")))
                subtitle_group = ''

                tag_list = td_list[2].find_all('span', {'class': 'tag'})

                for tag in tag_list:

                    href = tag.a.get('href')
                    if href == None:
                        continue

                    team_id_raw = re.findall('team_id\/(.*)$', href)
                    if len(team_id_raw) == 0:
                        continue
                    subtitle_group = team_id_raw[0]

                if subtitle_list:
                    if subtitle_group not in subtitle_list:
                        continue

                if os.environ.get('DEBUG', False):  # pragma: no cover
                    print(name, title, subtitle_group, download, episode, time)

                result.append({
                    'name': name,
                    'title': title,
                    'subtitle_group': subtitle_group,
                    'download': download,
                    'episode': episode,
                    'time': time,
                })

        return result

    pass
<|endoftext|>


<commit_before>"""
spaceshooter.py
Author: Ethan Adner
Credit:
ta presence, n'importe ou, me console. Au cas que ton ceour bat, je suis content
mon amour pour toi est eternel et vivante
sans vous, mes
Assignment:
Write and submit a program that implements the spacewar game:
https://github.com/HHS-IntroProgramming/Spacewar

tutorial4.py
by E. Dennison
"""

from ggame import App, RectangleAsset, ImageAsset, Sprite, LineStyle, Color, Frame
from math import sin, cos, pi

SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 700
"""
xli=[]
for x in range(-25,25):
    xli.append(x+500)
yli=[]
for x in range(-25, 25):
    yli.append(x+300)
"""

class sun(Sprite):

    asset1 = ImageAsset("images/sun.png")
    height = 50
    width = 50

    def __init__(self, position):
        super().__init__(sun.asset1, position)

class SpaceShip(Sprite):

#    Animated space ship

    asset = ImageAsset("images/four_spaceship_by_albertov_with_thrust.png",
    Frame(227,0,292-227,125), 4, 'vertical')

    def __init__(self, position):
        super().__init__(SpaceShip.asset, position)
        self.vx = 0
        self.vy = 0
        self.vr = .0
        self.thrust = 0
        self.thrustframe = 1

        SpaceGame.listenKeyEvent("keydown", "q", self.clockwise)
        SpaceGame.listenKeyEvent("keyup", "q", self.stopr)
        SpaceGame.listenKeyEvent("keydown", "e", self.cntrclockwise)
        SpaceGame.listenKeyEvent("keyup", "e", self.stopr)
        SpaceGame.listenKeyEvent("keydown", "space", self.thrustOn)
        SpaceGame.listenKeyEvent("keyup", "space", self.thrustOff)
        #SpaceGame.listenKeyEvent("keyup", "s", self.shoot)

        self.fxcenter = self.fycenter = 0.5

    def step(self):
        self.x += self.vx
        self.y += self.vy
        self.rotation += self.vr
        self.explode(self.x, self.y)
        if self.explode(self.x, self.y) == True:
            return()
        if self.thrust==1:
            self.vx=.1*cos(self.rotation+1/2*pi)+self.vx
            self.vy=.1*sin(self.rotation-1/2*pi)+self.vy
        if self.thrust == 1:
            self.setImage(self.thrustframe)
            self.thrustframe += 1
            if self.thrustframe == 4:
                self.thrustframe = 1
        else:
            self.setImage(0)

    def thrustOn(self, event):
        self.thrust = 1

    def thrustOff(self, event):
        self.thrust = 0

    def stopr(self, event):
        self.vr=0

    def clockwise(self, event):
        self.vr=.05

    def cntrclockwise(self, event):
        self.vr=-.05

    def explode(self, x, y):

        if (x<550 and x>450):
            if (y<350 and y>250):
                print("1")
                SpaceGame.explode(x, y)
                self.vr=.5
                self.vx=20
                self.vy=0

                return(True)
    """def shoot(self, event):
        shot(self.x, self.y, self.vx, self.vy)
    """

class SpaceGame(App):

    #Tutorial4 space game example.

    def __init__(self, width, height):
        super().__init__(width, height)
        black = Color(0, 1)
        noline = LineStyle(0, black)
        bg_asset = ImageAsset("images/starfield.jpg")

        bg1 = Sprite(bg_asset, (0,0))
        bg2 = Sprite(bg_asset, (512,0))
        bg3 = Sprite(bg_asset, (0,512))
        bg4 = Sprite(bg_asset, (512,512))
        bg5 = Sprite(bg_asset, (1024,0))
        bg6 = Sprite(bg_asset, (1024,1024))
        bg7 = Sprite(bg_asset, (1536,1024))
        bg8 = Sprite(bg_asset, (512,512))
        sun((500,300))
        SpaceShip((100,100))

    def explode(xx, yy):
        expl =  ImageAsset("images/explosion1.png")
        ex = Sprite(expl, (xx-100, yy-60))
    """
    def shot(xx, yy, vx, vy):
        sht= ImageAsser("images/blast.png")
        st= Sprite(expl, (xx,yy))
        """

    def step(self):
        for ship in self.getSpritesbyClass(SpaceShip):
            ship.step()

myapp = SpaceGame(SCREEN_WIDTH, SCREEN_HEIGHT)
myapp.run()<commit_msg>Updated from Brython Server: 3/30/2016 1:35:28 PM<commit_after>"""
spaceshooter.py
Author: Ethan Adner
Credit:
ta presence, n'importe ou, me console. Au cas que ton ceour bat, je suis content
mon amour pour toi est eternel et vivante
sans vous, mes
Assignment:
Write and submit a program that implements the spacewar game:
https://github.com/HHS-IntroProgramming/Spacewar

tutorial4.py
by E. Dennison
"""

from ggame import App, RectangleAsset, ImageAsset, Sprite, LineStyle, Color, Frame
from math import sin, cos, pi

SCREEN_WIDTH = 1024
SCREEN_HEIGHT = 700
"""
xli=[]
for x in range(-25,25):
    xli.append(x+500)
yli=[]
for x in range(-25, 25):
    yli.append(x+300)
"""

class sun(Sprite):

    asset1 = ImageAsset("images/sun.png")
    height = 50
    width = 50

    def __init__(self, position):
        super().__init__(sun.asset1, position)

class SpaceShip(Sprite):

#    Animated space ship

    asset = ImageAsset("images/four_spaceship_by_albertov_with_thrust.png",
    Frame(227,0,292-227,125), 4, 'vertical')

    def __init__(self, position):
        super().__init__(SpaceShip.asset, position)
        self.vx = 0
        self.vy = 0
        self.vr = .0
        self.thrust = 0
        self.thrustframe = 1

        SpaceGame.listenKeyEvent("keydown", "q", self.clockwise)
        SpaceGame.listenKeyEvent("keyup", "q", self.stopr)
        SpaceGame.listenKeyEvent("keydown", "e", self.cntrclockwise)
        SpaceGame.listenKeyEvent("keyup", "e", self.stopr)
        SpaceGame.listenKeyEvent("keydown", "space", self.thrustOn)
        SpaceGame.listenKeyEvent("keyup", "space", self.thrustOff)
        #SpaceGame.listenKeyEvent("keyup", "s", self.shoot)

        self.fxcenter = self.fycenter = 0.5

    def step(self):
        self.x += self.vx
        self.y += self.vy
        self.rotation += self.vr
        self.explode(self.x, self.y)
        if self.explode(self.x, self.y) == True:
            return()
        if self.thrust==1:
            self.vx=.1*cos(self.rotation+1/2*pi)+self.vx
            self.vy=.1*sin(self.rotation-1/2*pi)+self.vy
        if self.thrust == 1:
            self.setImage(self.thrustframe)
            self.thrustframe += 1
            if self.thrustframe == 4:
                self.thrustframe = 1
        else:
            self.setImage(0)

    def thrustOn(self, event):
        self.thrust = 1

    def thrustOff(self, event):
        self.thrust = 0

    def stopr(self, event):
        self.vr=0

    def clockwise(self, event):
        self.vr=.05

    def cntrclockwise(self, event):
        self.vr=-.05

    def explode(self, x, y):

        if (x<550 and x>450):
            if (y<350 and y>250):
                print("1")

                self.vr=.5
                self.vx=20
                self.vy=0
                SpaceGame.explode(x, y)
                return(True)
    """def shoot(self, event):
        shot(self.x, self.y, self.vx, self.vy)
    """

class SpaceGame(App):

    #Tutorial4 space game example.

    def __init__(self, width, height):
        super().__init__(width, height)
        black = Color(0, 1)
        noline = LineStyle(0, black)
        bg_asset = ImageAsset("images/starfield.jpg")

        bg1 = Sprite(bg_asset, (0,0))
        bg2 = Sprite(bg_asset, (512,0))
        bg3 = Sprite(bg_asset, (0,512))
        bg4 = Sprite(bg_asset, (512,512))
        bg5 = Sprite(bg_asset, (1024,0))
        bg6 = Sprite(bg_asset, (1024,1024))
        bg7 = Sprite(bg_asset, (1536,1024))
        bg8 = Sprite(bg_asset, (512,512))
        sun((500,300))
        SpaceShip((100,100))

    def explode(xx, yy):
        expl =  ImageAsset("images/explosion1.png")
        ex = Sprite(expl, (xx-100, yy-60))
    """
    def shot(xx, yy, vx, vy):
        sht= ImageAsser("images/blast.png")
        st= Sprite(expl, (xx,yy))
        """

    def step(self):
        for ship in self.getSpritesbyClass(SpaceShip):
            ship.step()

myapp = SpaceGame(SCREEN_WIDTH, SCREEN_HEIGHT)
myapp.run()<|endoftext|>


<commit_before>#!/usr/bin/env python
import argparse
import logging, os, sys, random, datetime, time, collections
import requests
from sqlalchemy.sql import text

from totalimpact import tiredis
from totalimpact import app, db
from totalimpact import item as item_module

logger = logging.getLogger('ti.updater')
logger.setLevel(logging.DEBUG)

# run in heroku by a) commiting, b) pushing to heroku, and c) running
# heroku run python totalimpact/updater.py

def update_by_tiids(all_tiids, myredis):
    for tiid in all_tiids:
        item_obj = item_module.Item.query.get(tiid)  # can use this method because don't need metrics
        item_doc = item_obj.as_old_doc()
        item_module.start_item_update([{"tiid": item_doc["_id"], "aliases_dict":item_doc["aliases"]}], {}, "low", myredis)
    return all_tiids

def set_last_update_run(all_tiids):
    now = datetime.datetime.utcnow().isoformat()
    for tiid in all_tiids:
        item_obj = item_module.Item.query.get(tiid)  # can use this method because don't need metrics
        try:
            item_obj.last_update_run = now
            db.session.add(item_obj)
        except AttributeError:
            logger.warning(u"no object found for tiid {tiid} when updating last_update_run".format(
                tiid=tiid))

    db.session.commit()
    return all_tiids

# create table registered_tiid as (select tiid, api_key
# from alias, registered_item
# where alias.nid=registered_item.nid and alias.namespace=registered_item.namespace
# )

def get_registered_tiids_not_updated_since(number_to_update, now=datetime.datetime.utcnow()):

    raw_sql = text("""SELECT tiid FROM item i
        WHERE last_update_run < now()::date - 7
        and tiid in
        (select tiid
        from registered_tiid where api_key not in ('vanwijikc233acaa'))
        ORDER BY last_update_run DESC
        LIMIT :number_to_update""")

    result = db.session.execute(raw_sql, params={
        "number_to_update": number_to_update
        })
    tiids = [row["tiid"] for row in result]

    return tiids

def get_nids_for_altmetric_com_to_update(number_to_update):

    raw_sql = text("""SELECT i.tiid, namespace, nid, last_update_run
        FROM item i, alias a, user_tiids_valid_users u
        WHERE last_update_run < now()::date - 1
        AND i.tiid = a.tiid
        AND i.tiid = u.tiid
        AND namespace in ('doi', 'arxiv', 'pmid')
        ORDER BY last_update_run ASC
        LIMIT :number_to_update""")

    result = db.session.execute(raw_sql, params={
        "number_to_update": number_to_update
        })
    #tiids = [row["tiid"] for row in result]

    return result.fetchall()

def get_altmetric_ids_from_nids(nids):
    nid_string = u"|".join(nids)
    #print "nid_string", nid_string

    headers = {u'content-type': u'application/x-www-form-urlencoded',
                u'accept': u'application/json'}
    try:
        r = requests.post(u"http://api.altmetric.com/v1/translate?key=" + os.getenv("ALTMETRIC_COM_KEY"),
                            data=u"ids="+nid_string,
                            headers=headers)
        altmetric_ids_dict = r.json()
    except UnicodeEncodeError:
        print "UnicodeEncodeError"
        altmetric_ids_dict = []

    nids_by_altmetric_id = dict((str(altmetric_ids_dict[nid]), nid) for nid in altmetric_ids_dict)
    return nids_by_altmetric_id

def altmetric_com_ids_to_update(altmetric_ids):
    altmetric_ids_string = u",".join(altmetric_ids)
    #print "altmetric_ids_string", altmetric_ids_string

    headers = {u'content-type': u'application/x-www-form-urlencoded',
                u'accept': u'application/json'}

    r = requests.post(u"http://api.altmetric.com/v1/citations/1y?key=" + os.getenv("ALTMETRIC_COM_KEY"),
                        data=u"citation_ids="+altmetric_ids_string,
                        headers=headers)
    try:
        data = r.json()
        ids_with_changes = [str(entry["altmetric_id"]) for entry in data["results"]]
    except ValueError:
        # says "Not Found" not in JSON if nothing found
        ids_with_changes = []
    return ids_with_changes

def tiids_from_altmetric_ids(altmetric_ids, nids_by_altmetric_id, tiids_by_nids):
    #print "altmetric_ids", altmetric_ids
    nids = [nids_by_altmetric_id[id] for id in altmetric_ids]
    tiids_nested = [tiids_by_nids[nid] for nid in nids]
    #print "tiids_nested", tiids_nested
    tiids = [tiid for inner_list in tiids_nested for tiid in inner_list]
    #print "tiids", tiids
    return tiids

def altmetric_com_update(number_to_update, myredis):
    candidate_tiid_rows = get_nids_for_altmetric_com_to_update(number_to_update)
    tiids_by_nids = collections.defaultdict(list)
    for row in candidate_tiid_rows:
        tiids_by_nids[row["nid"]] += [row["tiid"]]
    print "tiids_by_nids", tiids_by_nids
    all_tiids = [row["tiid"] for row in candidate_tiid_rows]
    #print "all_tiids", all_tiids

    nids = tiids_by_nids.keys()
    if not nids:
        logger.info("no items to update")
        return []
    #print "nids", nids
    nids_by_altmetric_id = get_altmetric_ids_from_nids(nids)
    print "nids_by_altmetric_id", nids_by_altmetric_id

    altmetric_ids = nids_by_altmetric_id.keys()
    #print "altmetric_ids", altmetric_ids

    if altmetric_ids:
        tiids_with_altmetric_ids = tiids_from_altmetric_ids(altmetric_ids, nids_by_altmetric_id, tiids_by_nids)
        updated_tiids = update_by_tiids(tiids_with_altmetric_ids, myredis)

        # altmetric_ids_with_changes = altmetric_com_ids_to_update(altmetric_ids, nids_by_altmetric_id, tiids_by_nids)
        # tiids_with_changes = tiids_from_altmetric_ids(altmetric_ids_with_changes)
        # updated_tiids = update_by_tiids(tiids_with_changes, myredis)

    if all_tiids:
        set_last_update_run(all_tiids)
    return({"len_candidate_tiid_rows":len(candidate_tiid_rows), "len_altmetric_ids":len(altmetric_ids)})

def gold_update(number_to_update, myredis, now=datetime.datetime.utcnow()):
    tiids = get_registered_tiids_not_updated_since(number_to_update, now)
    updated_tiids = update_by_tiids(tiids, myredis)
    return updated_tiids

def main(action_type, number_to_update=35, number_loops=400, seconds_wait=10):
    #35 every 10 minutes is 35*6perhour*24hours=5040 per day

    redis_url = os.getenv("REDIS_URL")

    myredis = tiredis.from_url(redis_url)
    print u"running " + action_type

    try:
        if action_type == "gold_update":
            tiids = gold_update(number_to_update, myredis)
        elif action_type == "altmetric_com":
            for i in range(0, number_loops):
                print "another loop of altmetric_com_update", i
                resp = altmetric_com_update(number_to_update, myredis)
                print "updating", resp["len_altmetric_ids"]
                print "sleeping to pause, for", seconds_wait * resp["len_altmetric_ids"], "seconds"
                time.sleep(seconds_wait * resp["len_altmetric_ids"])
                if not resp["len_candidate_tiid_rows"]:
                    raise SystemExit
    except (KeyboardInterrupt, SystemExit):
        # this approach is per http://stackoverflow.com/questions/2564137/python-how-to-terminate-a-thread-when-main-program-ends
        sys.exit()

if __name__ == "__main__":

    # get args from the command line:
    parser = argparse.ArgumentParser(description="Run periodic metrics updating from the command line")
    parser.add_argument("action_type", type=str, help="The action to test; available actions are 'gold_update' (that's all right now)")
    parser.add_argument('--number_to_update', default='35', type=int, help="Number to update.")
    parser.add_argument('--number_loops', default='1', type=int, help="Number loops.")
    parser.add_argument('--seconds_wait', default='10', type=int, help="Number seconds wait per altmetrics_id.")
    args = vars(parser.parse_args())
    print args
    print "updater.py starting."
    main(args["action_type"], args["number_to_update"], number_loops=args["number_loops"], seconds_wait=args["seconds_wait"])

<commit_msg>update date threshold<commit_after>#!/usr/bin/env python
import argparse
import logging, os, sys, random, datetime, time, collections
import requests
from sqlalchemy.sql import text

from totalimpact import tiredis
from totalimpact import app, db
from totalimpact import item as item_module

logger = logging.getLogger('ti.updater')
logger.setLevel(logging.DEBUG)

# run in heroku by a) commiting, b) pushing to heroku, and c) running
# heroku run python totalimpact/updater.py

def update_by_tiids(all_tiids, myredis):
    for tiid in all_tiids:
        item_obj = item_module.Item.query.get(tiid)  # can use this method because don't need metrics
        item_doc = item_obj.as_old_doc()
        item_module.start_item_update([{"tiid": item_doc["_id"], "aliases_dict":item_doc["aliases"]}], {}, "low", myredis)
    return all_tiids

def set_last_update_run(all_tiids):
    now = datetime.datetime.utcnow().isoformat()
    for tiid in all_tiids:
        item_obj = item_module.Item.query.get(tiid)  # can use this method because don't need metrics
        try:
            item_obj.last_update_run = now
            db.session.add(item_obj)
        except AttributeError:
            logger.warning(u"no object found for tiid {tiid} when updating last_update_run".format(
                tiid=tiid))

    db.session.commit()
    return all_tiids

# create table registered_tiid as (select tiid, api_key
# from alias, registered_item
# where alias.nid=registered_item.nid and alias.namespace=registered_item.namespace
# )

def get_registered_tiids_not_updated_since(number_to_update, now=datetime.datetime.utcnow()):

    raw_sql = text("""SELECT tiid FROM item i
        WHERE last_update_run < now()::date - 7
        and tiid in
        (select tiid
        from registered_tiid where api_key not in ('vanwijikc233acaa'))
        ORDER BY last_update_run DESC
        LIMIT :number_to_update""")

    result = db.session.execute(raw_sql, params={
        "number_to_update": number_to_update
        })
    tiids = [row["tiid"] for row in result]

    return tiids

def get_nids_for_altmetric_com_to_update(number_to_update):

    raw_sql = text("""SELECT i.tiid, namespace, nid, last_update_run
        FROM item i, alias a, user_tiids_valid_users u
        WHERE last_update_run < now()::date - 2
        AND i.tiid = a.tiid
        AND i.tiid = u.tiid
        AND namespace in ('doi', 'arxiv', 'pmid')
        ORDER BY last_update_run ASC
        LIMIT :number_to_update""")

    result = db.session.execute(raw_sql, params={
        "number_to_update": number_to_update
        })
    #tiids = [row["tiid"] for row in result]

    return result.fetchall()

def get_altmetric_ids_from_nids(nids):
    nid_string = u"|".join(nids)
    #print "nid_string", nid_string

    headers = {u'content-type': u'application/x-www-form-urlencoded',
                u'accept': u'application/json'}
    try:
        r = requests.post(u"http://api.altmetric.com/v1/translate?key=" + os.getenv("ALTMETRIC_COM_KEY"),
                            data=u"ids="+nid_string,
                            headers=headers)
        altmetric_ids_dict = r.json()
    except UnicodeEncodeError:
        print "UnicodeEncodeError"
        altmetric_ids_dict = []

    nids_by_altmetric_id = dict((str(altmetric_ids_dict[nid]), nid) for nid in altmetric_ids_dict)
    return nids_by_altmetric_id

def altmetric_com_ids_to_update(altmetric_ids):
    altmetric_ids_string = u",".join(altmetric_ids)
    #print "altmetric_ids_string", altmetric_ids_string

    headers = {u'content-type': u'application/x-www-form-urlencoded',
                u'accept': u'application/json'}

    r = requests.post(u"http://api.altmetric.com/v1/citations/1y?key=" + os.getenv("ALTMETRIC_COM_KEY"),
                        data=u"citation_ids="+altmetric_ids_string,
                        headers=headers)
    try:
        data = r.json()
        ids_with_changes = [str(entry["altmetric_id"]) for entry in data["results"]]
    except ValueError:
        # says "Not Found" not in JSON if nothing found
        ids_with_changes = []
    return ids_with_changes

def tiids_from_altmetric_ids(altmetric_ids, nids_by_altmetric_id, tiids_by_nids):
    #print "altmetric_ids", altmetric_ids
    nids = [nids_by_altmetric_id[id] for id in altmetric_ids]
    tiids_nested = [tiids_by_nids[nid] for nid in nids]
    #print "tiids_nested", tiids_nested
    tiids = [tiid for inner_list in tiids_nested for tiid in inner_list]
    #print "tiids", tiids
    return tiids

def altmetric_com_update(number_to_update, myredis):
    candidate_tiid_rows = get_nids_for_altmetric_com_to_update(number_to_update)
    tiids_by_nids = collections.defaultdict(list)
    for row in candidate_tiid_rows:
        tiids_by_nids[row["nid"]] += [row["tiid"]]
    print "tiids_by_nids", tiids_by_nids
    all_tiids = [row["tiid"] for row in candidate_tiid_rows]
    #print "all_tiids", all_tiids

    nids = tiids_by_nids.keys()
    if not nids:
        logger.info("no items to update")
        return []
    #print "nids", nids
    nids_by_altmetric_id = get_altmetric_ids_from_nids(nids)
    print "nids_by_altmetric_id", nids_by_altmetric_id

    altmetric_ids = nids_by_altmetric_id.keys()
    #print "altmetric_ids", altmetric_ids

    if altmetric_ids:
        tiids_with_altmetric_ids = tiids_from_altmetric_ids(altmetric_ids, nids_by_altmetric_id, tiids_by_nids)
        updated_tiids = update_by_tiids(tiids_with_altmetric_ids, myredis)

        # altmetric_ids_with_changes = altmetric_com_ids_to_update(altmetric_ids, nids_by_altmetric_id, tiids_by_nids)
        # tiids_with_changes = tiids_from_altmetric_ids(altmetric_ids_with_changes)
        # updated_tiids = update_by_tiids(tiids_with_changes, myredis)

    if all_tiids:
        set_last_update_run(all_tiids)
    return({"len_candidate_tiid_rows":len(candidate_tiid_rows), "len_altmetric_ids":len(altmetric_ids)})

def gold_update(number_to_update, myredis, now=datetime.datetime.utcnow()):
    tiids = get_registered_tiids_not_updated_since(number_to_update, now)
    updated_tiids = update_by_tiids(tiids, myredis)
    return updated_tiids

def main(action_type, number_to_update=35, number_loops=400, seconds_wait=10):
    #35 every 10 minutes is 35*6perhour*24hours=5040 per day

    redis_url = os.getenv("REDIS_URL")

    myredis = tiredis.from_url(redis_url)
    print u"running " + action_type

    try:
        if action_type == "gold_update":
            tiids = gold_update(number_to_update, myredis)
        elif action_type == "altmetric_com":
            for i in range(0, number_loops):
                print "another loop of altmetric_com_update", i
                resp = altmetric_com_update(number_to_update, myredis)
                print "updating", resp["len_altmetric_ids"]
                print "sleeping to pause, for", seconds_wait * resp["len_altmetric_ids"], "seconds"
                time.sleep(seconds_wait * resp["len_altmetric_ids"])
                if not resp["len_candidate_tiid_rows"]:
                    raise SystemExit
    except (KeyboardInterrupt, SystemExit):
        # this approach is per http://stackoverflow.com/questions/2564137/python-how-to-terminate-a-thread-when-main-program-ends
        sys.exit()

if __name__ == "__main__":

    # get args from the command line:
    parser = argparse.ArgumentParser(description="Run periodic metrics updating from the command line")
    parser.add_argument("action_type", type=str, help="The action to test; available actions are 'gold_update' (that's all right now)")
    parser.add_argument('--number_to_update', default='35', type=int, help="Number to update.")
    parser.add_argument('--number_loops', default='1', type=int, help="Number loops.")
    parser.add_argument('--seconds_wait', default='10', type=int, help="Number seconds wait per altmetrics_id.")
    args = vars(parser.parse_args())
    print args
    print "updater.py starting."
    main(args["action_type"], args["number_to_update"], number_loops=args["number_loops"], seconds_wait=args["seconds_wait"])

<|endoftext|>


<commit_before>from . import opcodes
from .parser import parse

try:
    input = raw_input
except NameError:
    pass

class Machine(object):
    """A Chicken VM.

    Attributes:
    - ip - instruction pointer
    - sp - stack pointer
    - stack
    """

    ip = None  # type: int
    sp = -1

    def __init__(self, input_=None, code=None, bbq_compat=False):
        self.stack = []
        self.push(self.stack)
        self.push(input_)

        if code:
            self.load_str(code)

        self.bbq_compat = bbq_compat

    def __iter__(self):
        return self

    def __next__(self):
        x = self.step()
        if x is None:
            raise StopIteration
        return x

    next = __next__

    def exec_op(self, opcode):
        """Execute an opcode."""

        if opcode == opcodes.CHICKEN:
            self.push('chicken')

        elif opcode == opcodes.ADD:
            a, b = self.pop(), self.pop()

            # JavaScript's + operator coerces to string if either operand is string
            if isinstance(a, str):
                b = str(b)
            elif isinstance(b, str):
                a = str(a)

            self.push(b + a)

        elif opcode == opcodes.FOX:
            a, b = self.pop(), self.pop()

            # JavaScript's - operator coerces both operands to numbers
            if isinstance(b, str):
                b = int(b)
            if isinstance(a, str):
                a = int(a)

            self.push(b - a)

        elif opcode == opcodes.ROOSTER:
            a, b = self.pop(), self.pop()
            self.push(a * b)
        elif opcode == opcodes.COMPARE:
            a, b = self.pop(), self.pop()
            self.push(a == b)

        elif opcode == opcodes.PICK:
            where = self.next_op()
            if where == 1:
                source = self.get_input()
            else:
                source = self.stack[where]
            addr = self.pop()

            #self.push(source[addr])
            try:
                if source is self.stack and addr == 1:
                    self.push(self.get_input())
                else:
                    self.push(source[addr])
            except (IndexError, TypeError):
                self.push(None)

        elif opcode == opcodes.PECK:
            addr = self.pop()
            self.set(addr, self.pop())

        elif opcode == opcodes.FR:
            offset = self.pop()
            if self.pop():
                self.ip += offset

        elif opcode == opcodes.BBQ:
            v = self.pop()
            if self.bbq_compat:
                self.push('&#{};'.format(v))
            else:
                self.push(chr(v))

        else:
            self.push(opcode - 10)

    def get_input(self):
        """Get input, either previously loaded or from stdin."""

        if self.stack[1] is None:
            self.stack[1] = input()
        return self.stack[1]

    def has_loaded(self):
        """Check whether a Chicken program has been loaded."""
        return self.ip is not None

    def is_end(self):
        """Check whether we have finished executing."""
        return self.ip >= len(self.stack) or not self.peek()

    def load_file(self, filename):
        """Load a Chicken program from a file."""

        with open(filename) as f:
            self.load_str(f.read())

    def load_input(self, inp):
        """Load input from a string."""
        self.stack[1] = inp

    def load_str(self, code):
        """Load a Chicken program from a string."""

        bytecode = parse(code)
        self.stack += bytecode
        self.sp = len(self.stack)
        if self.ip is None:
            self.ip = 2

    def look(self):
        """Get the top value on the stack."""
        return self.stack[self.sp]

    def next_op(self):
        """Get the next instruction, advancing the instruction pointer."""

        opcode = self.peek()
        self.ip += 1
        return opcode

    def peek(self):
        """Get the next instruction."""
        return self.stack[self.ip]

    def push(self, val):
        """Push a value onto the stack."""

        self.sp += 1
        self.set(self.sp, val)

    def pop(self):
        """Pop a value off the stack."""

        val = self.stack[self.sp]
        self.sp -= 1
        return val

    def run(self):
        """Execute the loaded Chicken program."""

        while self.step():
            pass

        out = self.look()
        if self.bbq_compat and '&#' in out:
            import re
            out = re.sub(r'&#(\d+);', lambda m: chr(int(m.group(1))), out)

        return out

    def set(self, addr, value):
        l = len(self.stack)
        if addr == l:
            self.stack.append(value)
        elif addr > l:
            self.stack += [None] * (addr - l + 1)
            self.stack[addr] = value
        else:
            self.stack[addr] = value

    def step(self):
        """Execute the next instruction.

        Returns the advanced IP and the last executed opcode.
        """

        if not self.has_loaded():
            raise RuntimeError('No Chicken program has been loaded.')

        if self.is_end():
            return None

        opcode = self.next_op()
        self.exec_op(opcode)
        return self.ip, opcode
<commit_msg>vm: Move output decode logic from run to new func<commit_after>from . import opcodes
from .parser import parse

try:
    input = raw_input
except NameError:
    pass

class Machine(object):
    """A Chicken VM.

    Attributes:
    - ip - instruction pointer
    - sp - stack pointer
    - stack
    """

    ip = None  # type: int
    sp = -1

    def __init__(self, input_=None, code=None, bbq_compat=False):
        self.stack = []
        self.push(self.stack)
        self.push(input_)

        if code:
            self.load_str(code)

        self.bbq_compat = bbq_compat

    def __iter__(self):
        return self

    def __next__(self):
        x = self.step()
        if x is None:
            raise StopIteration
        return x

    next = __next__

    def exec_op(self, opcode):
        """Execute an opcode."""

        if opcode == opcodes.CHICKEN:
            self.push('chicken')

        elif opcode == opcodes.ADD:
            a, b = self.pop(), self.pop()

            # JavaScript's + operator coerces to string if either operand is string
            if isinstance(a, str):
                b = str(b)
            elif isinstance(b, str):
                a = str(a)

            self.push(b + a)

        elif opcode == opcodes.FOX:
            a, b = self.pop(), self.pop()

            # JavaScript's - operator coerces both operands to numbers
            if isinstance(b, str):
                b = int(b)
            if isinstance(a, str):
                a = int(a)

            self.push(b - a)

        elif opcode == opcodes.ROOSTER:
            a, b = self.pop(), self.pop()
            self.push(a * b)
        elif opcode == opcodes.COMPARE:
            a, b = self.pop(), self.pop()
            self.push(a == b)

        elif opcode == opcodes.PICK:
            where = self.next_op()
            if where == 1:
                source = self.get_input()
            else:
                source = self.stack[where]
            addr = self.pop()

            #self.push(source[addr])
            try:
                if source is self.stack and addr == 1:
                    self.push(self.get_input())
                else:
                    self.push(source[addr])
            except (IndexError, TypeError):
                self.push(None)

        elif opcode == opcodes.PECK:
            addr = self.pop()
            self.set(addr, self.pop())

        elif opcode == opcodes.FR:
            offset = self.pop()
            if self.pop():
                self.ip += offset

        elif opcode == opcodes.BBQ:
            v = self.pop()
            if self.bbq_compat:
                self.push('&#{};'.format(v))
            else:
                self.push(chr(v))

        else:
            self.push(opcode - 10)

    def get_input(self):
        """Get input, either previously loaded or from stdin."""

        if self.stack[1] is None:
            self.stack[1] = input()
        return self.stack[1]

    def get_output(self):
        """Get the program's output, if the program has finished."""

        out = self.look()
        if self.bbq_compat and '&#' in out:
            import re
            out = re.sub(r'&#(\d+);', lambda m: chr(int(m.group(1))), out)

        return out

    def has_loaded(self):
        """Check whether a Chicken program has been loaded."""
        return self.ip is not None

    def is_end(self):
        """Check whether we have finished executing."""
        return self.ip >= len(self.stack) or not self.peek()

    def load_file(self, filename):
        """Load a Chicken program from a file."""

        with open(filename) as f:
            self.load_str(f.read())

    def load_input(self, inp):
        """Load input from a string."""
        self.stack[1] = inp

    def load_str(self, code):
        """Load a Chicken program from a string."""

        bytecode = parse(code)
        self.stack += bytecode
        self.sp = len(self.stack)
        if self.ip is None:
            self.ip = 2

    def look(self):
        """Get the top value on the stack."""
        return self.stack[self.sp]

    def next_op(self):
        """Get the next instruction, advancing the instruction pointer."""

        opcode = self.peek()
        self.ip += 1
        return opcode

    def peek(self):
        """Get the next instruction."""
        return self.stack[self.ip]

    def push(self, val):
        """Push a value onto the stack."""

        self.sp += 1
        self.set(self.sp, val)

    def pop(self):
        """Pop a value off the stack."""

        val = self.stack[self.sp]
        self.sp -= 1
        return val

    def run(self):
        """Execute the loaded Chicken program."""

        while self.step():
            pass

        return self.get_output()

    def set(self, addr, value):
        l = len(self.stack)
        if addr == l:
            self.stack.append(value)
        elif addr > l:
            self.stack += [None] * (addr - l + 1)
            self.stack[addr] = value
        else:
            self.stack[addr] = value

    def step(self):
        """Execute the next instruction.

        Returns the advanced IP and the last executed opcode.
        """

        if not self.has_loaded():
            raise RuntimeError('No Chicken program has been loaded.')

        if self.is_end():
            return None

        opcode = self.next_op()
        self.exec_op(opcode)
        return self.ip, opcode
<|endoftext|>