<commit_before># -*- Mode: Python; tab-width: 4 -*-
#       Id: asynchat.py,v 2.25 1999/11/18 11:01:08 rushing Exp
#       Author: Sam Rushing <rushing@nightmare.com>

# ======================================================================
# Copyright 1996 by Sam Rushing
#
#                         All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of Sam
# Rushing not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
#
# SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
# NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# ======================================================================

"""A class supporting chat-style (command/response) protocols.

This class adds support for 'chat' style protocols - where one side
sends a 'command', and the other sends a response (examples would be
the common internet protocols - smtp, nntp, ftp, etc..).

The handle_read() method looks at the input stream for the current
'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n'
for multi-line output), calling self.found_terminator() on its
receipt.

for example:
Say you build an async nntp client using this class.  At the start
of the connection, you'll have self.terminator set to '\r\n', in
order to process the single-line greeting.  Just before issuing a
'LIST' command you'll set it to '\r\n.\r\n'.  The output of the LIST
command will be accumulated (using your own 'collect_incoming_data'
method) up to the terminator, and then control will be returned to
you - by calling your self.found_terminator() method.
"""

import socket
import asyncore
import string

class async_chat (asyncore.dispatcher):
    """This is an abstract class.  You must derive from this class, and add
    the two methods collect_incoming_data() and found_terminator()"""

    # these are overridable defaults

    ac_in_buffer_size       = 4096
    ac_out_buffer_size      = 4096

    def __init__ (self, conn=None):
        self.ac_in_buffer = ''
        self.ac_out_buffer = ''
        self.producer_fifo = fifo()
        asyncore.dispatcher.__init__ (self, conn)

    def set_terminator (self, term):
        "Set the input delimiter.  Can be a fixed string of any length, an integer, or None"
        self.terminator = term

    def get_terminator (self):
        return self.terminator

    # grab some more data from the socket,
    # throw it to the collector method,
    # check for the terminator,
    # if found, transition to the next state.

    def handle_read (self):

        try:
            data = self.recv (self.ac_in_buffer_size)
        except socket.error, why:
            self.handle_error()
            return

        self.ac_in_buffer = self.ac_in_buffer + data

        # Continue to search for self.terminator in self.ac_in_buffer,
        # while calling self.collect_incoming_data.  The while loop
        # is necessary because we might read several data+terminator
        # combos with a single recv(1024).

        while self.ac_in_buffer:
            lb = len(self.ac_in_buffer)
            terminator = self.get_terminator()
            if terminator is None:
                # no terminator, collect it all
                self.collect_incoming_data (self.ac_in_buffer)
                self.ac_in_buffer = ''
            elif type(terminator) == type(0):
                # numeric terminator
                n = terminator
                if lb < n:
                    self.collect_incoming_data (self.ac_in_buffer)
                    self.ac_in_buffer = ''
                    self.terminator = self.terminator - lb
                else:
                    self.collect_incoming_data (self.ac_in_buffer[:n])
                    self.ac_in_buffer = self.ac_in_buffer[n:]
                    self.terminator = 0
                    self.found_terminator()
            else:
                # 3 cases:
                # 1) end of buffer matches terminator exactly:
                #    collect data, transition
                # 2) end of buffer matches some prefix:
                #    collect data to the prefix
                # 3) end of buffer does not match any prefix:
                #    collect data
                terminator_len = len(terminator)
                index = string.find (self.ac_in_buffer, terminator)
                if index != -1:
                    # we found the terminator
                    if index > 0:
                        # don't bother reporting the empty string (source of subtle bugs)
                        self.collect_incoming_data (self.ac_in_buffer[:index])
                    self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:]
                    # This does the Right Thing if the terminator is changed here.
                    self.found_terminator()
                else:
                    # check for a prefix of the terminator
                    index = find_prefix_at_end (self.ac_in_buffer, terminator)
                    if index:
                        if index != lb:
                            # we found a prefix, collect up to the prefix
                            self.collect_incoming_data (self.ac_in_buffer[:-index])
                            self.ac_in_buffer = self.ac_in_buffer[-index:]
                        break
                    else:
                        # no prefix, collect it all
                        self.collect_incoming_data (self.ac_in_buffer)
                        self.ac_in_buffer = ''

    def handle_write (self):
        self.initiate_send ()

    def handle_close (self):
        self.close()

    def push (self, data):
        self.producer_fifo.push (simple_producer (data))
        self.initiate_send()

    def push_with_producer (self, producer):
        self.producer_fifo.push (producer)
        self.initiate_send()

    def readable (self):
        "predicate for inclusion in the readable for select()"
        return (len(self.ac_in_buffer) <= self.ac_in_buffer_size)

    def writable (self):
        "predicate for inclusion in the writable for select()"
        # return len(self.ac_out_buffer) or len(self.producer_fifo) or (not self.connected)
        # this is about twice as fast, though not as clear.
        return not (
                (self.ac_out_buffer is '') and
                self.producer_fifo.is_empty() and
                self.connected
                )

    def close_when_done (self):
        "automatically close this channel once the outgoing queue is empty"
        self.producer_fifo.push (None)

    # refill the outgoing buffer by calling the more() method
    # of the first producer in the queue
    def refill_buffer (self):
        _string_type = type('')
        while 1:
            if len(self.producer_fifo):
                p = self.producer_fifo.first()
                # a 'None' in the producer fifo is a sentinel,
                # telling us to close the channel.
                if p is None:
                    if not self.ac_out_buffer:
                        self.producer_fifo.pop()
                        self.close()
                    return
                elif type(p) is _string_type:
                    self.producer_fifo.pop()
                    self.ac_out_buffer = self.ac_out_buffer + p
                    return
                data = p.more()
                if data:
                    self.ac_out_buffer = self.ac_out_buffer + data
                    return
                else:
                    self.producer_fifo.pop()
            else:
                return

    def initiate_send (self):
        obs = self.ac_out_buffer_size
        # try to refill the buffer
        if (len (self.ac_out_buffer) < obs):
            self.refill_buffer()

        if self.ac_out_buffer and self.connected:
            # try to send the buffer
            try:
                num_sent = self.send (self.ac_out_buffer[:obs])
                if num_sent:
                    self.ac_out_buffer = self.ac_out_buffer[num_sent:]

            except socket.error, why:
                self.handle_error()
                return

    def discard_buffers (self):
        # Emergencies only!
        self.ac_in_buffer = ''
        self.ac_out_buffer = ''
        while self.producer_fifo:
            self.producer_fifo.pop()

class simple_producer:

    def __init__ (self, data, buffer_size=512):
        self.data = data
        self.buffer_size = buffer_size

    def more (self):
        if len (self.data) > self.buffer_size:
            result = self.data[:self.buffer_size]
            self.data = self.data[self.buffer_size:]
            return result
        else:
            result = self.data
            self.data = ''
            return result

class fifo:
    def __init__ (self, list=None):
        if not list:
            self.list = []
        else:
            self.list = list

    def __len__ (self):
        return len(self.list)

    def is_empty (self):
        return self.list == []

    def first (self):
        return self.list[0]

    def push (self, data):
        self.list.append (data)

    def pop (self):
        if self.list:
            result = self.list[0]
            del self.list[0]
            return (1, result)
        else:
            return (0, None)

# Given 'haystack', see if any prefix of 'needle' is at its end.  This
# assumes an exact match has already been checked.  Return the number of
# characters matched.
# for example:
# f_p_a_e ("qwerty\r", "\r\n") => 1
# f_p_a_e ("qwerty\r\n", "\r\n") => 2
# f_p_a_e ("qwertydkjf", "\r\n") => 0

# this could maybe be made faster with a computed regex?

##def find_prefix_at_end (haystack, needle):
##      nl = len(needle)
##      result = 0
##      for i in range (1,nl):
##              if haystack[-(nl-i):] == needle[:(nl-i)]:
##                      result = nl-i
##                      break
##      return result

# yes, this is about twice as fast, but still seems
# to be negligible CPU.  The previous version could do about 290
# searches/sec. the new one about 555/sec.

import regex

prefix_cache = {}

def prefix_regex (needle):
    if prefix_cache.has_key (needle):
        return prefix_cache[needle]
    else:
        reg = needle[-1]
        for i in range(1,len(needle)):
            reg = '%c\(%s\)?' % (needle[-(i+1)], reg)
        reg = regex.compile (reg+'$')
        prefix_cache[needle] = reg, len(needle)
        return reg, len(needle)

def find_prefix_at_end (haystack, needle):
    reg, length = prefix_regex (needle)
    lh = len(haystack)
    result = reg.search (haystack, max(0,lh-length))
    if result >= 0:
        return (lh - result)
    else:
        return 0
<commit_msg>New asynchat.py from Sam Rushing:  this foregoes using the regex module    to find the prefix of strings, thus removing a warning, and simply    uses straightforward string slicing.<commit_after># -*- Mode: Python; tab-width: 4 -*-
#       Id: asynchat.py,v 2.26 2000/09/07 22:29:26 rushing Exp
#       Author: Sam Rushing <rushing@nightmare.com>

# ======================================================================
# Copyright 1996 by Sam Rushing
#
#                         All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of Sam
# Rushing not be used in advertising or publicity pertaining to
# distribution of the software without specific, written prior
# permission.
#
# SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
# NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
# ======================================================================

"""A class supporting chat-style (command/response) protocols.

This class adds support for 'chat' style protocols - where one side
sends a 'command', and the other sends a response (examples would be
the common internet protocols - smtp, nntp, ftp, etc..).

The handle_read() method looks at the input stream for the current
'terminator' (usually '\r\n' for single-line responses, '\r\n.\r\n'
for multi-line output), calling self.found_terminator() on its
receipt.

for example:
Say you build an async nntp client using this class.  At the start
of the connection, you'll have self.terminator set to '\r\n', in
order to process the single-line greeting.  Just before issuing a
'LIST' command you'll set it to '\r\n.\r\n'.  The output of the LIST
command will be accumulated (using your own 'collect_incoming_data'
method) up to the terminator, and then control will be returned to
you - by calling your self.found_terminator() method.
"""

import socket
import asyncore
import string

class async_chat (asyncore.dispatcher):
    """This is an abstract class.  You must derive from this class, and add
    the two methods collect_incoming_data() and found_terminator()"""

    # these are overridable defaults

    ac_in_buffer_size       = 4096
    ac_out_buffer_size      = 4096

    def __init__ (self, conn=None):
        self.ac_in_buffer = ''
        self.ac_out_buffer = ''
        self.producer_fifo = fifo()
        asyncore.dispatcher.__init__ (self, conn)

    def set_terminator (self, term):
        "Set the input delimiter.  Can be a fixed string of any length, an integer, or None"
        self.terminator = term

    def get_terminator (self):
        return self.terminator

    # grab some more data from the socket,
    # throw it to the collector method,
    # check for the terminator,
    # if found, transition to the next state.

    def handle_read (self):

        try:
            data = self.recv (self.ac_in_buffer_size)
        except socket.error, why:
            self.handle_error()
            return

        self.ac_in_buffer = self.ac_in_buffer + data

        # Continue to search for self.terminator in self.ac_in_buffer,
        # while calling self.collect_incoming_data.  The while loop
        # is necessary because we might read several data+terminator
        # combos with a single recv(1024).

        while self.ac_in_buffer:
            lb = len(self.ac_in_buffer)
            terminator = self.get_terminator()
            if terminator is None:
                # no terminator, collect it all
                self.collect_incoming_data (self.ac_in_buffer)
                self.ac_in_buffer = ''
            elif type(terminator) == type(0):
                # numeric terminator
                n = terminator
                if lb < n:
                    self.collect_incoming_data (self.ac_in_buffer)
                    self.ac_in_buffer = ''
                    self.terminator = self.terminator - lb
                else:
                    self.collect_incoming_data (self.ac_in_buffer[:n])
                    self.ac_in_buffer = self.ac_in_buffer[n:]
                    self.terminator = 0
                    self.found_terminator()
            else:
                # 3 cases:
                # 1) end of buffer matches terminator exactly:
                #    collect data, transition
                # 2) end of buffer matches some prefix:
                #    collect data to the prefix
                # 3) end of buffer does not match any prefix:
                #    collect data
                terminator_len = len(terminator)
                index = string.find (self.ac_in_buffer, terminator)
                if index != -1:
                    # we found the terminator
                    if index > 0:
                        # don't bother reporting the empty string (source of subtle bugs)
                        self.collect_incoming_data (self.ac_in_buffer[:index])
                    self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:]
                    # This does the Right Thing if the terminator is changed here.
                    self.found_terminator()
                else:
                    # check for a prefix of the terminator
                    index = find_prefix_at_end (self.ac_in_buffer, terminator)
                    if index:
                        if index != lb:
                            # we found a prefix, collect up to the prefix
                            self.collect_incoming_data (self.ac_in_buffer[:-index])
                            self.ac_in_buffer = self.ac_in_buffer[-index:]
                        break
                    else:
                        # no prefix, collect it all
                        self.collect_incoming_data (self.ac_in_buffer)
                        self.ac_in_buffer = ''

    def handle_write (self):
        self.initiate_send ()

    def handle_close (self):
        self.close()

    def push (self, data):
        self.producer_fifo.push (simple_producer (data))
        self.initiate_send()

    def push_with_producer (self, producer):
        self.producer_fifo.push (producer)
        self.initiate_send()

    def readable (self):
        "predicate for inclusion in the readable for select()"
        return (len(self.ac_in_buffer) <= self.ac_in_buffer_size)

    def writable (self):
        "predicate for inclusion in the writable for select()"
        # return len(self.ac_out_buffer) or len(self.producer_fifo) or (not self.connected)
        # this is about twice as fast, though not as clear.
        return not (
                (self.ac_out_buffer is '') and
                self.producer_fifo.is_empty() and
                self.connected
                )

    def close_when_done (self):
        "automatically close this channel once the outgoing queue is empty"
        self.producer_fifo.push (None)

    # refill the outgoing buffer by calling the more() method
    # of the first producer in the queue
    def refill_buffer (self):
        _string_type = type('')
        while 1:
            if len(self.producer_fifo):
                p = self.producer_fifo.first()
                # a 'None' in the producer fifo is a sentinel,
                # telling us to close the channel.
                if p is None:
                    if not self.ac_out_buffer:
                        self.producer_fifo.pop()
                        self.close()
                    return
                elif type(p) is _string_type:
                    self.producer_fifo.pop()
                    self.ac_out_buffer = self.ac_out_buffer + p
                    return
                data = p.more()
                if data:
                    self.ac_out_buffer = self.ac_out_buffer + data
                    return
                else:
                    self.producer_fifo.pop()
            else:
                return

    def initiate_send (self):
        obs = self.ac_out_buffer_size
        # try to refill the buffer
        if (len (self.ac_out_buffer) < obs):
            self.refill_buffer()

        if self.ac_out_buffer and self.connected:
            # try to send the buffer
            try:
                num_sent = self.send (self.ac_out_buffer[:obs])
                if num_sent:
                    self.ac_out_buffer = self.ac_out_buffer[num_sent:]

            except socket.error, why:
                self.handle_error()
                return

    def discard_buffers (self):
        # Emergencies only!
        self.ac_in_buffer = ''
        self.ac_out_buffer = ''
        while self.producer_fifo:
            self.producer_fifo.pop()

class simple_producer:

    def __init__ (self, data, buffer_size=512):
        self.data = data
        self.buffer_size = buffer_size

    def more (self):
        if len (self.data) > self.buffer_size:
            result = self.data[:self.buffer_size]
            self.data = self.data[self.buffer_size:]
            return result
        else:
            result = self.data
            self.data = ''
            return result

class fifo:
    def __init__ (self, list=None):
        if not list:
            self.list = []
        else:
            self.list = list

    def __len__ (self):
        return len(self.list)

    def is_empty (self):
        return self.list == []

    def first (self):
        return self.list[0]

    def push (self, data):
        self.list.append (data)

    def pop (self):
        if self.list:
            result = self.list[0]
            del self.list[0]
            return (1, result)
        else:
            return (0, None)

# Given 'haystack', see if any prefix of 'needle' is at its end.  This
# assumes an exact match has already been checked.  Return the number of
# characters matched.
# for example:
# f_p_a_e ("qwerty\r", "\r\n") => 1
# f_p_a_e ("qwerty\r\n", "\r\n") => 2
# f_p_a_e ("qwertydkjf", "\r\n") => 0

# this could maybe be made faster with a computed regex?
# [answer: no; circa Python-2.0, Jan 2001]
# python:    18307/s
# re:        12820/s
# regex:     14035/s

def find_prefix_at_end (haystack, needle):
    nl = len(needle)
    result = 0
    for i in range (1,nl):
        if haystack[-(nl-i):] == needle[:(nl-i)]:
            result = nl-i
            break
    return result
<|endoftext|>


<commit_before>"""Python part of the warnings subsystem."""

# Note: function level imports should *not* be used
# in this module as it may cause import lock deadlock.
# See bug 683658.
import sys, types
import linecache

__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
           "resetwarnings"]

# filters contains a sequence of filter 5-tuples
# The components of the 5-tuple are:
# - an action: error, ignore, always, default, module, or once
# - a compiled regex that must match the warning message
# - a class representing the warning category
# - a compiled regex that must match the module that is being warned
# - a line number for the line being warning, or 0 to mean any line
# If either if the compiled regexs are None, match anything.
filters = []
defaultaction = "default"
onceregistry = {}

def warn(message, category=None, stacklevel=1):
    """Issue a warning, or maybe ignore it or raise an exception."""
    # Check if message is already a Warning object
    if isinstance(message, Warning):
        category = message.__class__
    # Check category argument
    if category is None:
        category = UserWarning
    assert issubclass(category, Warning)
    # Get context information
    try:
        caller = sys._getframe(stacklevel)
    except ValueError:
        globals = sys.__dict__
        lineno = 1
    else:
        globals = caller.f_globals
        lineno = caller.f_lineno
    if '__name__' in globals:
        module = globals['__name__']
    else:
        module = "<string>"
    filename = globals.get('__file__')
    if filename:
        fnl = filename.lower()
        if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
            filename = filename[:-1]
    else:
        if module == "__main__":
            filename = sys.argv[0]
        if not filename:
            filename = module
    registry = globals.setdefault("__warningregistry__", {})
    warn_explicit(message, category, filename, lineno, module, registry)

def warn_explicit(message, category, filename, lineno,
                  module=None, registry=None):
    if module is None:
        module = filename
        if module[-3:].lower() == ".py":
            module = module[:-3] # XXX What about leading pathname?
    if registry is None:
        registry = {}
    if isinstance(message, Warning):
        text = str(message)
        category = message.__class__
    else:
        text = message
        message = category(message)
    key = (text, category, lineno)
    # Quick test for common case
    if registry.get(key):
        return
    # Search the filters
    for item in filters:
        action, msg, cat, mod, ln = item
        if ((msg is None or msg.match(text)) and
            issubclass(category, cat) and
            (mod is None or mod.match(module)) and
            (ln == 0 or lineno == ln)):
            break
    else:
        action = defaultaction
    # Early exit actions
    if action == "ignore":
        registry[key] = 1
        return
    if action == "error":
        raise message
    # Other actions
    if action == "once":
        registry[key] = 1
        oncekey = (text, category)
        if onceregistry.get(oncekey):
            return
        onceregistry[oncekey] = 1
    elif action == "always":
        pass
    elif action == "module":
        registry[key] = 1
        altkey = (text, category, 0)
        if registry.get(altkey):
            return
        registry[altkey] = 1
    elif action == "default":
        registry[key] = 1
    else:
        # Unrecognized actions are errors
        raise RuntimeError(
              "Unrecognized action (%r) in warnings.filters:\n %s" %
              (action, item))
    # Print message and context
    showwarning(message, category, filename, lineno)

def showwarning(message, category, filename, lineno, file=None):
    """Hook to write a warning to a file; replace if you like."""
    if file is None:
        file = sys.stderr
    try:
        file.write(formatwarning(message, category, filename, lineno))
    except IOError:
        pass # the file (probably stderr) is invalid - this warning gets lost.

def formatwarning(message, category, filename, lineno):
    """Function to format a warning the standard way."""
    s =  "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
    line = linecache.getline(filename, lineno).strip()
    if line:
        s = s + "  " + line + "\n"
    return s

def filterwarnings(action, message="", category=Warning, module="", lineno=0,
                   append=0):
    """Insert an entry into the list of warnings filters (at the front).

    Use assertions to check that all arguments have the right type."""
    import re
    assert action in ("error", "ignore", "always", "default", "module",
                      "once"), "invalid action: %r" % (action,)
    assert isinstance(message, basestring), "message must be a string"
    assert isinstance(category, types.ClassType), "category must be a class"
    assert issubclass(category, Warning), "category must be a Warning subclass"
    assert isinstance(module, basestring), "module must be a string"
    assert isinstance(lineno, int) and lineno >= 0, \
           "lineno must be an int >= 0"
    item = (action, re.compile(message, re.I), category,
            re.compile(module), lineno)
    if append:
        filters.append(item)
    else:
        filters.insert(0, item)

def simplefilter(action, category=Warning, lineno=0, append=0):
    """Insert a simple entry into the list of warnings filters (at the front).

    A simple filter matches all modules and messages.
    """
    assert action in ("error", "ignore", "always", "default", "module",
                      "once"), "invalid action: %r" % (action,)
    assert isinstance(lineno, int) and lineno >= 0, \
           "lineno must be an int >= 0"
    item = (action, None, category, None, lineno)
    if append:
        filters.append(item)
    else:
        filters.insert(0, item)

def resetwarnings():
    """Clear the list of warning filters, so that no filters are active."""
    filters[:] = []

class _OptionError(Exception):
    """Exception used by option processing helpers."""
    pass

# Helper to process -W options passed via sys.warnoptions
def _processoptions(args):
    for arg in args:
        try:
            _setoption(arg)
        except _OptionError, msg:
            print >>sys.stderr, "Invalid -W option ignored:", msg

# Helper for _processoptions()
def _setoption(arg):
    import re
    parts = arg.split(':')
    if len(parts) > 5:
        raise _OptionError("too many fields (max 5): %r" % (arg,))
    while len(parts) < 5:
        parts.append('')
    action, message, category, module, lineno = [s.strip()
                                                 for s in parts]
    action = _getaction(action)
    message = re.escape(message)
    category = _getcategory(category)
    module = re.escape(module)
    if module:
        module = module + '$'
    if lineno:
        try:
            lineno = int(lineno)
            if lineno < 0:
                raise ValueError
        except (ValueError, OverflowError):
            raise _OptionError("invalid lineno %r" % (lineno,))
    else:
        lineno = 0
    filterwarnings(action, message, category, module, lineno)

# Helper for _setoption()
def _getaction(action):
    if not action:
        return "default"
    if action == "all": return "always" # Alias
    for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
        if a.startswith(action):
            return a
    raise _OptionError("invalid action: %r" % (action,))

# Helper for _setoption()
def _getcategory(category):
    import re
    if not category:
        return Warning
    if re.match("^[a-zA-Z0-9_]+$", category):
        try:
            cat = eval(category)
        except NameError:
            raise _OptionError("unknown warning category: %r" % (category,))
    else:
        i = category.rfind(".")
        module = category[:i]
        klass = category[i+1:]
        try:
            m = __import__(module, None, None, [klass])
        except ImportError:
            raise _OptionError("invalid module name: %r" % (module,))
        try:
            cat = getattr(m, klass)
        except AttributeError:
            raise _OptionError("unknown warning category: %r" % (category,))
    if (not isinstance(cat, types.ClassType) or
        not issubclass(cat, Warning)):
        raise _OptionError("invalid warning category: %r" % (category,))
    return cat

# Module initialization
_processoptions(sys.warnoptions)
# XXX OverflowWarning should go away for Python 2.5.
simplefilter("ignore", category=OverflowWarning, append=1)
simplefilter("ignore", category=PendingDeprecationWarning, append=1)
<commit_msg>bug [ 839151 ] attempt to access sys.argv when it doesn't exist<commit_after>"""Python part of the warnings subsystem."""

# Note: function level imports should *not* be used
# in this module as it may cause import lock deadlock.
# See bug 683658.
import sys, types
import linecache

__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
           "resetwarnings"]

# filters contains a sequence of filter 5-tuples
# The components of the 5-tuple are:
# - an action: error, ignore, always, default, module, or once
# - a compiled regex that must match the warning message
# - a class representing the warning category
# - a compiled regex that must match the module that is being warned
# - a line number for the line being warning, or 0 to mean any line
# If either if the compiled regexs are None, match anything.
filters = []
defaultaction = "default"
onceregistry = {}

def warn(message, category=None, stacklevel=1):
    """Issue a warning, or maybe ignore it or raise an exception."""
    # Check if message is already a Warning object
    if isinstance(message, Warning):
        category = message.__class__
    # Check category argument
    if category is None:
        category = UserWarning
    assert issubclass(category, Warning)
    # Get context information
    try:
        caller = sys._getframe(stacklevel)
    except ValueError:
        globals = sys.__dict__
        lineno = 1
    else:
        globals = caller.f_globals
        lineno = caller.f_lineno
    if '__name__' in globals:
        module = globals['__name__']
    else:
        module = "<string>"
    filename = globals.get('__file__')
    if filename:
        fnl = filename.lower()
        if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
            filename = filename[:-1]
    else:
        if module == "__main__":
            try:
                filename = sys.argv[0]
            except AttributeError:
                # embedded interpreters don't have sys.argv, see bug #839151
                filename = '__main__'
        if not filename:
            filename = module
    registry = globals.setdefault("__warningregistry__", {})
    warn_explicit(message, category, filename, lineno, module, registry)

def warn_explicit(message, category, filename, lineno,
                  module=None, registry=None):
    if module is None:
        module = filename
        if module[-3:].lower() == ".py":
            module = module[:-3] # XXX What about leading pathname?
    if registry is None:
        registry = {}
    if isinstance(message, Warning):
        text = str(message)
        category = message.__class__
    else:
        text = message
        message = category(message)
    key = (text, category, lineno)
    # Quick test for common case
    if registry.get(key):
        return
    # Search the filters
    for item in filters:
        action, msg, cat, mod, ln = item
        if ((msg is None or msg.match(text)) and
            issubclass(category, cat) and
            (mod is None or mod.match(module)) and
            (ln == 0 or lineno == ln)):
            break
    else:
        action = defaultaction
    # Early exit actions
    if action == "ignore":
        registry[key] = 1
        return
    if action == "error":
        raise message
    # Other actions
    if action == "once":
        registry[key] = 1
        oncekey = (text, category)
        if onceregistry.get(oncekey):
            return
        onceregistry[oncekey] = 1
    elif action == "always":
        pass
    elif action == "module":
        registry[key] = 1
        altkey = (text, category, 0)
        if registry.get(altkey):
            return
        registry[altkey] = 1
    elif action == "default":
        registry[key] = 1
    else:
        # Unrecognized actions are errors
        raise RuntimeError(
              "Unrecognized action (%r) in warnings.filters:\n %s" %
              (action, item))
    # Print message and context
    showwarning(message, category, filename, lineno)

def showwarning(message, category, filename, lineno, file=None):
    """Hook to write a warning to a file; replace if you like."""
    if file is None:
        file = sys.stderr
    try:
        file.write(formatwarning(message, category, filename, lineno))
    except IOError:
        pass # the file (probably stderr) is invalid - this warning gets lost.

def formatwarning(message, category, filename, lineno):
    """Function to format a warning the standard way."""
    s =  "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
    line = linecache.getline(filename, lineno).strip()
    if line:
        s = s + "  " + line + "\n"
    return s

def filterwarnings(action, message="", category=Warning, module="", lineno=0,
                   append=0):
    """Insert an entry into the list of warnings filters (at the front).

    Use assertions to check that all arguments have the right type."""
    import re
    assert action in ("error", "ignore", "always", "default", "module",
                      "once"), "invalid action: %r" % (action,)
    assert isinstance(message, basestring), "message must be a string"
    assert isinstance(category, types.ClassType), "category must be a class"
    assert issubclass(category, Warning), "category must be a Warning subclass"
    assert isinstance(module, basestring), "module must be a string"
    assert isinstance(lineno, int) and lineno >= 0, \
           "lineno must be an int >= 0"
    item = (action, re.compile(message, re.I), category,
            re.compile(module), lineno)
    if append:
        filters.append(item)
    else:
        filters.insert(0, item)

def simplefilter(action, category=Warning, lineno=0, append=0):
    """Insert a simple entry into the list of warnings filters (at the front).

    A simple filter matches all modules and messages.
    """
    assert action in ("error", "ignore", "always", "default", "module",
                      "once"), "invalid action: %r" % (action,)
    assert isinstance(lineno, int) and lineno >= 0, \
           "lineno must be an int >= 0"
    item = (action, None, category, None, lineno)
    if append:
        filters.append(item)
    else:
        filters.insert(0, item)

def resetwarnings():
    """Clear the list of warning filters, so that no filters are active."""
    filters[:] = []

class _OptionError(Exception):
    """Exception used by option processing helpers."""
    pass

# Helper to process -W options passed via sys.warnoptions
def _processoptions(args):
    for arg in args:
        try:
            _setoption(arg)
        except _OptionError, msg:
            print >>sys.stderr, "Invalid -W option ignored:", msg

# Helper for _processoptions()
def _setoption(arg):
    import re
    parts = arg.split(':')
    if len(parts) > 5:
        raise _OptionError("too many fields (max 5): %r" % (arg,))
    while len(parts) < 5:
        parts.append('')
    action, message, category, module, lineno = [s.strip()
                                                 for s in parts]
    action = _getaction(action)
    message = re.escape(message)
    category = _getcategory(category)
    module = re.escape(module)
    if module:
        module = module + '$'
    if lineno:
        try:
            lineno = int(lineno)
            if lineno < 0:
                raise ValueError
        except (ValueError, OverflowError):
            raise _OptionError("invalid lineno %r" % (lineno,))
    else:
        lineno = 0
    filterwarnings(action, message, category, module, lineno)

# Helper for _setoption()
def _getaction(action):
    if not action:
        return "default"
    if action == "all": return "always" # Alias
    for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
        if a.startswith(action):
            return a
    raise _OptionError("invalid action: %r" % (action,))

# Helper for _setoption()
def _getcategory(category):
    import re
    if not category:
        return Warning
    if re.match("^[a-zA-Z0-9_]+$", category):
        try:
            cat = eval(category)
        except NameError:
            raise _OptionError("unknown warning category: %r" % (category,))
    else:
        i = category.rfind(".")
        module = category[:i]
        klass = category[i+1:]
        try:
            m = __import__(module, None, None, [klass])
        except ImportError:
            raise _OptionError("invalid module name: %r" % (module,))
        try:
            cat = getattr(m, klass)
        except AttributeError:
            raise _OptionError("unknown warning category: %r" % (category,))
    if (not isinstance(cat, types.ClassType) or
        not issubclass(cat, Warning)):
        raise _OptionError("invalid warning category: %r" % (category,))
    return cat

# Module initialization
_processoptions(sys.warnoptions)
# XXX OverflowWarning should go away for Python 2.5.
simplefilter("ignore", category=OverflowWarning, append=1)
simplefilter("ignore", category=PendingDeprecationWarning, append=1)
<|endoftext|>


<commit_before>"""
Copyright (c) 2015 Red Hat, Inc
All rights reserved.

This software may be modified and distributed under the terms
of the BSD license. See the LICENSE file for details.

It returns the dockerfile itself and therefore displays it in results.
"""
from __future__ import unicode_literals
import os

from atomic_reactor.constants import EXPORTED_SQUASHED_IMAGE_NAME
from atomic_reactor.plugin import PrePublishPlugin
from atomic_reactor.util import get_exported_image_metadata
from docker_scripts.squash import Squash

__all__ = ('PrePublishSquashPlugin', )

class PrePublishSquashPlugin(PrePublishPlugin):

    """
    This feature requires docker-scripts package to be installed in version 0.3.2
    or higher.

    Usage:

    A json build config file should be created with following content:

    ```
      "prepublish_plugins": [{
        "name": "squash",
          "args": {
            "tag": "SQUASH_TAG",
            "from_layer": "FROM_LAYER",
            "remove_former_image": false,
            "dont_load": false
          }
        }
      }
    ```

    The `tag` argument specifes the tag under which the new squashed image will
    be registered. The `from_layer` argument specifies from which layer we want
    to squash. `remove_former_image` is an optional boolean argument which specifies
    if former, unsquashed image should be removed.

    Of course it's possible to override it at runtime, like this: `--substitute prepublish_plugins.squash.tag=image:squashed
      --substitute prepublish_plugins.squash.from_layer=asdasd2332`.
    """

    key = "squash"
    # Fail the build in case of squashing error
    is_allowed_to_fail = False

    def __init__(self, tasker, workflow, tag=None, from_base=True, from_layer=None,
                 remove_former_image=True, dont_load=False):
        """
        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param from_base: bool, squash from base-image layer, on by default
        :param from_layer: layer from we will squash - if specified, takes precedence over from_base
        :param tag: str, new name of the image - by default use the former one
        :param remove_former_image: bool, remove unsquashed image?
        :param dont_load: bool, don't load squashed image into Docker, place it to `$tmpdir/image.tar` instead
        """
        super(PrePublishSquashPlugin, self).__init__(tasker, workflow)
        self.image = self.workflow.builder.image_id
        self.tag = tag or str(self.workflow.builder.image)
        self.from_layer = from_layer
        if from_base and from_layer is None:
            try:
                base_image_id = self.workflow.base_image_inspect['Id']
            except KeyError:
                self.log.error("Missing Id in inspection: '%s'", self.workflow.base_image_inspect)
                raise
            self.log.info("will squash from base-image: '%s'", base_image_id)
            self.from_layer = base_image_id
        self.remove_former_image = remove_former_image
        self.dont_load = dont_load

    def run(self):
        if self.dont_load:
            metadata = {}
            self.workflow.exported_image_sequence.append(metadata)
            metadata["path"] = \
                os.path.join(self.workflow.source.workdir, EXPORTED_SQUASHED_IMAGE_NAME)
            # squash the image, don't load it back to docker
            Squash(log=self.log, image=self.image, from_layer=self.from_layer,
                   tag=self.tag, output_path=metadata["path"]).run()
            metadata.update(get_exported_image_metadata(metadata["path"]))
        else:
            # squash the image and load it back to engine
            new_id = Squash(log=self.log, image=self.image, from_layer=self.from_layer,
                            tag=self.tag).run()
            self.workflow.builder.image_id = new_id
        if self.remove_former_image:
            self.tasker.remove_image(self.image)
<commit_msg>Make squash plugin output both tar and engine image if dont_load is False.<commit_after>"""
Copyright (c) 2015 Red Hat, Inc
All rights reserved.

This software may be modified and distributed under the terms
of the BSD license. See the LICENSE file for details.

It returns the dockerfile itself and therefore displays it in results.
"""
from __future__ import unicode_literals
import os

from atomic_reactor.constants import EXPORTED_SQUASHED_IMAGE_NAME
from atomic_reactor.plugin import PrePublishPlugin
from atomic_reactor.util import get_exported_image_metadata
from docker_scripts.squash import Squash

__all__ = ('PrePublishSquashPlugin', )

class PrePublishSquashPlugin(PrePublishPlugin):

    """
    This feature requires docker-scripts package to be installed in version 0.3.2
    or higher.

    Usage:

    A json build config file should be created with following content:

    ```
      "prepublish_plugins": [{
        "name": "squash",
          "args": {
            "tag": "SQUASH_TAG",
            "from_layer": "FROM_LAYER",
            "remove_former_image": false,
            "dont_load": false
          }
        }
      }
    ```

    The `tag` argument specifes the tag under which the new squashed image will
    be registered. The `from_layer` argument specifies from which layer we want
    to squash. `remove_former_image` is an optional boolean argument which specifies
    if former, unsquashed image should be removed.

    Of course it's possible to override it at runtime, like this: `--substitute prepublish_plugins.squash.tag=image:squashed
      --substitute prepublish_plugins.squash.from_layer=asdasd2332`.
    """

    key = "squash"
    # Fail the build in case of squashing error
    is_allowed_to_fail = False

    def __init__(self, tasker, workflow, tag=None, from_base=True, from_layer=None,
                 remove_former_image=True, dont_load=False):
        """
        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param from_base: bool, squash from base-image layer, on by default
        :param from_layer: layer from we will squash - if specified, takes precedence over from_base
        :param tag: str, new name of the image - by default use the former one
        :param remove_former_image: bool, remove unsquashed image?
        :param dont_load: if `False` (default), squashed image is loaded into Docker *and* saved
            to `$tmpdir/image.tar`; if `True`, squashed image is only saved as a file
        """
        super(PrePublishSquashPlugin, self).__init__(tasker, workflow)
        self.image = self.workflow.builder.image_id
        self.tag = tag or str(self.workflow.builder.image)
        self.from_layer = from_layer
        if from_base and from_layer is None:
            try:
                base_image_id = self.workflow.base_image_inspect['Id']
            except KeyError:
                self.log.error("Missing Id in inspection: '%s'", self.workflow.base_image_inspect)
                raise
            self.log.info("will squash from base-image: '%s'", base_image_id)
            self.from_layer = base_image_id
        self.remove_former_image = remove_former_image
        self.dont_load = dont_load

    def run(self):
        metadata = {}
        metadata["path"] = os.path.join(self.workflow.source.workdir, EXPORTED_SQUASHED_IMAGE_NAME)

        if self.dont_load:
            # squash the image, don't load it back to docker
            Squash(log=self.log, image=self.image, from_layer=self.from_layer,
                   tag=self.tag, output_path=metadata["path"]).run()
        else:
            # squash the image and output both tarfile and Docker engine image
            new_id = Squash(log=self.log, image=self.image, from_layer=self.from_layer,
                            tag=self.tag, output_path=metadata["path"], load_output_back=True
                            ).run()
            self.workflow.builder.image_id = new_id

        metadata.update(get_exported_image_metadata(metadata["path"]))
        self.workflow.exported_image_sequence.append(metadata)

        if self.remove_former_image:
            self.tasker.remove_image(self.image)
<|endoftext|>


<commit_before>import sys
import time

CONFIG_FILE = 'bot.ini'
BACKLOG_FILE = 'giveaway.txt'

Config = {}
Backlog = {}

class Init(object):
    """Inits backlog and config global variables"""
    def __init__(self):
        super(Init, self).__init__()
        u = Utils()
        u.read_config(CONFIG_FILE)
        u.read_backlog(BACKLOG_FILE)

class Utils(object):
    """miscellaneus utilities"""
    def __init__(self):
        super(Utils, self).__init__()

    def sprint(self, msg):
        """a statusbar-like print for console

        args:
            msg: the string to print
        """
        clock = "[" + time.asctime(time.localtime()) + "] "
        sys.stdout.write("\r" + clock + msg)
        sys.stdout.write("\033[K")
        sys.stdout.flush()

    def add_backlog_entry(self, id):
        """adds an entry to the backlog file

        args:
            id: the entry to add
        """
        with open(BACKLOG_FILE, 'a') as f:
            f.write(',' + id)

    def save_config(self, config_file):
        """saves the current config to disk

        args:
            config_file: the config file to write to
        """
        with open(config_file, 'w') as f:
            for section in Config:
                f.write('>>%s\n' % section)
                for entry in Config[key]:
                    f.write('%s\n' % entry)
                f.write('\n')

    def read_config(self, config_file):
        """reads the config file

        reads the config file specified in the config_file argument and
        populates the global Config dict accordingly.

        args:
            config_file: the config file to read and parse
        """
        with open(config_file) as f:
            for line in f.readlines():
                line = line.strip()
                if not line:
                    continue
                if line[0:2] == '>>':
                    values = []
                    section = line.split('>>')[1]
                else:
                    if len(line.split('=')) > 1:
                        values.append(line.split('=')[1])
                    else:
                        values.append(line)
                Config[section] = values

    def read_backlog(self, backlog_file):
        """reads the backlog file

        reads the backlog file specified in the backlog_file argument and
        populates the global Backlog dict accordingly.

        args:
            backlog_file: the backlog file to read and parse

        raises: IOError when the file doesn't exist, and proceeds to create one
        """
        try:
            f = open(backlog_file)
            f.close()
        except IOError:
            with open(backlog_file, 'w') as f:
                f.write('bogus')

        with open(backlog_file, 'r') as f:
            for entry in f.read().split(','):
                Backlog[entry] = True
<commit_msg>removed useless arguments<commit_after>import sys
import time

CONFIG_FILE = 'bot.ini'
BACKLOG_FILE = 'giveaway.txt'

Config = {}
Backlog = {}

class Init(object):
    """Inits backlog and config global variables"""
    def __init__(self):
        super(Init, self).__init__()
        u = Utils()
        u.read_config()
        u.read_backlog()

class Utils(object):
    """miscellaneus utilities"""
    def __init__(self):
        super(Utils, self).__init__()

    def sprint(self, msg):
        """a statusbar-like print for console

        args:
            msg: the string to print
        """
        clock = "[" + time.asctime(time.localtime()) + "] "
        sys.stdout.write("\r" + clock + msg)
        sys.stdout.write("\033[K")
        sys.stdout.flush()

    def add_backlog_entry(self, id):
        """adds an entry to the backlog file

        args:
            id: the entry to add
        """
        with open(BACKLOG_FILE, 'a') as f:
            f.write(',' + id)

    def save_config(self):
        """saves the current config to disk

        args:
            config_file: the config file to write to
        """
        with open(CONFIG_FILE, 'w') as f:
            for section in Config:
                f.write('>>%s\n' % section)
                for entry in Config[key]:
                    f.write('%s\n' % entry)
                f.write('\n')

    def read_config(self):
        """reads the config file

        reads the config file specified in the config_file argument and
        populates the global Config dict accordingly.

        args:
            config_file: the config file to read and parse
        """
        with open(CONFIG_FILE) as f:
            for line in f.readlines():
                line = line.strip()
                if not line:
                    continue
                if line[0:2] == '>>':
                    values = []
                    section = line.split('>>')[1]
                else:
                    if len(line.split('=')) > 1:
                        values.append(line.split('=')[1])
                    else:
                        values.append(line)
                Config[section] = values

    def read_backlog(self):
        """reads the backlog file

        reads the backlog file specified in the backlog_file argument and
        populates the global Backlog dict accordingly.

        args:
            backlog_file: the backlog file to read and parse

        raises: IOError when the file doesn't exist, and proceeds to create one
        """
        try:
            f = open(BACKLOG_FILE)
            f.close()
        except IOError:
            with open(BACKLOG_FILE, 'w') as f:
                f.write('bogus')

        with open(BACKLOG_FILE, 'r') as f:
            for entry in f.read().split(','):
                Backlog[entry] = True
<|endoftext|>


<commit_before>from nose.tools import assert_raises

from bamboo.core.parser import ParseError
from bamboo.models.calculation import Calculation, DependencyError
from bamboo.models.dataset import Dataset
from bamboo.tests.test_base import TestBase

class TestCalculation(TestBase):

    def setUp(self):
        TestBase.setUp(self)
        self.dataset = Dataset()
        self.dataset.save(self.test_dataset_ids['good_eats.csv'])
        self.formula = 'rating'
        self.name = 'test'

    def _save_calculation(self, formula):
        if not formula:
            formula = self.formula
        return self.calculation.save(self.dataset, formula, self.name)

    def _save_observations(self):
        self.dataset.save_observations(self.get_data('good_eats.csv'))

    def _save_observations_and_calculation(self, formula=None):
        self._save_observations()
        self.calculation = Calculation()
        return self._save_calculation(formula)

    def test_save(self):
        record = self._save_observations_and_calculation()
        self.assertTrue(isinstance(record, dict))
        self.assertTrue(Calculation.FORMULA in record.keys())
        self.assertTrue(Calculation.STATE in record.keys())
        record = Calculation.find(self.dataset)[0].record
        self.assertEqual(record[Calculation.STATE], Calculation.STATE_READY)
        self.assertTrue(Calculation(record).is_ready)

    def test_save_set_status(self):
        record = self._save_observations_and_calculation()
        self.assertTrue(isinstance(record, dict))
        self.assertTrue(Calculation.FORMULA in record.keys())

    def test_save_set_aggregation(self):
        record = self._save_observations_and_calculation('max(amount)')
        calculation = Calculation.find(self.dataset)[0]
        self.assertEqual('max', calculation.aggregation)

    def test_save_set_aggregation_id(self):
        record = self._save_observations_and_calculation('max(amount)')
        agg_id = self.dataset.aggregated_datasets_dict['']
        calculation = Calculation.find(self.dataset)[0]
        self.assertEqual(agg_id, calculation.aggregation_id)

    def test_save_improper_formula(self):
        assert_raises(ParseError, self._save_observations_and_calculation,
                      'NON_EXISTENT_COLUMN')
        try:
            self._save_observations_and_calculation('NON_EXISTENT_COLUMN')
        except ParseError as e:
            self.assertTrue('Missing column' in e.__str__())

    def test_save_unparsable_formula(self):
        assert_raises(ParseError, self._save_observations_and_calculation,
                      '=NON_EXISTENT_COLUMN')
        try:
            self._save_observations_and_calculation(
                '=NON_EXISTENT_COLUMN')
        except ParseError as e:
            self.assertTrue('Parse Failure' in e.__str__())

    def test_save_improper_formula_no_data(self):
        assert_raises(ParseError, Calculation().save, self.dataset,
                      'NON_EXISTENT_COLUMN', self.name)
        try:
            Calculation().save(self.dataset, 'NON_EXISTENT_COLUMN',
                               self.name)
        except ParseError as e:
            self.assertTrue('No schema' in e.__str__())

    def test_save_unparsable_formula_no_data(self):
        assert_raises(ParseError, Calculation().save, self.dataset,
                      '=NON_EXISTENT_COLUMN', self.name)
        try:
            Calculation().save(self.dataset, '=NON_EXISTENT_COLUMN',
                               self.name)
        except ParseError as e:
            self.assertTrue('Parse Failure' in e.__str__())

    def test_save_non_existent_group(self):
        self._save_observations()
        assert_raises(ParseError, Calculation().save, self.dataset,
                      self.formula, self.name, group='NON_EXISTENT_GROUP')
        try:
            Calculation().save(self.dataset, self.formula, self.name,
                               group='NON_EXISTENT_GROUP')
        except ParseError as e:
            self.assertTrue('Group' in e.__str__())

    def test_find(self):
        record = self._save_observations_and_calculation()
        rows = Calculation.find(self.dataset)
        new_record = rows[0].record
        status = new_record.pop(Calculation.STATE)
        self.assertEqual(status, Calculation.STATE_READY)

    def test_sets_dependent_calculations(self):
        record = self._save_observations_and_calculation()
        self.name = 'test1'
        record = self._save_calculation('test')
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, ['test1'])

    def test_removes_dependent_calculations(self):
        record = self._save_observations_and_calculation()
        self.name = 'test1'
        record = self._save_calculation('test')
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, ['test1'])
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test1')
        calculation.delete(self.dataset)
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, [])

    def test_disallow_delete_dependent_calculation(self):
        record = self._save_observations_and_calculation()
        self.name = 'test1'
        record = self._save_calculation('test')
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, ['test1'])
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        assert_raises(DependencyError, calculation.delete, self.dataset)
<commit_msg>fix group sig ref<commit_after>from nose.tools import assert_raises

from bamboo.core.parser import ParseError
from bamboo.models.calculation import Calculation, DependencyError
from bamboo.models.dataset import Dataset
from bamboo.tests.test_base import TestBase

class TestCalculation(TestBase):

    def setUp(self):
        TestBase.setUp(self)
        self.dataset = Dataset()
        self.dataset.save(self.test_dataset_ids['good_eats.csv'])
        self.formula = 'rating'
        self.name = 'test'

    def _save_calculation(self, formula):
        if not formula:
            formula = self.formula
        return self.calculation.save(self.dataset, formula, self.name)

    def _save_observations(self):
        self.dataset.save_observations(self.get_data('good_eats.csv'))

    def _save_observations_and_calculation(self, formula=None):
        self._save_observations()
        self.calculation = Calculation()
        return self._save_calculation(formula)

    def test_save(self):
        record = self._save_observations_and_calculation()
        self.assertTrue(isinstance(record, dict))
        self.assertTrue(Calculation.FORMULA in record.keys())
        self.assertTrue(Calculation.STATE in record.keys())
        record = Calculation.find(self.dataset)[0].record
        self.assertEqual(record[Calculation.STATE], Calculation.STATE_READY)
        self.assertTrue(Calculation(record).is_ready)

    def test_save_set_status(self):
        record = self._save_observations_and_calculation()
        self.assertTrue(isinstance(record, dict))
        self.assertTrue(Calculation.FORMULA in record.keys())

    def test_save_set_aggregation(self):
        record = self._save_observations_and_calculation('max(amount)')
        calculation = Calculation.find(self.dataset)[0]
        self.assertEqual('max', calculation.aggregation)

    def test_save_set_aggregation_id(self):
        record = self._save_observations_and_calculation('max(amount)')
        agg_id = self.dataset.aggregated_datasets_dict['']
        calculation = Calculation.find(self.dataset)[0]
        self.assertEqual(agg_id, calculation.aggregation_id)

    def test_save_improper_formula(self):
        assert_raises(ParseError, self._save_observations_and_calculation,
                      'NON_EXISTENT_COLUMN')
        try:
            self._save_observations_and_calculation('NON_EXISTENT_COLUMN')
        except ParseError as e:
            self.assertTrue('Missing column' in e.__str__())

    def test_save_unparsable_formula(self):
        assert_raises(ParseError, self._save_observations_and_calculation,
                      '=NON_EXISTENT_COLUMN')
        try:
            self._save_observations_and_calculation(
                '=NON_EXISTENT_COLUMN')
        except ParseError as e:
            self.assertTrue('Parse Failure' in e.__str__())

    def test_save_improper_formula_no_data(self):
        assert_raises(ParseError, Calculation().save, self.dataset,
                      'NON_EXISTENT_COLUMN', self.name)
        try:
            Calculation().save(self.dataset, 'NON_EXISTENT_COLUMN',
                               self.name)
        except ParseError as e:
            self.assertTrue('No schema' in e.__str__())

    def test_save_unparsable_formula_no_data(self):
        assert_raises(ParseError, Calculation().save, self.dataset,
                      '=NON_EXISTENT_COLUMN', self.name)
        try:
            Calculation().save(self.dataset, '=NON_EXISTENT_COLUMN',
                               self.name)
        except ParseError as e:
            self.assertTrue('Parse Failure' in e.__str__())

    def test_save_non_existent_group(self):
        self._save_observations()
        assert_raises(ParseError, Calculation().save, self.dataset,
                      self.formula, self.name, group_str='NON_EXISTENT_GROUP')
        try:
            Calculation().save(self.dataset, self.formula, self.name,
                               group_str='NON_EXISTENT_GROUP')
        except ParseError as e:
            self.assertTrue('Group' in e.__str__())

    def test_find(self):
        record = self._save_observations_and_calculation()
        rows = Calculation.find(self.dataset)
        new_record = rows[0].record
        status = new_record.pop(Calculation.STATE)
        self.assertEqual(status, Calculation.STATE_READY)

    def test_sets_dependent_calculations(self):
        record = self._save_observations_and_calculation()
        self.name = 'test1'
        record = self._save_calculation('test')
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, ['test1'])

    def test_removes_dependent_calculations(self):
        record = self._save_observations_and_calculation()
        self.name = 'test1'
        record = self._save_calculation('test')
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, ['test1'])
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test1')
        calculation.delete(self.dataset)
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, [])

    def test_disallow_delete_dependent_calculation(self):
        record = self._save_observations_and_calculation()
        self.name = 'test1'
        record = self._save_calculation('test')
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        self.assertEqual(calculation.dependent_calculations, ['test1'])
        calculation = Calculation.find_one(self.dataset.dataset_id, 'test')
        assert_raises(DependencyError, calculation.delete, self.dataset)
<|endoftext|>


<commit_before>#-------------------------------------------------------------------------------
# Name:        test Logistic Regression
# Purpose:
#
# Author:      Nonlining
#
# Created:     19/12/2017
# Copyright:   (c) Nonlining 2017
# Licence:     <your licence>
#-------------------------------------------------------------------------------
import LogisticRegression as LR
import pandas as pd
import numpy as np

# import sklearn for sentiment
from sklearn.feature_extraction.text import CountVectorizer
from sklearn import datasets, linear_model
from sklearn.linear_model import LogisticRegression

def main():
    np.random.seed(seed=1)

    products = pd.read_csv('../Datafiles/amazon_baby.csv')

    review_without_punctuation = products['review'].apply(LR.remove_punctuation)
    products['word_count'] = review_without_punctuation.apply(LR.countWords)
    products['clear_words'] = review_without_punctuation

    # print 5 items in the list
    print review_without_punctuation.head()

    # remove all rating 3 , they are considered as neutral
    products = products[products['rating'] != 3]
    products['sentiment'] = products['rating'].apply(lambda rating: +1 if rating > 3 else -1)

    mask = np.random.rand(len(products)) < 0.8

    train = products[mask]
    test = products[~mask]
    print "Training data size",len(train), "Testing data size",len(test)

    train_reviews = np.array(train['clear_words'])
    train_labels = np.array(train['sentiment'])

    vect = CountVectorizer().fit(train_reviews)
    trained_vectorized = vect.transform(train_reviews)

    sentiment_model = LogisticRegression()

    sentiment_model.fit(trained_vectorized, train_labels)
    print sentiment_model.coef_
    print np.sum(sum(sentiment_model.coef_ >= 0))

    sample_test_data = test[10:13]
    print sample_test_data

if __name__ == '__main__':
    main()
<commit_msg>update<commit_after>#-------------------------------------------------------------------------------
# Name:        test Logistic Regression
# Purpose:
#
# Author:      Nonlining
#
# Created:     19/12/2017
# Copyright:   (c) Nonlining 2017
# Licence:     <your licence>
#-------------------------------------------------------------------------------
import LogisticRegression as LR
import pandas as pd
import numpy as np

# import sklearn for sentiment
from sklearn.feature_extraction.text import CountVectorizer
from sklearn import datasets, linear_model
from sklearn.linear_model import LogisticRegression

def main():
    np.random.seed(seed=1)

    products = pd.read_csv('../Datafiles/amazon_baby.csv')

    review_without_punctuation = products['review'].apply(LR.remove_punctuation)
    products['word_count'] = review_without_punctuation.apply(LR.countWords)
    products['clear_words'] = review_without_punctuation

    # print 5 items in the list
    print review_without_punctuation.head()

    # remove all rating 3 , they are considered as neutral
    products = products[products['rating'] != 3]
    products['sentiment'] = products['rating'].apply(lambda rating: +1 if rating > 3 else -1)

    mask = np.random.rand(len(products)) < 0.8

    train = products[mask]
    test = products[~mask]
    print "Training data size",len(train), "Testing data size",len(test)

    train_reviews = np.array(train['clear_words'])
    train_labels = np.array(train['sentiment'])

    vect = CountVectorizer().fit(train_reviews)
    trained_vectorized = vect.transform(train_reviews)

    sentiment_model = LogisticRegression()

    sentiment_model.fit(trained_vectorized, train_labels)
    print sentiment_model.coef_
    print np.sum(sum(sentiment_model.coef_ >= 0))

    sample_test_data = test[10:13]
    print sample_test_data

    sample_test_matrix = vect.transform(sample_test_data['clear_words'])

    print sentiment_model.predict(sample_test_matrix)

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


<commit_before>#!/opt/bin/python

import argparse
import json
import os
import sys
import shutil
import re
import time
import logging

def watch_for_media(folder):
    last_time_stamp = os.stat(folder).st_mtime
    if last_time_stamp < os.stat(folder).st_mtime:
        find_media(folder)
        last_time_stamp = os.stat(folder).st_mtime
    time.sleep(15*60)

def find_media(folder):
    for root, folders, files in os.walk(folder):
        for entry in files:
            ext = os.path.splitext(entry)
            if ext in config["accepted_video_exts"]:
                check_media(root, entry)

def check_media(dir, entry):
    # Check if file name contains a known episode pattern
    for regex in config["episode_regexs"]:
        result = re.search(regex, entry, re.I|re.U)
        if result:
            convert_episode(dir, entry, result)
    convert_movie(dir, entry)

def convert_episode(dir, entry, episode_match):
    logging.info("Found TV episode at: {}".format(os.path.join(dir, entry)))

def convert_movie(dir, entry):
    logging.info("Found movie at: {}".format(os.path.join(dir, entry)))

if __name__ == "__main__":
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("--auto", action="store_true",
        help="Should go with the best guess."
    )
    arg_parser.add_argument("--watch", action="store_true",
        help="Should check folder every 15 mins."
    )

    args = vars(arg_parser.parse_args())

    global config
    with open("./config.json") as reader:
        config = json.load(reader)

    config.update(args)

    if config.get("watch"):
        watch_for_media(config["watch_folder"])
    else:
        find_media(config["watch_folder"])
<commit_msg>print config<commit_after>#!/opt/bin/python

import argparse
import json
import os
import sys
import shutil
import re
import time
import logging

def watch_for_media(folder):
    last_time_stamp = os.stat(folder).st_mtime
    if last_time_stamp < os.stat(folder).st_mtime:
        find_media(folder)
        last_time_stamp = os.stat(folder).st_mtime
    time.sleep(15*60)

def find_media(folder):
    for root, folders, files in os.walk(folder):
        logging.info("Checking: {}".format(root))
        for entry in files:
            ext = os.path.splitext(entry)
            if ext in config["accepted_video_exts"]:
                check_media(root, entry)

def check_media(dir, entry):
    # Check if file name contains a known episode pattern
    for regex in config["episode_regexs"]:
        result = re.search(regex, entry, re.I|re.U)
        if result:
            convert_episode(dir, entry, result)
    convert_movie(dir, entry)

def convert_episode(dir, entry, episode_match):
    logging.info("Found TV episode at: {}".format(os.path.join(dir, entry)))

def convert_movie(dir, entry):
    logging.info("Found movie at: {}".format(os.path.join(dir, entry)))

if __name__ == "__main__":
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("--auto", action="store_true",
        help="Should go with the best guess."
    )
    arg_parser.add_argument("--watch", action="store_true",
        help="Should check folder every 15 mins."
    )

    args = vars(arg_parser.parse_args())

    global config
    with open("./config.json") as reader:
        config = json.load(reader)

    config.update(args)

    print(config)

    if config.get("watch"):
        watch_for_media(config["watch_folder"])
    else:
        find_media(config["watch_folder"])
<|endoftext|>


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

"""
MediumBot's configuration GUI to make it easier for non-technical users to use
the bot.
Note: this is a starting point for the GUI and is not finished.
"""

from Tkinter import *
from ttk import *

class MediumBotGUI(Frame):

    def __init__(self, parent):
        """
        Initilaize the MediumBotGUI object.
        """
        Frame.__init__(self, parent)

        self.parent = parent
        self.initUI()

    def initUI(self):
        """
        Initialize the user interface.
        """

        mediumBotVariables = parseMediumBot()

        service = IntVar()
        likePosts = IntVar()
        randomizeLikes = IntVar()
        commentOnPosts = IntVar()
        randomizeComments = IntVar()
        followUsers = IntVar()
        randomizeFollowingUsers = IntVar()
        unfollowUsers = IntVar()
        randomizeUnfollowingUsers = IntVar()
        useRelatedTags = IntVar()
        verbose = IntVar()

        self.parent.title("Medium Bot")
        self.pack(fill=BOTH, expand=True)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(3, pad=7)
        self.rowconfigure(3, weight=1)
        self.rowconfigure(5, pad=7)

        emailLabel = Label(self, text="Email: ")
        emailLabel.grid(sticky=W, pady=4, padx=5)
        emailTextField = Entry(self, width = 100)
        emailTextField.grid(row=0, column=1, columnspan = 3)
        emailTextField.insert(10, mediumBotVariables["EMAIL"])

        passwordLabel = Label(self, text="Password: ")
        passwordLabel.grid(sticky=W, pady=4, padx=5)
        passwordField = Entry(self, show="*", width = 100)
        passwordField.grid(row=1, column=1, columnspan = 3)
        passwordField.insert(10, mediumBotVariables["PASSWORD"])

        serviceLabel = Label(self, text="Service: ")
        serviceLabel.grid(sticky=W, pady=4, padx=5)
        serviceDropDown = Combobox(self, values=["Google", "Facebook", "Twitter"], width = 100)
        serviceDropDown.grid(row=2, column=1, columnspan = 3)

        likePostsLabel = Label(self, text="Like Posts: ")
        likePostsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=likePosts).grid(row=3, column = 1, columnspan = 3)

        randomizeLikesLabel = Label(self, text="Randomize Likes: ")
        randomizeLikesLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeLikes).grid(row=4, column = 1, columnspan = 3)

        maxLikesLabel = Label(self, text="Max Likes On Posts: ")
        maxLikesLabel.grid(sticky=W, pady=4, padx=5)
        maxLikesField = Entry(self, width = 100)
        maxLikesField.grid(row=5, column=1, columnspan = 3)
        maxLikesField.insert(10, mediumBotVariables["MAX_LIKES_ON_POST"])

        commentPostsLabel = Label(self, text="Comment On Posts: ")
        commentPostsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=commentOnPosts).grid(row=6, column = 1, columnspan = 3)

        randomizeCommentsLabel = Label(self, text="Randomize Comments: ")
        randomizeCommentsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeComments).grid(row=7, column = 1, columnspan = 3)

        commentsLabel = Label(self, text="Comments: ")
        commentsLabel.grid(sticky=W, pady=4, padx=5)
        commentsField = Entry(self, width = 100)
        commentsField.grid(row=8, column=1, columnspan = 3)
        commentsField.insert(10, mediumBotVariables["COMMENTS"])

        articleBlackListLabel = Label(self, text="Article Black List: ")
        articleBlackListLabel.grid(sticky=W, pady=4, padx=5)
        articleBlackListField = Entry(self, width = 100)
        articleBlackListField.grid(row=9, column=1, columnspan = 3)
        articleBlackListField.insert(10, mediumBotVariables["ARTICLE_BLACK_LIST"])

        followUsersLabel = Label(self, text="Follow Users: ")
        followUsersLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=followUsers).grid(row=10, column = 1, columnspan = 3)

        randomizeFollowingLabel = Label(self, text="Randomize Following: ")
        randomizeFollowingLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeFollowingUsers).grid(row=11, column = 1, columnspan = 3)

        unfollowUsersLabel = Label(self, text="Unfollow Users: ")
        unfollowUsersLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=unfollowUsers).grid(row=12, column = 1, columnspan = 3)

        randomizeUnfollowingLabel = Label(self, text="Randomize Unfollowing: ")
        randomizeUnfollowingLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeUnfollowingUsers).grid(row=13, column = 1, columnspan = 3)

        unfollowBlackListLabel = Label(self, text="Unfollow Black List: ")
        unfollowBlackListLabel.grid(sticky=W, pady=4, padx=5)
        unfollowBlackListField = Entry(self, width = 100)
        unfollowBlackListField.grid(row=14, column=1, columnspan = 3)
        unfollowBlackListField.insert(10, mediumBotVariables["UNFOLLOW_USERS_BLACK_LIST"])

        useRelatedTagsLabel = Label(self, text="Use Related Tags: ")
        useRelatedTagsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=useRelatedTags).grid(row=15, column = 1, columnspan = 3)

        articlesPerTagLabel = Label(self, text="Articles Per Tag: ")
        articlesPerTagLabel.grid(sticky=W, pady=4, padx=5)
        articlesPerTagField = Entry(self, width = 100)
        articlesPerTagField.grid(row=16, column=1, columnspan = 3)

        verboseLabel = Label(self, text="Verbose Output: ")
        verboseLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=verbose).grid(row=17, column = 1, columnspan = 3)

        obtn = Button(self, text="Start Bot")
        obtn.grid(row=20, column=3)

def parseMediumBot():
    """
    Get the user's current set values in MediumBot.py to display in the fields.
    """

    lines = [line.rstrip('\n') for line in open('MediumBot.py')]
    charsToRemove = ["'", "[", "]", '"']
    mediumBotVariables = {}
    atStartOfVariables = False

    for line in lines:

        if not atStartOfVariables and "=" in line:
            atStartOfVariables = True
        elif atStartOfVariables and "=" not in line:
            break

        if atStartOfVariables:

            mediumBotVar = line.split(" = ")
            for charToRemove in charsToRemove:
                mediumBotVar[1] = mediumBotVar[1].replace(charToRemove,"")

            mediumBotVariables[mediumBotVar[0]] = mediumBotVar[1]

    return mediumBotVariables

def main():
    """
    Set the gui's window size, initialize and launch
    """

    root = Tk()
    root.geometry("500x550+300+300")
    app = MediumBotGUI(root)
    root.mainloop()

if __name__ == '__main__':
    main()
<commit_msg>Added logic to update variables once the start button is tapped in the MediumBot.py file.<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
MediumBot's configuration GUI to make it easier for non-technical users to use
the bot.
Note: this is a starting point for the GUI and is not finished.
"""

from Tkinter import *
from ttk import *
from tempfile import mkstemp
from shutil import move
from os import remove, close

FILE_PATH = "MediumBot.py"

class MediumBotGUI(Frame):

    def __init__(self, parent):
        """
        Initilaize the MediumBotGUI object.
        """
        Frame.__init__(self, parent)

        self.parent = parent
        self.initUI()

    def initUI(self):
        """
        Initialize the user interface.
        """

        mediumBotVariables = parseMediumBot()

        service = IntVar()
        likePosts = IntVar()
        randomizeLikes = IntVar()
        commentOnPosts = IntVar()
        randomizeComments = IntVar()
        followUsers = IntVar()
        randomizeFollowingUsers = IntVar()
        unfollowUsers = IntVar()
        randomizeUnfollowingUsers = IntVar()
        useRelatedTags = IntVar()
        verbose = IntVar()

        self.parent.title("Medium Bot")
        self.pack(fill=BOTH, expand=True)
        self.columnconfigure(1, weight=1)
        self.columnconfigure(3, pad=7)
        self.rowconfigure(3, weight=1)
        self.rowconfigure(5, pad=7)

        emailLabel = Label(self, text="Email: ")
        emailLabel.grid(sticky=W, pady=4, padx=5)
        emailTextField = Entry(self, width = 100)
        emailTextField.grid(row=0, column=1, columnspan = 3)
        emailTextField.insert(10, mediumBotVariables["EMAIL"])

        passwordLabel = Label(self, text="Password: ")
        passwordLabel.grid(sticky=W, pady=4, padx=5)
        passwordField = Entry(self, show="*", width = 100)
        passwordField.grid(row=1, column=1, columnspan = 3)
        passwordField.insert(10, mediumBotVariables["PASSWORD"])

        serviceLabel = Label(self, text="Service: ")
        serviceLabel.grid(sticky=W, pady=4, padx=5)
        serviceDropDown = Combobox(self, values=["Google", "Facebook", "Twitter"], width = 100)
        serviceDropDown.grid(row=2, column=1, columnspan = 3)

        likePostsLabel = Label(self, text="Like Posts: ")
        likePostsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=likePosts).grid(row=3, column = 1, columnspan = 3)

        randomizeLikesLabel = Label(self, text="Randomize Likes: ")
        randomizeLikesLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeLikes).grid(row=4, column = 1, columnspan = 3)

        maxLikesLabel = Label(self, text="Max Likes On Posts: ")
        maxLikesLabel.grid(sticky=W, pady=4, padx=5)
        maxLikesField = Entry(self, width = 100)
        maxLikesField.grid(row=5, column=1, columnspan = 3)
        maxLikesField.insert(10, mediumBotVariables["MAX_LIKES_ON_POST"])

        commentPostsLabel = Label(self, text="Comment On Posts: ")
        commentPostsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=commentOnPosts).grid(row=6, column = 1, columnspan = 3)

        randomizeCommentsLabel = Label(self, text="Randomize Comments: ")
        randomizeCommentsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeComments).grid(row=7, column = 1, columnspan = 3)

        commentsLabel = Label(self, text="Comments: ")
        commentsLabel.grid(sticky=W, pady=4, padx=5)
        commentsField = Entry(self, width = 100)
        commentsField.grid(row=8, column=1, columnspan = 3)
        commentsField.insert(10, mediumBotVariables["COMMENTS"])

        articleBlackListLabel = Label(self, text="Article Black List: ")
        articleBlackListLabel.grid(sticky=W, pady=4, padx=5)
        articleBlackListField = Entry(self, width = 100)
        articleBlackListField.grid(row=9, column=1, columnspan = 3)
        articleBlackListField.insert(10, mediumBotVariables["ARTICLE_BLACK_LIST"])

        followUsersLabel = Label(self, text="Follow Users: ")
        followUsersLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=followUsers).grid(row=10, column = 1, columnspan = 3)

        randomizeFollowingLabel = Label(self, text="Randomize Following: ")
        randomizeFollowingLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeFollowingUsers).grid(row=11, column = 1, columnspan = 3)

        unfollowUsersLabel = Label(self, text="Unfollow Users: ")
        unfollowUsersLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=unfollowUsers).grid(row=12, column = 1, columnspan = 3)

        randomizeUnfollowingLabel = Label(self, text="Randomize Unfollowing: ")
        randomizeUnfollowingLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=randomizeUnfollowingUsers).grid(row=13, column = 1, columnspan = 3)

        unfollowBlackListLabel = Label(self, text="Unfollow Black List: ")
        unfollowBlackListLabel.grid(sticky=W, pady=4, padx=5)
        unfollowBlackListField = Entry(self, width = 100)
        unfollowBlackListField.grid(row=14, column=1, columnspan = 3)
        unfollowBlackListField.insert(10, mediumBotVariables["UNFOLLOW_USERS_BLACK_LIST"])

        useRelatedTagsLabel = Label(self, text="Use Related Tags: ")
        useRelatedTagsLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=useRelatedTags).grid(row=15, column = 1, columnspan = 3)

        articlesPerTagLabel = Label(self, text="Articles Per Tag: ")
        articlesPerTagLabel.grid(sticky=W, pady=4, padx=5)
        articlesPerTagField = Entry(self, width = 100)
        articlesPerTagField.grid(row=16, column=1, columnspan = 3)

        verboseLabel = Label(self, text="Verbose Output: ")
        verboseLabel.grid(sticky=W, pady=4, padx=5)
        Checkbutton(self, text="", variable=verbose).grid(row=17, column = 1, columnspan = 3)

        obtn = Button(self, text="Start Bot")
        obtn.grid(row=20, column=3)

def parseMediumBot():
    """
    Get the user's current set values in MediumBot.py to display in the fields.
    """

    lines = [line.rstrip('\n') for line in open(FILE_PATH)]
    charsToRemove = ["'", "[", "]", '"']
    mediumBotVariables = {}
    atStartOfVariables = False

    for line in lines:

        if not atStartOfVariables and "=" in line:
            atStartOfVariables = True
        elif atStartOfVariables and "=" not in line:
            break

        if atStartOfVariables:

            mediumBotVar = line.split(" = ")
            for charToRemove in charsToRemove:
                mediumBotVar[1] = mediumBotVar[1].replace(charToRemove,"")

            mediumBotVariables[mediumBotVar[0]] = mediumBotVar[1]

    return mediumBotVariables

def updateMediumBot():
    """
    Update the MediumBot with the values in the GUI. Called when the start buttton
    is clicked.
    """

    print "TODO"

def updateMediumBotVariable(variableToUpdate, value):
    """
    Update a variable in the MediumBot.py file.
    variableToUpdate: the variable that is being update in MediumBot.py.
    value: value to update the variable in MediumBot.py to.
    """

    fh, abs_path = mkstemp()
    with open(abs_path,'w') as newFile:

        with open(FILE_PATH) as oldFile:

            for line in oldFile:
                if variableToUpdate in line and " = " in line and "if" not in line and "elif" not in line:
                    newFile.write(variableToUpdate+" = "+value)
                else:
                    newFile.write(line)

    close(fh)
    remove(FILE_PATH)
    move(abs_path, FILE_PATH)

def main():
    """
    Set the gui's window size, initialize and launch
    """

    root = Tk()
    root.geometry("500x550+300+300")
    app = MediumBotGUI(root)
    root.mainloop()

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