<commit_before>"""
Main file for the LASubway Data Interpreter (LASDI)

TODO:
    - Implement DISS
    - Implement network file downloads
    - Implement file-path search on the "Metro Network" if a path is not found on file system
    - Implement local file path search within the metro directory **I now have doubts about this
"""

import os
import ntpath
#import urllib
from urllib.parse import urlparse, ParseResult

#Imports for compression/archive file interpreting:
import gzip
import bz2
import zipfile
import tarfile

class IndecipherableStringError(Exception):
    """Error when a string cannot be desciphered"""
    def __init__(self, message):
        super(IndecipherableStringError, self).__init__(message)

def data_interpreter(data_string, tmp_data_dump):
    """Generates a string(s) to pass to a station to be used as the input path(s)"""

    if os.path.isfile(data_string):
        comp_file = check_compression(data_string)
        if comp_file != None:
            return extract_compresson_files(comp_file, tmp_data_dump)

        elif tarfile.is_tarfile(data_string):
            return extract_tar_files(data_string, tmp_data_dump)
        elif data_string.endswith("_staion_input.sin"):
            return extract_sin_files(data_string)
        else:
            return data_string #This is where recursive calls end

    #TODO Implement Network downloads
    #TODO Implement automatic metro execution

    elif os.path.isdir(data_string):
        #if is_metro(data_string): TODO Implement please
        #    return run_metro(data_string)
        return extract_dir_files()

    else:
        raise IndecipherableStringError("Indecipherable string!!!")

def extract_sin_files(sin_path, out_directory):
    """
    Opens a Station Input File and returns a list of verified input strings
    (A Station file contains filepaths to other files. extention: .sin)
    """

    in_strings = []
    with open(sin_path, 'r') as sinfile:
        for line in sinfile:
            return data_interpreter(line, out_directory)

def extract_dir_files(dir_path, out_directory):
    """Opens a directory and returns a list of verified input strings"""

    for path in [os.path.join(dir_path, i) for i in os.listdir(dir_path)]:
        return data_interpreter(path, out_directory)

def extract_tar_files(tar_file, out_directory):
    """
    extracts all files in a tar archive
    """
    tar_name = ntpath.basename(tar_file)
    un_tar_path = os.path.join(tar_file, tar_name)
    tarfile.TarFile(tar_file)
    tarfile.extractall(out_directory)

    return data_interpreter(un_tar_path, out_directory)

def extract_zip_files(zip_file, out_directory):
    """
    extracts all files in a zip archive
    """
    zip_name = ntpath.basename(zip_file)
    un_tar_path = os.path.join(zip_file, zip_name)
    zipfile.TarFile(zip_file)
    zarfile.extractall(out_directory)

    return data_interpreter(un_tar_path, out_directory)

def extract_compresson_file(compression_file, out_directory):
    """
    Attempts to decompress a filepath
    Will pass higher file types to data_interpreter before returning
    """
    out_file_name = ntpath.basename(compression_file.path)
    out_file_name_path = os.path.join(out_directory, out_file_name)
    with open(out_file_name_path, 'w') as f:
        f.write(compression_file.decompress())
    return data_interpreter(out_file_name_path, out_directory)

def check_compression(filename):
    """
    Function that attempts to detect and compression type
    The code used was found at: http://stackoverflow.com/questions/13044562/python-mechanism-to-identify-compressed-file-type-and-uncompress
    """
    with file(filename, 'rb') as f:
        start_of_file = f.read(1024)
        f.seek(0)
        for cls in (BZ2File, GZFile):
            if cls.is_magic(start_of_file):
                return cls(f)

        return None

#Classes for file compression detection and decompression
class CompressedFile(object):
    magic_signature = None
    filetype = None
    default_extention = None

    def __init__(self, path):
        self.path = path
        self.accessor = self.open()

    def is_magic(self, file_start):
        return file_start.startswith(self.magic_signature)

    def decompress(self):
        raise NotImplementedError

class GZFile(CompressedFile):
    magic_signature = "\x1f\x8b\x08"
    filetype = "gzip"
    default_extention = ".gz"

    def decompress(self):
         with gzip.open(self.path, 'rb') as gfile:
             return gfile.read()

class BZ2File(CompressedFile):
    magic_signature = "\x42\x5a\x68"
    filetype = "bzip2"
    default_extention = ".bz2"

    def decompress(self, outpath):
        with bz2.open(self.path, 'rb') as bfile:
            return bfile.read()

def diss_interpreter(data_string):
    """Parses out filter statments denoted by `"""
    split_data = data_string.split('`')

class DataStatement(ParseResult):
    """"""
    def __init__(self, statement_string):
        """
        TODO:
            Parse out Data Filters before passing the string to urlparse
        """
        if (statement_string == "" or statement_string is None):
            raise Exception #TODO Create exception for this

        self.parameters = []
        parsed_statement = statement_string.split('`')
        parsed_data_string = urlparse(parsed_statement[0])
        super.__init__([getattr(parsed_data_string, field) for field in parsed_data_string._fields]) #TODO add user name and password info

    @staticmethod
    def _create_data_parameters(parameters):
        pass

    def is_local(self):
        """
        RETURNS TRUE: if self.path is the only field that is set (assuming that empty strings are caught)
        RETURNS FALSE: if other fields besides self.path are set
        TODO:
            this needs to be fully tested
        """

        if (self.scheme == ""
            and self.netloc == ""
            and self.params == ""
            and self.query == ""
            and self.fragment == ""):
            return True
        return False

class DISSSyntaxError(Exception):
    """Error thrown for bad DISS syntax"""
    def __init__(self, message):
        super(DISSSyntaxError, self).__init__(message)

class DISSParameterTypeError(Exception):
    """Error thrown when the Parameter type string is incorrect"""
    def __init__(self, message):
        super(DISSParameterTypeError, self).__init__(message)

#Data String Classes: #############################################

class BaseParameter(object):
    """Base parameter object"""
    def __init__(self, parameter_type, parameter_statement):
        self.parameter_statement = parameter_statement
        self.filter_type = filter_type

        #Check statement syntax
        if (self.parameter_statement.count != 3) or ((not self.parameter_statement.startswith('`')) and (not self.parameter_statement.endswith('`'))):
            raise DISSSyntaxError
        elif self.parse_parameter_statement()[0] != filter_type:
            raise DISSParameterTypeError

    def factory(parameter_type):
        """"""
        if (parameter_type == 're') or (parameter_type == 'regex'): return RegexFilter()
        if (parameter_type == 'r') or (parameter_type == 'range'): return RangeFilter()
        if (parameter_type == 'ru') or (parameter_type == 'range-unique'): return RangeUniqueFilter()
        if (parameter_type == 'e') or (parameter_type == 'extention'): return ExentionFilter()
        if (parameter_type == 's') or (parameter_type == 'substring'): return SubstringFilter()
        if (parameter_type == 'sin') or (parameter_type == 'station-in-file'): return SinFileParameter()
        if (parameter_type == 'rd') or (parameter_type == 'raw-delimiter'): return RawDelimiter()

        assert 0, "Bad parameter: " + parameter_type
    factory = staticmethod(factory)

    def parse_parameter_statement(self):
        """"""
        return self.parameter_statement.split('`')

    def parse_parameter_settings(self):
        """
        This method will parse out the settings defined after parameter type but in the parameter type field
        """
        pass

class RegexFilter(BaseParameter):
    """Parameter object that filters strings with a python regex"""
    def __init__(self, parameter_statement):
        super().__init__('re', parameter_statement)

class ExentionFilter(BaseParameter):
    """Parameter object that filters verified file paths by extention"""
    def __init__(self, parameter_statement):
        super().__init__('e', parameter_statement)

class SubstringFilter(BaseParameter):
    """Parameter object that filters all strings by substring inclusion"""
    def __init__(self, parameter_statement):
        super().__init__('s', parameter_statement)

class RangeFilter(BaseParameter):
    """Parameter object that filters out all files not in the specified range"""
    def __init__(self, parameter_statement):
        super().__init__('r', parameter_statement)

class RangeUniqueFilter(BaseParameter):
    """Parameter object that filters out all files not in the specified range but will throw error if not all number in range found"""
    def __init__(self, parameter_statement):
        super().__init__('ru', parameter_statement)

class SinFileParameter(BaseParameter):
    """"""
    def __init__(self, parameter_statement):
        super().__init__('sin', parameter_statement)

class RawDelimiter(BaseParameter):
    """"""
    def __init__(self, parameter_statement):
        super().__init__('rd', parameter_statement)

class LevelIntercept(BaseParameter):
    """"""
    def __init__(self, parameter_statement):
        super().__init__('L', parameter_statement)

if __name__ == '__main__':
    ################# TESTING ##################

    # Data Statement Parameter parsing tests
    #### Factory Test
    parameter_type = "r"
    print(type(BaseParameter.factory(parameter_type)))

    #### Basic parameter
    #### Compound parameter
    #### Multiple parameters

    # Full Data statement parsing tests

    # LASDI file path tests

    # LASDI Raw Data tests

    pass

<commit_msg>Added docstring comment to DataStatement<commit_after>"""
Main file for the LASubway Data Interpreter (LASDI)

TODO:
    - Implement DISS
    - Implement network file downloads
    - Implement file-path search on the "Metro Network" if a path is not found on file system
    - Implement local file path search within the metro directory **I now have doubts about this
"""

import os
import ntpath
#import urllib
from urllib.parse import urlparse, ParseResult

#Imports for compression/archive file interpreting:
import gzip
import bz2
import zipfile
import tarfile

class IndecipherableStringError(Exception):
    """Error when a string cannot be desciphered"""
    def __init__(self, message):
        super(IndecipherableStringError, self).__init__(message)

def data_interpreter(data_string, tmp_data_dump):
    """Generates a string(s) to pass to a station to be used as the input path(s)"""

    if os.path.isfile(data_string):
        comp_file = check_compression(data_string)
        if comp_file != None:
            return extract_compresson_files(comp_file, tmp_data_dump)

        elif tarfile.is_tarfile(data_string):
            return extract_tar_files(data_string, tmp_data_dump)
        elif data_string.endswith("_staion_input.sin"):
            return extract_sin_files(data_string)
        else:
            return data_string #This is where recursive calls end

    #TODO Implement Network downloads
    #TODO Implement automatic metro execution

    elif os.path.isdir(data_string):
        #if is_metro(data_string): TODO Implement please
        #    return run_metro(data_string)
        return extract_dir_files()

    else:
        raise IndecipherableStringError("Indecipherable string!!!")

def extract_sin_files(sin_path, out_directory):
    """
    Opens a Station Input File and returns a list of verified input strings
    (A Station file contains filepaths to other files. extention: .sin)
    """

    in_strings = []
    with open(sin_path, 'r') as sinfile:
        for line in sinfile:
            return data_interpreter(line, out_directory)

def extract_dir_files(dir_path, out_directory):
    """Opens a directory and returns a list of verified input strings"""

    for path in [os.path.join(dir_path, i) for i in os.listdir(dir_path)]:
        return data_interpreter(path, out_directory)

def extract_tar_files(tar_file, out_directory):
    """
    extracts all files in a tar archive
    """
    tar_name = ntpath.basename(tar_file)
    un_tar_path = os.path.join(tar_file, tar_name)
    tarfile.TarFile(tar_file)
    tarfile.extractall(out_directory)

    return data_interpreter(un_tar_path, out_directory)

def extract_zip_files(zip_file, out_directory):
    """
    extracts all files in a zip archive
    """
    zip_name = ntpath.basename(zip_file)
    un_tar_path = os.path.join(zip_file, zip_name)
    zipfile.TarFile(zip_file)
    zarfile.extractall(out_directory)

    return data_interpreter(un_tar_path, out_directory)

def extract_compresson_file(compression_file, out_directory):
    """
    Attempts to decompress a filepath
    Will pass higher file types to data_interpreter before returning
    """
    out_file_name = ntpath.basename(compression_file.path)
    out_file_name_path = os.path.join(out_directory, out_file_name)
    with open(out_file_name_path, 'w') as f:
        f.write(compression_file.decompress())
    return data_interpreter(out_file_name_path, out_directory)

def check_compression(filename):
    """
    Function that attempts to detect and compression type
    The code used was found at: http://stackoverflow.com/questions/13044562/python-mechanism-to-identify-compressed-file-type-and-uncompress
    """
    with file(filename, 'rb') as f:
        start_of_file = f.read(1024)
        f.seek(0)
        for cls in (BZ2File, GZFile):
            if cls.is_magic(start_of_file):
                return cls(f)

        return None

#Classes for file compression detection and decompression
class CompressedFile(object):
    magic_signature = None
    filetype = None
    default_extention = None

    def __init__(self, path):
        self.path = path
        self.accessor = self.open()

    def is_magic(self, file_start):
        return file_start.startswith(self.magic_signature)

    def decompress(self):
        raise NotImplementedError

class GZFile(CompressedFile):
    magic_signature = "\x1f\x8b\x08"
    filetype = "gzip"
    default_extention = ".gz"

    def decompress(self):
         with gzip.open(self.path, 'rb') as gfile:
             return gfile.read()

class BZ2File(CompressedFile):
    magic_signature = "\x42\x5a\x68"
    filetype = "bzip2"
    default_extention = ".bz2"

    def decompress(self, outpath):
        with bz2.open(self.path, 'rb') as bfile:
            return bfile.read()

def diss_interpreter(data_string):
    """Parses out filter statments denoted by `"""
    split_data = data_string.split('`')

class DataStatement(ParseResult):
    """
    This class will be used for parsing and operating a single data statement
    """
    def __init__(self, statement_string):
        """
        TODO:
            Parse out Data Filters before passing the string to urlparse
        """
        if (statement_string == "" or statement_string is None):
            raise Exception #TODO Create exception for this

        self.parameters = []
        parsed_statement = statement_string.split('`')
        parsed_data_string = urlparse(parsed_statement[0])
        super.__init__([getattr(parsed_data_string, field) for field in parsed_data_string._fields]) #TODO add user name and password info

    @staticmethod
    def _create_data_parameters(parameters):
        pass

    def is_local(self):
        """
        RETURNS TRUE: if self.path is the only field that is set (assuming that empty strings are caught)
        RETURNS FALSE: if other fields besides self.path are set
        TODO:
            this needs to be fully tested
        """

        if (self.scheme == ""
            and self.netloc == ""
            and self.params == ""
            and self.query == ""
            and self.fragment == ""):
            return True
        return False

class DISSSyntaxError(Exception):
    """Error thrown for bad DISS syntax"""
    def __init__(self, message):
        super(DISSSyntaxError, self).__init__(message)

class DISSParameterTypeError(Exception):
    """Error thrown when the Parameter type string is incorrect"""
    def __init__(self, message):
        super(DISSParameterTypeError, self).__init__(message)

#Data String Classes: #############################################

class BaseParameter(object):
    """Base parameter object"""
    def __init__(self, parameter_type, parameter_statement):
        self.parameter_statement = parameter_statement
        self.filter_type = filter_type

        #Check statement syntax
        if (self.parameter_statement.count != 3) or ((not self.parameter_statement.startswith('`')) and (not self.parameter_statement.endswith('`'))):
            raise DISSSyntaxError
        elif self.parse_parameter_statement()[0] != filter_type:
            raise DISSParameterTypeError

    def factory(parameter_type):
        """"""
        if (parameter_type == 're') or (parameter_type == 'regex'): return RegexFilter()
        if (parameter_type == 'r') or (parameter_type == 'range'): return RangeFilter()
        if (parameter_type == 'ru') or (parameter_type == 'range-unique'): return RangeUniqueFilter()
        if (parameter_type == 'e') or (parameter_type == 'extention'): return ExentionFilter()
        if (parameter_type == 's') or (parameter_type == 'substring'): return SubstringFilter()
        if (parameter_type == 'sin') or (parameter_type == 'station-in-file'): return SinFileParameter()
        if (parameter_type == 'rd') or (parameter_type == 'raw-delimiter'): return RawDelimiter()

        assert 0, "Bad parameter: " + parameter_type
    factory = staticmethod(factory)

    def parse_parameter_statement(self):
        """"""
        return self.parameter_statement.split('`')

    def parse_parameter_settings(self):
        """
        This method will parse out the settings defined after parameter type but in the parameter type field
        """
        pass

class RegexFilter(BaseParameter):
    """Parameter object that filters strings with a python regex"""
    def __init__(self, parameter_statement):
        super().__init__('re', parameter_statement)

class ExentionFilter(BaseParameter):
    """Parameter object that filters verified file paths by extention"""
    def __init__(self, parameter_statement):
        super().__init__('e', parameter_statement)

class SubstringFilter(BaseParameter):
    """Parameter object that filters all strings by substring inclusion"""
    def __init__(self, parameter_statement):
        super().__init__('s', parameter_statement)

class RangeFilter(BaseParameter):
    """Parameter object that filters out all files not in the specified range"""
    def __init__(self, parameter_statement):
        super().__init__('r', parameter_statement)

class RangeUniqueFilter(BaseParameter):
    """Parameter object that filters out all files not in the specified range but will throw error if not all number in range found"""
    def __init__(self, parameter_statement):
        super().__init__('ru', parameter_statement)

class SinFileParameter(BaseParameter):
    """"""
    def __init__(self, parameter_statement):
        super().__init__('sin', parameter_statement)

class RawDelimiter(BaseParameter):
    """"""
    def __init__(self, parameter_statement):
        super().__init__('rd', parameter_statement)

class LevelIntercept(BaseParameter):
    """"""
    def __init__(self, parameter_statement):
        super().__init__('L', parameter_statement)

if __name__ == '__main__':
    ################# TESTING ##################

    # Data Statement Parameter parsing tests
    #### Factory Test
    parameter_type = "r"
    print(type(BaseParameter.factory(parameter_type)))

    #### Basic parameter
    #### Compound parameter
    #### Multiple parameters

    # Full Data statement parsing tests

    # LASDI file path tests

    # LASDI Raw Data tests

    pass

<|endoftext|>


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

import csv
import random

# Files are written to the 'output' directory.

# Worth pointing out that this script expects there to
# be a number of both experienced and inexperienced
# players that can be split evenly across teams.

# Also, this currently stores players in a player_dict
# with names for keys. If a new list with two players
# who have the same name is used, one of them will
# get overwritten. Because this script is written
# specifically for the test file I'm leaving it
# like that.

if __name__ == "__main__":

    player_dict = {}
    teams = {
    	'Sharks': {
    		'players': []
    	},
    	'Dragons': {
    		'players': []
    	},
    	'Raptors': {
    		'players': []
    	}
    }

    def load_players():
        with open('soccer_players.csv', 'r') as csv_file:
            csv_data = csv.DictReader(csv_file)
            for row in csv_data:
                player_dict[row['Name']] = {
                    'height': row['Height (inches)'],
                    'experience': row['Soccer Experience'],
                    'guardian': row['Guardian Name(s)']
                }

    def players_who_have_experience(do_they_have_it):
        return_list = []
        for player_name, player_data in player_dict.items():
        	if player_data['experience'] == do_they_have_it:
        		return_list.append(player_name)
        return return_list

    def put_players_on_team_randomly(player_list):
        while len(player_list):
        	for team_key, team_data in teams.items():
        		if len(player_list):
        		    team_data['players'].append(player_list.pop(random.randint(0,len(player_list) - 1)))

    def output_team_file():
        with open('output/teams.txt', 'w') as teams_file:
            for team_key, team_data in teams.items():
                teams_file.write(team_key + '\n')
            	for player in team_data['players']:
            		teams_file.write('{}, {}'.format(player, player_dict[player]['experience']) + '\n')

    load_players()
    experienced_players = players_who_have_experience('YES')
    inexperienced_players = players_who_have_experience('NO')

    put_players_on_team_randomly(experienced_players)
    put_players_on_team_randomly(inexperienced_players)

    print(teams)
    output_team_file()
<commit_msg>Refactored to remove temporary variables.<commit_after>#!/usr/bin/env python

import csv
import random

# Files are written to the 'output' directory.

# Worth pointing out that this script expects there to
# be a number of both experienced and inexperienced
# players that can be split evenly across teams.

# Also, this currently stores players in a player_dict
# with names for keys. If a new list with two players
# who have the same name is used, one of them will
# get overwritten. Because this script is written
# specifically for the test file I'm leaving it
# like that.

if __name__ == "__main__":

    player_dict = {}
    teams = {
    	'Sharks': {
    		'players': []
    	},
    	'Dragons': {
    		'players': []
    	},
    	'Raptors': {
    		'players': []
    	}
    }

    def load_players():
        with open('soccer_players.csv', 'r') as csv_file:
            csv_data = csv.DictReader(csv_file)
            for row in csv_data:
                player_dict[row['Name']] = {
                    'height': row['Height (inches)'],
                    'experience': row['Soccer Experience'],
                    'guardian': row['Guardian Name(s)']
                }

    def players_who_have_experience(do_they_have_it):
        return_list = []
        for player_name, player_data in player_dict.items():
        	if player_data['experience'] == do_they_have_it:
        		return_list.append(player_name)
        return return_list

    def put_players_on_team_randomly(player_list):
        while len(player_list):
        	for team_key, team_data in teams.items():
        		if len(player_list):
        		    team_data['players'].append(player_list.pop(random.randint(0,len(player_list) - 1)))

    def output_team_file():
        with open('output/teams.txt', 'w') as teams_file:
            for team_key, team_data in teams.items():
                teams_file.write(team_key + '\n')
            	for player in team_data['players']:
            		teams_file.write('{}, {}'.format(player, player_dict[player]['experience']) + '\n')

    load_players()

    put_players_on_team_randomly(players_who_have_experience('YES'))
    put_players_on_team_randomly(players_who_have_experience('NO'))

    print(teams)
    output_team_file()
<|endoftext|>


<commit_before>import random
import math
import maincore as mc
import os
import importlib
import pickle
from room import *
import item
from entity import *

rpgPrefix = "%" #The prefix used for RPG commands
helptext = "If you are seeing this, panic!" #Define the helptext variable that will be overwritten later

rooms = [Room("This room contains all the noobs who just started")]
playerlist = {}

deadCMD = ["help", "respawn", "reset", "sub", "notify", "sudo", "about"]
joinCMD = ["help", "join", "sub", "unsub", "notify", "sudo", "about"]

f = []
for (dirpath, dirnames, filenames) in os.walk('./actions'): #get every file in the actions folder
    f.extend(filenames) #and add them to this list
    break

py_files = filter(lambda x: os.path.splitext(x)[1] == '.py', f) #get all the .py files
module_names = list(map(lambda x: os.path.splitext(x)[0], py_files))

commands = {}
alias = {}
for m in module_names:
    commands[m] = importlib.import_module('actions.' + m) #Create a dictionary of commands and import them all

print("basic.py was silently loaded in a module")

def ready():
    global rooms
    global playerlist
    global alias
##    with open('important/playerlist.txt', 'rb') as f:
##        pickle.dump(playerlist, f)
##    with open('important/rooms.txt', 'rb') as f:
##        pickle.dump(rooms, f)
    with open('important/rooms.txt', 'xb') as f: #open the file named fileName
        rooms = pickle.loads(f.read()) #unpickle the stats file
    with open('important/playerlist.txt', 'xb') as f: #open the file named fileName
        playerlist = pickle.loads(f.read()) #unpickle the stats file
    print(rooms)
    print(playerlist)
    for n in module_names:
        for m in commands[n].alias():
            alias[m] = n
    print(alias)
    print("basic.py rpg module loaded")
    print("RPG prefix is " + rpgPrefix)
    cache_help() #update the %help file
    print(helptext)

def get_helptext():
    return helptext #return the helptext for in case other commands need to use it

def cache_help():
    ###Compile the helptext and put it into a variable to save processing power when it is needed later
    ###a.k.a "cache" the helptext into a variable
    global helptext
    clist = commands.keys() #get all the command names from the command dictionary
    ft = ""
    ftn = ""
    found = False
    for i in range(11): #cycle through all the permission levels. This orders the command nicely
        found = False #this will stay false if nothing is found in this permission level cycle
        ftn = ""
        for y in clist:
            if commands[y].help_perms() == i: #if the command permission level matches the current permission level that is being cycled
                part1 = commands[y].help_cmd(rpgPrefix) #fetch that command's command syntax
                part2 = commands[y].help_list() #fetch that command's breif description
                ftn = ftn + part1 + " :: " + part2 + "\n" #put those two into one line added onto the previously already found help
                found = True #say that something was found in this permission level cycle
        if found: #only if something was found in that permission level (to avoid lots of empty permission headers
            ft = ft + "== THE FOLLOWING COMMANDS NEED PERMISSION LEVEL " + str(i) + " OR BETTER ==\n" + ftn
        else:
            ft = ft + ftn

    ft = "```asciidoc\n" + ft + "\n```" #put the text into an asciidoc codeblock to get colors
    helptext = ft #save the helptext to variable

def compose_help(cSearch):
    ###compose help for a specific command
    usage1 = "Usage:\n"
    usage2 = commands[cSearch].help_cmd(rpgPrefix) + "\n" #get that command's command syntax
    usage3 = commands[cSearch].help_use() + "\n" #get that command's (longer) explanation
    paramGet = commands[cSearch].help_param() #get that command's parameters
    if paramGet == None: #If the command takes no parameters
        usage4 = "No parameters required\n"
    else:
        usage4 = paramGet + "\n"
    part5 = mc.perm_name(commands[cSearch].help_perms()) #Get the permission level (name) needed for that command
    part6 = str(commands[cSearch].help_perms()) #Get the permission level needed for that command
    usage5 = "You need the " + part5 + " (" + part6 + ") permission level or better to run this command"
    return "```\n" + usage1 + usage2 + usage3 + usage4 + usage5 + "\n```" #put all the previous data together and return it

def sub(author, add):
    with open('important/sub.txt', 'x') as f:
        lines = [line.rstrip('\n') for line in f] #remove all the \n from the end of lines

    print(lines)

    if add:
        if author.id not in lines:
            lines.append(author.id)
            with open('important/sub.txt', 'w') as f:
                for s in lines:
                    f.write(str(s) + "\n")
            return "subscribed!"

        else:
            return "already subscribed!"
    else:
        if author.id in lines:
            lines.remove(author.id)
            with open('important/sub.txt', 'w') as f:
                for s in lines:
                    f.write(str(s) + "\n")
            return "unsubscribed!"
        else:
            return "you arent subscribed!"

def return_itemlist():
    return item.get_itemlist()

def return_pools():
    return item.get_pools()

def scavenge(tp):
    items = item.get_itemlist()
    pools = item.get_pools()
    target = pools[tp]
    fItem = item.rweight(target)
    if fItem == None:
        return None
    gItem = items[fItem]
    newItem = item.Item(gItem)
    return newItem

def ping():
    sm = ""
    with open('important/sub.txt', 'x') as f:
        lines = [line.rstrip('\n') for line in f] #remove all the \n from the end of lines

    print(lines)
    for i in lines:
        sm = sm + "<@" + i + ">, "

    return sm

def default_stats():
    defaultStats = {'maxhealth': 40,
                    'health': 40,
                    'attack': 5,
                    'speed': 3,
                    'defense': 3,
                    'luck': 3,
                    'stat': 0,
                    'location': 0,
                    'furthest': 0,
                    'statpoints': 20,
                    'tongue': 0,
                    'torso': 0,
                    'legs': 0,
                    'weapon': 0,
                    'ring1': 0,
                    'ring2': 0}

    return defaultStats

def parse_status(status):
    ###Convert the base 10 representation of the status into a list of booleans
    binaryStatus = "{0:08b}".format(status) #Convert base 10 to base 2
    binaryList = list(binaryStatus) #Convert binary number into a binary list
    booleanList = [bool(int(x)) for x in binaryList] #Convert binary list into a boolean list
    return booleanList #Return the boolean list
    ###Status boolean list explanation
    ###length: 8
    ###element 0; PVP status - True if the player has opted in to get random attacks

def compile_status(booleanList):
    ###Convert the binary list representation of the status into a base 10 int
    binaryList = [str(int(x)) for x in booleanList] #Covert boolean list into binary list
    binaryStatus = "".join(binaryList) #Convert binary list into binary string
    decimalStatus = int(binaryStatus, 2) #convert binary string into base 10 int
    return decimalStatus #Return the base 10 representation of

def add_playerlist(pid, value):
    global playerlist
    playerlist[pid] = Entity(value)
    with open('important/playerlist.txt', 'wb') as f:
        pickle.dump(playerlist, f)

def get_playerlist():
    return playerlist

def save_playerlist():
    global playerlist
    with open('important/playerlist.txt', 'wb') as f:
        pickle.dump(playerlist, f)

def new_playerlist(playerlistnew):
    global playerlist
    playerlist = playerlistnew
    with open('important/playerlist.txt', 'wb') as f:
        pickle.dump(playerlistnew, f)

def run(message):
    toreturn = None
    cmdpart = "help"
    canPlay = True
    spaceloc = message.content.find(" ")
    if spaceloc == -1:
        cmdpart = message.content
    else:
        cmdpart = message.content[:spaceloc].strip()
    rprefix = len(rpgPrefix)
    cmdpart = cmdpart[rprefix:]
    print(cmdpart)
    print(commands.keys())
    if cmdpart.lower() in alias:
        cmdoriginal = cmdpart
        cmdpart = alias[cmdpart]
        runPerms = commands[cmdpart].help_perms()
        userPerms = mc.perm_get(message.author.id)
        hasFile = message.author.id in playerlist
        isDead = False
        canPlay = False
        if hasFile:
            print(playerlist[message.author.id].stats)
            sEnt = playerlist[message.author.id]
            isDead = sEnt.prop.get('dead', False)
            print(isDead)
            if isDead:
               if cmdpart in deadCMD:
                    canPlay = True
               else:
                    canPlay = False
            else:
                canPlay = True
        else:
            if cmdpart in joinCMD:
                canPlay = True
            else:
                canPlay = False
        if canPlay:
            if userPerms >= runPerms:
            #if userPerms == 10:
                toreturn = commands[cmdpart].run(message, rpgPrefix, cmdoriginal)
            else:
                toreturn = "m", [message.channel, "Oops! You do not have the permissions to run this command. You need " + mc.perm_name(runPerms) + " (" + str(runPerms) + ") or better. You have " + mc.perm_name(userPerms) + " (" + str(userPerms) + ")"]
                #toreturn = "m", [message.channel, "Bot is in lockdown mode"]
        elif isDead:
            toreturn = "m", [message.channel, "You are dead! Use %respawn to start from square one, with your stats, or\nUse %reset to completely restart everything, losing ***__ALL__*** of your progress"]
        else:
            toreturn = "m", [message.channel, "Oops! You haven't joined the game. Use %join to join in on the fun"]

        print(toreturn)
        return toreturn
    else:
        return "m", [message.channel, "Command not found"]
<commit_msg>wrong mode<commit_after>import random
import math
import maincore as mc
import os
import importlib
import pickle
from room import *
import item
from entity import *

rpgPrefix = "%" #The prefix used for RPG commands
helptext = "If you are seeing this, panic!" #Define the helptext variable that will be overwritten later

rooms = [Room("This room contains all the noobs who just started")]
playerlist = {}

deadCMD = ["help", "respawn", "reset", "sub", "notify", "sudo", "about"]
joinCMD = ["help", "join", "sub", "unsub", "notify", "sudo", "about"]

f = []
for (dirpath, dirnames, filenames) in os.walk('./actions'): #get every file in the actions folder
    f.extend(filenames) #and add them to this list
    break

py_files = filter(lambda x: os.path.splitext(x)[1] == '.py', f) #get all the .py files
module_names = list(map(lambda x: os.path.splitext(x)[0], py_files))

commands = {}
alias = {}
for m in module_names:
    commands[m] = importlib.import_module('actions.' + m) #Create a dictionary of commands and import them all

print("basic.py was silently loaded in a module")

def ready():
    global rooms
    global playerlist
    global alias
##    with open('important/playerlist.txt', 'wb') as f:
##        pickle.dump(playerlist, f)
##    with open('important/rooms.txt', 'wb') as f:
##        pickle.dump(rooms, f)
    with open('important/rooms.txt', 'xb') as f: #open the file named fileName
        rooms = pickle.loads(f.read()) #unpickle the stats file
    with open('important/playerlist.txt', 'xb') as f: #open the file named fileName
        playerlist = pickle.loads(f.read()) #unpickle the stats file
    print(rooms)
    print(playerlist)
    for n in module_names:
        for m in commands[n].alias():
            alias[m] = n
    print(alias)
    print("basic.py rpg module loaded")
    print("RPG prefix is " + rpgPrefix)
    cache_help() #update the %help file
    print(helptext)

def get_helptext():
    return helptext #return the helptext for in case other commands need to use it

def cache_help():
    ###Compile the helptext and put it into a variable to save processing power when it is needed later
    ###a.k.a "cache" the helptext into a variable
    global helptext
    clist = commands.keys() #get all the command names from the command dictionary
    ft = ""
    ftn = ""
    found = False
    for i in range(11): #cycle through all the permission levels. This orders the command nicely
        found = False #this will stay false if nothing is found in this permission level cycle
        ftn = ""
        for y in clist:
            if commands[y].help_perms() == i: #if the command permission level matches the current permission level that is being cycled
                part1 = commands[y].help_cmd(rpgPrefix) #fetch that command's command syntax
                part2 = commands[y].help_list() #fetch that command's breif description
                ftn = ftn + part1 + " :: " + part2 + "\n" #put those two into one line added onto the previously already found help
                found = True #say that something was found in this permission level cycle
        if found: #only if something was found in that permission level (to avoid lots of empty permission headers
            ft = ft + "== THE FOLLOWING COMMANDS NEED PERMISSION LEVEL " + str(i) + " OR BETTER ==\n" + ftn
        else:
            ft = ft + ftn

    ft = "```asciidoc\n" + ft + "\n```" #put the text into an asciidoc codeblock to get colors
    helptext = ft #save the helptext to variable

def compose_help(cSearch):
    ###compose help for a specific command
    usage1 = "Usage:\n"
    usage2 = commands[cSearch].help_cmd(rpgPrefix) + "\n" #get that command's command syntax
    usage3 = commands[cSearch].help_use() + "\n" #get that command's (longer) explanation
    paramGet = commands[cSearch].help_param() #get that command's parameters
    if paramGet == None: #If the command takes no parameters
        usage4 = "No parameters required\n"
    else:
        usage4 = paramGet + "\n"
    part5 = mc.perm_name(commands[cSearch].help_perms()) #Get the permission level (name) needed for that command
    part6 = str(commands[cSearch].help_perms()) #Get the permission level needed for that command
    usage5 = "You need the " + part5 + " (" + part6 + ") permission level or better to run this command"
    return "```\n" + usage1 + usage2 + usage3 + usage4 + usage5 + "\n```" #put all the previous data together and return it

def sub(author, add):
    with open('important/sub.txt', 'x') as f:
        lines = [line.rstrip('\n') for line in f] #remove all the \n from the end of lines

    print(lines)

    if add:
        if author.id not in lines:
            lines.append(author.id)
            with open('important/sub.txt', 'w') as f:
                for s in lines:
                    f.write(str(s) + "\n")
            return "subscribed!"

        else:
            return "already subscribed!"
    else:
        if author.id in lines:
            lines.remove(author.id)
            with open('important/sub.txt', 'w') as f:
                for s in lines:
                    f.write(str(s) + "\n")
            return "unsubscribed!"
        else:
            return "you arent subscribed!"

def return_itemlist():
    return item.get_itemlist()

def return_pools():
    return item.get_pools()

def scavenge(tp):
    items = item.get_itemlist()
    pools = item.get_pools()
    target = pools[tp]
    fItem = item.rweight(target)
    if fItem == None:
        return None
    gItem = items[fItem]
    newItem = item.Item(gItem)
    return newItem

def ping():
    sm = ""
    with open('important/sub.txt', 'x') as f:
        lines = [line.rstrip('\n') for line in f] #remove all the \n from the end of lines

    print(lines)
    for i in lines:
        sm = sm + "<@" + i + ">, "

    return sm

def default_stats():
    defaultStats = {'maxhealth': 40,
                    'health': 40,
                    'attack': 5,
                    'speed': 3,
                    'defense': 3,
                    'luck': 3,
                    'stat': 0,
                    'location': 0,
                    'furthest': 0,
                    'statpoints': 20,
                    'tongue': 0,
                    'torso': 0,
                    'legs': 0,
                    'weapon': 0,
                    'ring1': 0,
                    'ring2': 0}

    return defaultStats

def parse_status(status):
    ###Convert the base 10 representation of the status into a list of booleans
    binaryStatus = "{0:08b}".format(status) #Convert base 10 to base 2
    binaryList = list(binaryStatus) #Convert binary number into a binary list
    booleanList = [bool(int(x)) for x in binaryList] #Convert binary list into a boolean list
    return booleanList #Return the boolean list
    ###Status boolean list explanation
    ###length: 8
    ###element 0; PVP status - True if the player has opted in to get random attacks

def compile_status(booleanList):
    ###Convert the binary list representation of the status into a base 10 int
    binaryList = [str(int(x)) for x in booleanList] #Covert boolean list into binary list
    binaryStatus = "".join(binaryList) #Convert binary list into binary string
    decimalStatus = int(binaryStatus, 2) #convert binary string into base 10 int
    return decimalStatus #Return the base 10 representation of

def add_playerlist(pid, value):
    global playerlist
    playerlist[pid] = Entity(value)
    with open('important/playerlist.txt', 'wb') as f:
        pickle.dump(playerlist, f)

def get_playerlist():
    return playerlist

def save_playerlist():
    global playerlist
    with open('important/playerlist.txt', 'wb') as f:
        pickle.dump(playerlist, f)

def new_playerlist(playerlistnew):
    global playerlist
    playerlist = playerlistnew
    with open('important/playerlist.txt', 'wb') as f:
        pickle.dump(playerlistnew, f)

def run(message):
    toreturn = None
    cmdpart = "help"
    canPlay = True
    spaceloc = message.content.find(" ")
    if spaceloc == -1:
        cmdpart = message.content
    else:
        cmdpart = message.content[:spaceloc].strip()
    rprefix = len(rpgPrefix)
    cmdpart = cmdpart[rprefix:]
    print(cmdpart)
    print(commands.keys())
    if cmdpart.lower() in alias:
        cmdoriginal = cmdpart
        cmdpart = alias[cmdpart]
        runPerms = commands[cmdpart].help_perms()
        userPerms = mc.perm_get(message.author.id)
        hasFile = message.author.id in playerlist
        isDead = False
        canPlay = False
        if hasFile:
            print(playerlist[message.author.id].stats)
            sEnt = playerlist[message.author.id]
            isDead = sEnt.prop.get('dead', False)
            print(isDead)
            if isDead:
               if cmdpart in deadCMD:
                    canPlay = True
               else:
                    canPlay = False
            else:
                canPlay = True
        else:
            if cmdpart in joinCMD:
                canPlay = True
            else:
                canPlay = False
        if canPlay:
            if userPerms >= runPerms:
            #if userPerms == 10:
                toreturn = commands[cmdpart].run(message, rpgPrefix, cmdoriginal)
            else:
                toreturn = "m", [message.channel, "Oops! You do not have the permissions to run this command. You need " + mc.perm_name(runPerms) + " (" + str(runPerms) + ") or better. You have " + mc.perm_name(userPerms) + " (" + str(userPerms) + ")"]
                #toreturn = "m", [message.channel, "Bot is in lockdown mode"]
        elif isDead:
            toreturn = "m", [message.channel, "You are dead! Use %respawn to start from square one, with your stats, or\nUse %reset to completely restart everything, losing ***__ALL__*** of your progress"]
        else:
            toreturn = "m", [message.channel, "Oops! You haven't joined the game. Use %join to join in on the fun"]

        print(toreturn)
        return toreturn
    else:
        return "m", [message.channel, "Command not found"]
<|endoftext|>


<commit_before>#!python3

###############################################################################
# Copyright (c) 2013 Evgeny Proydakov <lord.tiran@gmail.com>
###############################################################################
# -*- coding: utf-8 -*-
###############################################################################

import sys
import utils
import re

# compate type
COMPARE_FULL   = 'FULL'
COMPARE_TRACE  = 'TRACE'
COMPARE_RESULT = 'RESULT'

def cmp(a, b):
    return (a > b) - (a < b)

def _read_result_data(name):
    file_data_temp = open(name, 'r', encoding = 'utf-8').readlines()
    utils.cut_slash(file_data_temp)

    file_data = []

    push = False
    for line in file_data_temp:
        if (push):
            line = re.sub(r'(\s+)Медиана:\s+(\S+)', r'\1(Медиана:)\2', line)
            file_data.append(line)
        if (line.find('BExpCalcCounter') != -1):
            push = True

    return file_data

def _read_trace_data(name):
    file_data_temp = open(name, 'r', encoding = 'utf-8').readlines()
    utils.cut_slash(file_data_temp)

    file_data = []

    push = False
    for line in file_data_temp:
        if (push):
            line = re.sub(r'SES\s+(\S+)\s(\S+)\s(\S+)', r'SES \1', line)
            line = re.sub(r'DPS_TM\s(\S+)(\s+)(\S+)(\s+)(\S+)', r'DPS_TM', line)
            line = re.sub(r'DPS_ME\s(\S+)(\s+)(\S+)(\s+)(\S+)', r'DPS_ME', line)
            line = re.sub(r'DPS_MM\s(\S+)', r'DPS_MM', line)
            file_data.append(line)

        if (line.find('$Changes') != -1):
            push = True

    return file_data

def full(file1, file2):
    file1_data = open(file1, 'r', encoding = 'utf-8').readlines()
    file2_data = open(file2, 'r', encoding = 'utf-8').readlines()

    utils.cut_slash(file1_data)
    utils.cut_slash(file2_data)

    if cmp(file1_data, file2_data) == 0:
        return True

    return False

def result(file1, file2):
    file1_data = _read_result_data(file1)
    file2_data = _read_result_data(file2)

    if cmp(file1_data, file2_data) == 0:
        return True

    return False

def trace(file1, file2):
    file1_data = _read_trace_data(file1)
    file2_data = _read_trace_data(file2)

    if cmp(file1_data, file2_data) == 0:
        return True

    return False

def files(file1, file2, type):
    if   type == COMPARE_FULL:
        return full(file1, file2)
    elif type == COMPARE_TRACE:
        return trace(file1, file2)
    elif type == COMPARE_RESULT:
        return result(file1, file2)

    return False

if __name__ == '__main__':

    utils.enc_print (str(files('game5.trc', 'game5_etalon.trc', COMPARE_TRACE)))
<commit_msg> - медиана не учавствует в сравнении<commit_after>#!python3

###############################################################################
# Copyright (c) 2013 Evgeny Proydakov <lord.tiran@gmail.com>
###############################################################################
# -*- coding: utf-8 -*-
###############################################################################

import sys
import utils
import re

# compate type
COMPARE_FULL   = 'FULL'
COMPARE_TRACE  = 'TRACE'
COMPARE_RESULT = 'RESULT'

def cmp(a, b):
    return (a > b) - (a < b)

def _read_result_data(name):
    file_data_temp = open(name, 'r', encoding = 'utf-8').readlines()
    utils.cut_slash(file_data_temp)

    file_data = []

    push = False
    for line in file_data_temp:
        if (push):
            line = re.sub(r'(\.+)Медиана:\s+(\S+)', r'\1(Медиана:)\2', line)
            file_data.append(line)
        if (line.find('BExpCalcCounter') != -1):
            push = True

    return file_data

def _read_trace_data(name):
    file_data_temp = open(name, 'r', encoding = 'utf-8').readlines()
    utils.cut_slash(file_data_temp)

    file_data = []

    push = False
    for line in file_data_temp:
        if (push):
            line = re.sub(r'SES\s+(\S+)\s(\S+)\s(\S+)', r'SES \1', line)
            line = re.sub(r'DPS_TM\s(\S+)(\s+)(\S+)(\s+)(\S+)', r'DPS_TM', line)
            line = re.sub(r'DPS_ME\s(\S+)(\s+)(\S+)(\s+)(\S+)', r'DPS_ME', line)
            line = re.sub(r'DPS_MM\s(\S+)', r'DPS_MM', line)
            file_data.append(line)

        if (line.find('$Changes') != -1):
            push = True

    return file_data

def full(file1, file2):
    file1_data = open(file1, 'r', encoding = 'utf-8').readlines()
    file2_data = open(file2, 'r', encoding = 'utf-8').readlines()

    utils.cut_slash(file1_data)
    utils.cut_slash(file2_data)

    if cmp(file1_data, file2_data) == 0:
        return True

    return False

def result(file1, file2):
    file1_data = _read_result_data(file1)
    file2_data = _read_result_data(file2)

    if cmp(file1_data, file2_data) == 0:
        return True

    return False

def trace(file1, file2):
    file1_data = _read_trace_data(file1)
    file2_data = _read_trace_data(file2)

    if cmp(file1_data, file2_data) == 0:
        return True

    return False

def files(file1, file2, type):
    if   type == COMPARE_FULL:
        return full(file1, file2)
    elif type == COMPARE_TRACE:
        return trace(file1, file2)
    elif type == COMPARE_RESULT:
        return result(file1, file2)

    return False

if __name__ == '__main__':

    utils.enc_print (str(files('game5.trc', 'game5_etalon.trc', COMPARE_TRACE)))
<|endoftext|>


<commit_before>from brutal.core.plugin import cmd, event, match
from brutal.core.utils import change_cmd
import re

@cmd
def ping(event):
    """Responds 'pong' to your 'ping'."""
    return 'pong'

@cmd
def echo(event):
    """Echoes back the message it recieves."""
    return ' '.join(event.args)

@cmd
def sudo(event):
    """Responds 'okay.' to your 'sudo ...' (http://xkcd.com/149/)."""
    return 'okay.'

@cmd
def make(event):
    """Tells user to go make it himself (http://xkcd.com/149/')."""
    return 'what? make it yourself.'

welcomes_db = {
    '#databazy': {
        "lordpotato":
            "Everybody on your knees and let's praise the mighty Potato!",
        "pepol": "Nazimod sighted, take cover!",
        "mrshu": "Hide yo codes, hide yo wife, nazireviewer is on site!",
        "jakubn": "Swiggidy swooty, he's comin' for dat booty!",
        "kalerab": "Hide your apples, 'cause he's gonna eat 'em!"
    }
}

@event
def auto_welcome(event):
    if event.event_type == 'join':
        if event.source_room in welcomes_db:
            welcomes = welcomes_db[event.source_room]
            # .lower() is a temporary fix for differences between lowercase
            # and uppercase name maching
            nick = event.meta['nick'].lower()

            if nick in welcomes:
                return welcomes[nick]
        return event.meta['nick'] + ': hi!'

# math functions need to be imported at runtime
from math import *  # NOQA
safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh',
             'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot',
             'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin',
             'sinh', 'sqrt', 'tan', 'tanh']
safe_dict = dict([(k, locals().get(k, None)) for k in safe_list])

# global builtin functions which are not in locals()
safe_dict['abs'] = abs
safe_dict['float'] = float
safe_dict['int'] = int

@cmd(command='eval')
def eval_(event):
    # the name eval_ is used in order to avoid clashing with the built-in eval
    # function which is actually how the eval command is implemented.

    """Evaluates user specified (mathematical) expression.

    Usage:

        !eval [input ...]

    Examples:

        !eval 5**2
        > 25
    """

    input = ' '.join(event.args)
    if len(input) < 1:
        return

    try:
        return eval(input, {"__builtins__": None}, safe_dict)
    except Exception as e:
        return "eval: {0}".format(e)

SED_REGEX = r'^s([^ a-zA-Z0-9])(.*?)\1(.*?)(?:\1(.+?|))?$'
last_events = {}

@event
def sub_event_catcher(event):
    if event.event_type in ['message', 'cmd']:
        last_events[event.meta['host']] = event

@match(regex=SED_REGEX)
def sub_match(event, sep, pattern, replacement, flags, *args, **kwargs):
    """Matches any substitute string (as sed would), applies this substitution to
    the user's last message and sends it back to processing."""

    host = event.meta['host']
    if host not in last_events:
        return

    if flags is None:
        flags = ''

    event = last_events[host]
    details = event.raw_details
    flag = 0
    count = 1
    if 'g' in flags:
        count = 0
    if 'i' in flags:
        flag = re.IGNORECASE

    pattern = re.escape(pattern)
    details['meta']['body'] = re.sub(pattern,
                                     replacement,
                                     details['meta']['body'],
                                     count,
                                     flag)

    evt = event.source_bot.build_event(details)
    event.source_bot.new_event(evt)
    return 'Reprocessing: {0}: {1}'.format(details['meta']['nick'],
                                           details['meta']['body'])

@cmd
def sub(event):
    """Applies the 'sed' substitution defined in its arguments to the user's
    last message and sends it back to processing."""

    arg = ' '.join(event.args)
    sed_args = re.match(SED_REGEX, arg)
    if sed_args is not None:
        return sub_match(event, *sed_args.groups())

@cmd
def r(event):
    """Reprocess the last command or message recieved by a bot."""
    host = event.meta['host']
    if host not in last_events:
        return

    event.source_bot.new_event(last_events[host])

@cmd
def redo(event):
    """Reprocess the last command or message recieved by a bot."""
    evt = change_cmd(event, 'r')
    event.source_bot.new_event(evt)
<commit_msg>basic: Fix for old versions of python re library<commit_after>from brutal.core.plugin import cmd, event, match
from brutal.core.utils import change_cmd
import re

@cmd
def ping(event):
    """Responds 'pong' to your 'ping'."""
    return 'pong'

@cmd
def echo(event):
    """Echoes back the message it recieves."""
    return ' '.join(event.args)

@cmd
def sudo(event):
    """Responds 'okay.' to your 'sudo ...' (http://xkcd.com/149/)."""
    return 'okay.'

@cmd
def make(event):
    """Tells user to go make it himself (http://xkcd.com/149/')."""
    return 'what? make it yourself.'

welcomes_db = {
    '#databazy': {
        "lordpotato":
            "Everybody on your knees and let's praise the mighty Potato!",
        "pepol": "Nazimod sighted, take cover!",
        "mrshu": "Hide yo codes, hide yo wife, nazireviewer is on site!",
        "jakubn": "Swiggidy swooty, he's comin' for dat booty!",
        "kalerab": "Hide your apples, 'cause he's gonna eat 'em!"
    }
}

@event
def auto_welcome(event):
    if event.event_type == 'join':
        if event.source_room in welcomes_db:
            welcomes = welcomes_db[event.source_room]
            # .lower() is a temporary fix for differences between lowercase
            # and uppercase name maching
            nick = event.meta['nick'].lower()

            if nick in welcomes:
                return welcomes[nick]
        return event.meta['nick'] + ': hi!'

# math functions need to be imported at runtime
from math import *  # NOQA
safe_list = ['acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh',
             'degrees', 'e', 'exp', 'fabs', 'floor', 'fmod', 'frexp', 'hypot',
             'ldexp', 'log', 'log10', 'modf', 'pi', 'pow', 'radians', 'sin',
             'sinh', 'sqrt', 'tan', 'tanh']
safe_dict = dict([(k, locals().get(k, None)) for k in safe_list])

# global builtin functions which are not in locals()
safe_dict['abs'] = abs
safe_dict['float'] = float
safe_dict['int'] = int

@cmd(command='eval')
def eval_(event):
    # the name eval_ is used in order to avoid clashing with the built-in eval
    # function which is actually how the eval command is implemented.

    """Evaluates user specified (mathematical) expression.

    Usage:

        !eval [input ...]

    Examples:

        !eval 5**2
        > 25
    """

    input = ' '.join(event.args)
    if len(input) < 1:
        return

    try:
        return eval(input, {"__builtins__": None}, safe_dict)
    except Exception as e:
        return "eval: {0}".format(e)

SED_REGEX = r'^s([^ a-zA-Z0-9])(.*?)\1(.*?)(?:\1$|\1([a-z]+)$|$)'
last_events = {}

@event
def sub_event_catcher(event):
    if event.event_type in ['message', 'cmd']:
        last_events[event.meta['host']] = event

@match(regex=SED_REGEX)
def sub_match(event, sep, pattern, replacement, flags, *args, **kwargs):
    """Matches any substitute string (as sed would), applies this substitution to
    the user's last message and sends it back to processing."""

    host = event.meta['host']
    if host not in last_events:
        return

    if flags is None:
        flags = ''

    event = last_events[host]
    details = event.raw_details
    flag = 0
    count = 1
    if 'g' in flags:
        count = 0
    if 'i' in flags:
        flag = re.IGNORECASE

    pattern = re.escape(pattern)
    details['meta']['body'] = re.sub(pattern,
                                     replacement,
                                     details['meta']['body'],
                                     count,
                                     flag)

    evt = event.source_bot.build_event(details)
    event.source_bot.new_event(evt)
    return 'Reprocessing: {0}: {1}'.format(details['meta']['nick'],
                                           details['meta']['body'])

@cmd
def sub(event):
    """Applies the 'sed' substitution defined in its arguments to the user's
    last message and sends it back to processing."""

    arg = ' '.join(event.args)
    sed_args = re.match(SED_REGEX, arg)
    if sed_args is not None:
        return sub_match(event, *sed_args.groups())

@cmd
def r(event):
    """Reprocess the last command or message recieved by a bot."""
    host = event.meta['host']
    if host not in last_events:
        return

    event.source_bot.new_event(last_events[host])

@cmd
def redo(event):
    """Reprocess the last command or message recieved by a bot."""
    evt = change_cmd(event, 'r')
    event.source_bot.new_event(evt)
<|endoftext|>


<commit_before>from datetime import datetime, timedelta
import json
import redis

#from flask import jsonify

import celery
from emails import send_email
from pytz import timezone
import requests
import stripe

from helpers import amount_to_charge

from salesforce import SalesforceConnection
from config import STRIPE_KEYS
from config import ACCOUNTING_MAIL_RECIPIENT
from config import TIMEZONE
from config import REDIS_URL

zone = timezone(TIMEZONE)

stripe.api_key = STRIPE_KEYS['secret_key']

class Log(object):
    """
    This encapulates sending to the console/stdout and email all in one.

    """
    def __init__(self):
        self.log = list()

    def it(self, string):
        """
        Add something to the log.
        """
        print(string)
        self.log.append(string)

    def send(self):
        """
        Send the assembled log out as an email.
        """
        body = '\n'.join(self.log)
        recipient = ACCOUNTING_MAIL_RECIPIENT
        subject = 'Batch run'
        send_email(body=body, recipient=recipient, subject=subject)

def process_charges(query, log):

    sf = SalesforceConnection()

    response = sf.query(query)
    # TODO: check response code

    log.it('Found {} opportunities available to process.'.format(
        len(response)))

    for item in response:

        amount = amount_to_charge(item)

        # salesforce connect
        path = item['attributes']['url']
        url = '{}{}'.format(sf.instance_url, path)

        if item['StageName'] == 'Pledged':
            try:

                log.it('---- Charging ${} to {} ({})'.format(amount / 100,
                    item['Stripe_Customer_ID__c'],
                    item['Name']))

                if item['Shipping_address_name__c'] != '':
                    shipping_address = {'line1' : item['Shipping_address_street__c'], 'city' : item['Shipping_address_city__c'], 'state' : item['Shipping_address_state__c'], 'postal_code' : item['Shipping_address_ZIP__c'], 'country' : item['Shipping_address_country__c']}
                    if shipping_address.get('line1'):
                        shipping_details = {'name' : item['Shipping_address_name__c'], 'address' : shipping_address}
                    else:
                        shipping_details = None
                else:
                    shipping_details = None

                charge_args = {
                    'customer': item['Stripe_Customer_ID__c'],
                    'amount': amount,
                    'currency': 'usd',
                    'description': item['Description'],
                    'metadata': {
                        'source': item['Referring_page__c']
                    },
                    'shipping': shipping_details
                }

                # if we know the source from the opportunity, use it
                # otherwise it will use the default on the Stripe customer
                # currently this just loads the token. not going to work.

                if item['Stripe_Card__c'] != '':
                    charge_source = item['Stripe_Card__c']
                    print('there is a card')
                elif item['Stripe_Bank_Account__c'] != '':
                    charge_source = item['Stripe_Bank_Account__c']
                    print('there is a bank')
                else:
                    charge_source = None
                    print('there is no charge')

                #charge = stripe.Charge.create(charge_args)

                charge = stripe.Charge.create(
                    customer=item['Stripe_Customer_ID__c'],
                    amount=amount,
                    currency='usd',
                    description=item['Description'],
                    metadata={'source': item['Referring_page__c']},
                    shipping=shipping_details,
                    source=charge_source
                )

            except stripe.error.CardError as e:
                # look for decline code:
                error = e.json_body['error']
                log.it('Error: The card has been declined:')
                log.it('\tStatus: {}'.format(e.http_status))
                log.it('\tType: {}'.format(error.get('type', '')))
                log.it('\tCode: {}'.format(error.get('code', '')))
                log.it('\tParam: {}'.format(error.get('param', '')))
                log.it('\tMessage: {}'.format(error.get('message', '')))
                log.it('\tDecline code: {}'.format(error.get('decline_code', '')))

                # charge was unsuccessful - change its salesforce status to Failed and store the error message
                update = {
                    'StageName': 'Failed',
                    'Stripe_Error_Message__c': "Error: {}".format(e)
                    }

                resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
                if resp.status_code == 204:
                    log.it('salesforce updated - charge failed')
                else:
                    log.it('error updating salesforce because status code was not 204')
                    raise Exception('error')

                continue

            except stripe.error.InvalidRequestError as e:
                log.it("Error: {}".format(e))
                update = {
                    'StageName': 'Failed',
                    'Stripe_Error_Message__c': "Error: {}".format(e)
                    }
                resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
                if resp.status_code == 204:
                    log.it('salesforce updated with invalidrequesterror - charge failed')
                else:
                    log.it('error updating salesforce because status code was not 204')
                    raise Exception('error')

                continue
            except Exception as e:
                log.it("Error: {}".format(e))
                update = {
                    'StageName': 'Failed',
                    'Stripe_Error_Message__c': "Error: {}".format(e)
                    }
                resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
                if resp.status_code == 204:
                    log.it('salesforce updated with generic exception - charge failed')
                else:
                    log.it('error updating salesforce because status code was not 204')
                    raise Exception('error')
                continue
        else:
            log.it('---- Checking transaction {} for status update.'.format(item['Stripe_Transaction_ID__c']))
            charge = stripe.Charge.retrieve(item['Stripe_Transaction_ID__c'])

        if charge.status != 'succeeded' and charge.status != 'pending':
            log.it("Error: Charge failed. Check Stripe logs.")
            update = {
                'StageName': 'Failed',
                'Stripe_Error_Message__c': "Error: Unknown. Check logs"
                }
            resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
            if resp.status_code == 204:
                log.it('salesforce updated - charge failed')
            else:
                log.it('error updating salesforce because status code was not 204')
                raise Exception('error')
            continue

        if charge.status == 'pending':
            log.it("ACH charge pending. Check daily to see if it processes.")
            update = {
                'Stripe_Transaction_Id__c': charge.id,
                #'Stripe_Bank_Account__c': charge.source.id,
                'StageName': 'ACH Pending',
                }
            resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
            if resp.status_code == 204:
                log.it('salesforce updated - charge is ach pending')
            else:
                log.it('error updating salesforce because status code was not 204')
                raise Exception('error')
            continue

        # charge was successful
        if charge.source.object != 'bank_account':
            update = {
                'Stripe_Transaction_Id__c': charge.id,
                #'Stripe_Card__c': charge.source.id,
                'Card_type__c': charge.source.brand,
                'Card_expiration_date__c': str(charge.source.exp_month) + ' / ' + str(charge.source.exp_year),
                'Card_acct_last_4__c': charge.source.last4,
                'StageName': 'Closed Won',
                }
        else:
            update = {
                #'Stripe_Transaction_Id__c': charge.id,
                #'Stripe_Bank_Account__c': charge.source.id,
                'StageName': 'Closed Won'
                }

        resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
        # TODO: check 'errors' and 'success' too
        if resp.status_code == 204:
            log.it('salesforce updated - charge succeeded')
        else:
            log.it('error updating salesforce because status code was not 204')
            raise Exception('error')

class AlreadyExecuting(Exception):
    """
    Here to show when more than one job of the same type is running.
    """
    pass

class Lock(object):
    """
    Claim an exclusive lock. Using Redis.
    """

    def __init__(self, key):
        self.key = key
        self.connection = redis.from_url(REDIS_URL)

    def acquire(self):
        if self.connection.get(self.key):
            raise AlreadyExecuting
        self.connection.setex(name=self.key, value='bar', time=1200)

    def release(self):
        self.connection.delete(self.key)

@celery.task()
def charge_cards():

    lock = Lock(key='charge-cards-lock')
    lock.acquire()

    log = Log()

    log.it('---Starting batch job...')

    three_days_ago = (datetime.now(tz=zone) - timedelta(
        days=3)).strftime('%Y-%m-%d')
    today = datetime.now(tz=zone).strftime('%Y-%m-%d')

    # regular (non Circle) pledges:
    log.it('---Processing regular charges...')

    query = """
        SELECT Amount, Name, Stripe_Customer_Id__c, Description, StageName, Stripe_Card__c, Stripe_Bank_Account__c,
            Stripe_Agreed_to_pay_fees__c, Referring_page__c, Shipping_address_name__c, Shipping_address_street__c,
            Shipping_address_city__c, Shipping_address_state__c, Shipping_address_ZIP__c, Shipping_address_country__c
        FROM Opportunity
        WHERE CloseDate <= {}
        AND CloseDate >= {}
        AND StageName = 'Pledged'
        AND Stripe_Customer_Id__c != ''
        """.format(today, three_days_ago)

    try:
        process_charges(query, log)
    finally:
        lock.release()

@celery.task()
def update_ach_charges():

    lock = Lock(key='update-ach-charges-lock')
    lock.acquire()

    log = Log()

    log.it('---Starting batch job...')

    #three_days_ago = (datetime.now(tz=zone) - timedelta(
    #    days=3)).strftime('%Y-%m-%d')
    #today = datetime.now(tz=zone).strftime('%Y-%m-%d')

    # regular (non Circle) pledges:
    log.it('---Checking for status changes on ACH charges...')

    query = """
        SELECT Stripe_Transaction_ID__c, Amount, Name, Stripe_Customer_Id__c, Description, StageName, Stripe_Card__c, Stripe_Bank_Account__c,
            Stripe_Agreed_to_pay_fees__c, Referring_page__c, Shipping_address_name__c, Shipping_address_street__c,
            Shipping_address_city__c, Shipping_address_state__c, Shipping_address_ZIP__c, Shipping_address_country__c
        FROM Opportunity
        WHERE StageName = 'ACH Pending'
        AND Stripe_Customer_Id__c != ''
        """

    try:
        process_charges(query, log)
    finally:
        lock.release()

if __name__ == '__main__':
    charge_cards()
<commit_msg>more debug<commit_after>from datetime import datetime, timedelta
import json
import redis

#from flask import jsonify

import celery
from emails import send_email
from pytz import timezone
import requests
import stripe

from helpers import amount_to_charge

from salesforce import SalesforceConnection
from config import STRIPE_KEYS
from config import ACCOUNTING_MAIL_RECIPIENT
from config import TIMEZONE
from config import REDIS_URL

zone = timezone(TIMEZONE)

stripe.api_key = STRIPE_KEYS['secret_key']

class Log(object):
    """
    This encapulates sending to the console/stdout and email all in one.

    """
    def __init__(self):
        self.log = list()

    def it(self, string):
        """
        Add something to the log.
        """
        print(string)
        self.log.append(string)

    def send(self):
        """
        Send the assembled log out as an email.
        """
        body = '\n'.join(self.log)
        recipient = ACCOUNTING_MAIL_RECIPIENT
        subject = 'Batch run'
        send_email(body=body, recipient=recipient, subject=subject)

def process_charges(query, log):

    sf = SalesforceConnection()

    response = sf.query(query)
    # TODO: check response code

    log.it('Found {} opportunities available to process.'.format(
        len(response)))

    for item in response:

        amount = amount_to_charge(item)

        # salesforce connect
        path = item['attributes']['url']
        url = '{}{}'.format(sf.instance_url, path)

        if item['StageName'] == 'Pledged':
            try:

                log.it('---- Charging ${} to {} ({})'.format(amount / 100,
                    item['Stripe_Customer_ID__c'],
                    item['Name']))

                if item['Shipping_address_name__c'] != '':
                    shipping_address = {'line1' : item['Shipping_address_street__c'], 'city' : item['Shipping_address_city__c'], 'state' : item['Shipping_address_state__c'], 'postal_code' : item['Shipping_address_ZIP__c'], 'country' : item['Shipping_address_country__c']}
                    if shipping_address.get('line1'):
                        shipping_details = {'name' : item['Shipping_address_name__c'], 'address' : shipping_address}
                    else:
                        shipping_details = None
                else:
                    shipping_details = None

                # if we know the source from the opportunity, use it
                # otherwise it will use the default on the Stripe customer
                # currently this just loads the token. not going to work.

                if item['Stripe_Card__c'] != '':
                    charge_source = item['Stripe_Card__c']
                    print('there is a card and it is {} so that is what to look for.' . item['Stripe_Card__c'])
                elif item['Stripe_Bank_Account__c'] != '':
                    charge_source = item['Stripe_Bank_Account__c']
                    print('there is a bank')
                else:
                    charge_source = None
                    print('there is no charge')

                #charge = stripe.Charge.create(charge_args)

                charge = stripe.Charge.create(
                    customer=item['Stripe_Customer_ID__c'],
                    amount=amount,
                    currency='usd',
                    description=item['Description'],
                    metadata={'source': item['Referring_page__c']},
                    shipping=shipping_details,
                    source=charge_source
                )

            except stripe.error.CardError as e:
                # look for decline code:
                error = e.json_body['error']
                log.it('Error: The card has been declined:')
                log.it('\tStatus: {}'.format(e.http_status))
                log.it('\tType: {}'.format(error.get('type', '')))
                log.it('\tCode: {}'.format(error.get('code', '')))
                log.it('\tParam: {}'.format(error.get('param', '')))
                log.it('\tMessage: {}'.format(error.get('message', '')))
                log.it('\tDecline code: {}'.format(error.get('decline_code', '')))

                # charge was unsuccessful - change its salesforce status to Failed and store the error message
                update = {
                    'StageName': 'Failed',
                    'Stripe_Error_Message__c': "Error: {}".format(e)
                    }

                resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
                if resp.status_code == 204:
                    log.it('salesforce updated - charge failed')
                else:
                    log.it('error updating salesforce because status code was not 204')
                    raise Exception('error')

                continue

            except stripe.error.InvalidRequestError as e:
                log.it("Error: {}".format(e))
                update = {
                    'StageName': 'Failed',
                    'Stripe_Error_Message__c': "Error: {}".format(e)
                    }
                resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
                if resp.status_code == 204:
                    log.it('salesforce updated with invalidrequesterror - charge failed')
                else:
                    log.it('error updating salesforce because status code was not 204')
                    raise Exception('error')

                continue
            except Exception as e:
                log.it("Error: {}".format(e))
                update = {
                    'StageName': 'Failed',
                    'Stripe_Error_Message__c': "Error: {}".format(e)
                    }
                resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
                if resp.status_code == 204:
                    log.it('salesforce updated with generic exception - charge failed')
                else:
                    log.it('error updating salesforce because status code was not 204')
                    raise Exception('error')
                continue
        else:
            log.it('---- Checking transaction {} for status update.'.format(item['Stripe_Transaction_ID__c']))
            charge = stripe.Charge.retrieve(item['Stripe_Transaction_ID__c'])

        if charge.status != 'succeeded' and charge.status != 'pending':
            log.it("Error: Charge failed. Check Stripe logs.")
            update = {
                'StageName': 'Failed',
                'Stripe_Error_Message__c': "Error: Unknown. Check logs"
                }
            resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
            if resp.status_code == 204:
                log.it('salesforce updated - charge failed')
            else:
                log.it('error updating salesforce because status code was not 204')
                raise Exception('error')
            continue

        if charge.status == 'pending':
            log.it("ACH charge pending. Check daily to see if it processes.")
            update = {
                'Stripe_Transaction_Id__c': charge.id,
                #'Stripe_Bank_Account__c': charge.source.id,
                'StageName': 'ACH Pending',
                }
            resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
            if resp.status_code == 204:
                log.it('salesforce updated - charge is ach pending')
            else:
                log.it('error updating salesforce because status code was not 204')
                raise Exception('error')
            continue

        # charge was successful
        if charge.source.object != 'bank_account':
            update = {
                'Stripe_Transaction_Id__c': charge.id,
                #'Stripe_Card__c': charge.source.id,
                'Card_type__c': charge.source.brand,
                'Card_expiration_date__c': str(charge.source.exp_month) + ' / ' + str(charge.source.exp_year),
                'Card_acct_last_4__c': charge.source.last4,
                'StageName': 'Closed Won',
                }
        else:
            update = {
                #'Stripe_Transaction_Id__c': charge.id,
                #'Stripe_Bank_Account__c': charge.source.id,
                'StageName': 'Closed Won'
                }

        resp = requests.patch(url, headers=sf.headers, data=json.dumps(update))
        # TODO: check 'errors' and 'success' too
        if resp.status_code == 204:
            log.it('salesforce updated - charge succeeded')
        else:
            log.it('error updating salesforce because status code was not 204')
            raise Exception('error')

class AlreadyExecuting(Exception):
    """
    Here to show when more than one job of the same type is running.
    """
    pass

class Lock(object):
    """
    Claim an exclusive lock. Using Redis.
    """

    def __init__(self, key):
        self.key = key
        self.connection = redis.from_url(REDIS_URL)

    def acquire(self):
        if self.connection.get(self.key):
            raise AlreadyExecuting
        self.connection.setex(name=self.key, value='bar', time=1200)

    def release(self):
        self.connection.delete(self.key)

@celery.task()
def charge_cards():

    lock = Lock(key='charge-cards-lock')
    lock.acquire()

    log = Log()

    log.it('---Starting batch job...')

    three_days_ago = (datetime.now(tz=zone) - timedelta(
        days=3)).strftime('%Y-%m-%d')
    today = datetime.now(tz=zone).strftime('%Y-%m-%d')

    # regular (non Circle) pledges:
    log.it('---Processing regular charges...')

    query = """
        SELECT Amount, Name, Stripe_Customer_Id__c, Description, StageName, Stripe_Card__c, Stripe_Bank_Account__c,
            Stripe_Agreed_to_pay_fees__c, Referring_page__c, Shipping_address_name__c, Shipping_address_street__c,
            Shipping_address_city__c, Shipping_address_state__c, Shipping_address_ZIP__c, Shipping_address_country__c
        FROM Opportunity
        WHERE CloseDate <= {}
        AND CloseDate >= {}
        AND StageName = 'Pledged'
        AND Stripe_Customer_Id__c != ''
        """.format(today, three_days_ago)

    try:
        process_charges(query, log)
    finally:
        lock.release()

@celery.task()
def update_ach_charges():

    lock = Lock(key='update-ach-charges-lock')
    lock.acquire()

    log = Log()

    log.it('---Starting batch job...')

    #three_days_ago = (datetime.now(tz=zone) - timedelta(
    #    days=3)).strftime('%Y-%m-%d')
    #today = datetime.now(tz=zone).strftime('%Y-%m-%d')

    # regular (non Circle) pledges:
    log.it('---Checking for status changes on ACH charges...')

    query = """
        SELECT Stripe_Transaction_ID__c, Amount, Name, Stripe_Customer_Id__c, Description, StageName, Stripe_Card__c, Stripe_Bank_Account__c,
            Stripe_Agreed_to_pay_fees__c, Referring_page__c, Shipping_address_name__c, Shipping_address_street__c,
            Shipping_address_city__c, Shipping_address_state__c, Shipping_address_ZIP__c, Shipping_address_country__c
        FROM Opportunity
        WHERE StageName = 'ACH Pending'
        AND Stripe_Customer_Id__c != ''
        """

    try:
        process_charges(query, log)
    finally:
        lock.release()

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


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

"""
bencode/decode library.

bencoding is used in bittorrent files

use the exposed functions to encode/decode them.
"""

from io import BytesIO, SEEK_CUR
try: #py 3.3
	from collections.abc import Iterable, Mapping
except ImportError:
	from collections     import Iterable, Mapping

_TYPE_INT  = b'i'
_TYPE_LIST = b'l'
_TYPE_DICT = b'd'
_TYPE_END  = b'e'
_TYPE_SEP  = b':'
_TYPES_STR = b'0123456789'

TYPES = {
	_TYPE_INT:  int,
	_TYPE_LIST: list,
	_TYPE_DICT: dict,
	_TYPE_END:  None,
	#_TYPE_SEP only appears in strings, not here
}
for byte in _TYPES_STR:
	TYPES[bytes([byte])] = str #b'0': str, b'1': str, …

def _readuntil(f, end=_TYPE_END):
	"""Helper function to read bytes until a certain end byte is hit"""
	buf = bytearray()
	while True:
		byte = f.read(1)
		if byte != end:
			buf += byte
		else:
			break
	return buf

def _decode_int(f):
	"""
	Integer types are normal ascii integers
	Delimited at the start with 'i' and the end with 'e'
	"""
	assert f.read(1) == _TYPE_INT
	return int(_readuntil(f))

def _decode_buffer(f):
	"""
	String types are normal (byte)strings
	starting with an integer followed by ':'
	which designates the string’s length.
	Since there’s
	"""
	strlen = int(_readuntil(f, _TYPE_SEP))
	buf = f.read(strlen)
	try:
		return buf.decode()
	except UnicodeDecodeError:
		return buf

def _decode_list(f):
	assert f.read(1) == _TYPE_LIST
	ret = []
	while True:
		item = bdecode(f)
		if item is None:
			break
		else:
			ret.append(item)
	return ret

def _decode_dict(f):
	assert f.read(1) == _TYPE_DICT
	ret = {}
	while True:
		key = bdecode(f)
		if key is None:
			break
		else:
			assert isinstance(key, (str, bytes))
			ret[key] = bdecode(f)
	return ret

DECODERS = {
	int:  _decode_int,
	str:  _decode_buffer,
	list: _decode_list,
	dict: _decode_dict,
}

def bdecode(f):
	"""
	bdecodes data contained in a file f opened in bytes mode.
	works by looking up the type byte,
	and using it to look up the respective decoding function,
	which in turn is used to return the decoded object
	"""
	btype = TYPES[f.read(1)]
	if btype is not None:
		f.seek(-1, SEEK_CUR)
		return DECODERS[btype](f)
	else: #Used in dicts and lists to designate an end
		return None

def bdecode_buffer(data):
	"""Convenience wrapper around bdecode that accepts strings or bytes"""
	if isinstance(data, str):
		data = data.encode()
	with BytesIO(data) as f:
		return bdecode(f)

################
### Encoding ###
################

def _encode_int(integer, f):
	f.write(_TYPE_INT)
	f.write(str(integer).encode())
	f.write(_TYPE_END)

def _encode_buffer(string, f):
	"""Writes the bencoded form of the input string or bytes"""
	if isinstance(string, str):
		string = string.encode()
	f.write(str(len(string)).encode())
	f.write(_TYPE_SEP)
	f.write(string)

def _encode_iterable(iterable, f):
	f.write(_TYPE_LIST)
	for item in iterable:
		bencode(item, f)
	f.write(_TYPE_END)

def _encode_mapping(mapping, f):
	f.write(_TYPE_DICT)
	for key, value in mapping.items():
		_encode_buffer(key, f)
		bencode(value, f)
	f.write(_TYPE_END)

def bencode(data, f):
	"""
	Writes a serializable data piece to f
	The order of tests is nonarbitrary,
	as strings and mappings are iterable.
	"""
	if isinstance(data, int):
		_encode_int(data, f)
	elif isinstance(data, (str, bytes)):
		_encode_buffer(data, f)
	elif isinstance(data, Mapping):
		_encode_mapping(data, f)
	elif isinstance(data, Iterable):
		_encode_iterable(data, f)

def bencode_buffer(data):
	"""
	Convenience wrapper around bencode that returns a byte array
	of the serialized sata
	"""
	with BytesIO() as f:
		bencode(data, f)
		return f.getvalue()

def main():
	import sys, pprint
	from argparse import ArgumentParser, FileType
	parser = ArgumentParser(description='Decodes bencoded files to python objects.')
	parser.add_argument('infile',  nargs='?', type=FileType('rb'), default=sys.stdin.buffer,
		help='bencoded file (e.g. torrent) [Default: stdin]')
	parser.add_argument('outfile', nargs='?', type=FileType('w'), default=sys.stdout,
		help='python-syntax serialization [Default: stdout]')
	args = parser.parse_args()

	data = bdecode(args.infile)
	pprint.pprint(data, stream=args.outfile)

if __name__ == '__main__':
	main()
<commit_msg>finished one comment<commit_after>#!/usr/bin/env python

"""
bencode/decode library.

bencoding is used in bittorrent files

use the exposed functions to encode/decode them.
"""

from io import BytesIO, SEEK_CUR
try: #py 3.3
	from collections.abc import Iterable, Mapping
except ImportError:
	from collections     import Iterable, Mapping

_TYPE_INT  = b'i'
_TYPE_LIST = b'l'
_TYPE_DICT = b'd'
_TYPE_END  = b'e'
_TYPE_SEP  = b':'
_TYPES_STR = b'0123456789'

TYPES = {
	_TYPE_INT:  int,
	_TYPE_LIST: list,
	_TYPE_DICT: dict,
	_TYPE_END:  None,
	#_TYPE_SEP only appears in strings, not here
}
for byte in _TYPES_STR:
	TYPES[bytes([byte])] = str #b'0': str, b'1': str, …

def _readuntil(f, end=_TYPE_END):
	"""Helper function to read bytes until a certain end byte is hit"""
	buf = bytearray()
	while True:
		byte = f.read(1)
		if byte != end:
			buf += byte
		else:
			break
	return buf

def _decode_int(f):
	"""
	Integer types are normal ascii integers
	Delimited at the start with 'i' and the end with 'e'
	"""
	assert f.read(1) == _TYPE_INT
	return int(_readuntil(f))

def _decode_buffer(f):
	"""
	String types are normal (byte)strings
	starting with an integer followed by ':'
	which designates the string’s length.

	Since there’s no way to specify the byte type
	in bencoded files, we have to guess
	"""
	strlen = int(_readuntil(f, _TYPE_SEP))
	buf = f.read(strlen)
	try:
		return buf.decode()
	except UnicodeDecodeError:
		return buf

def _decode_list(f):
	assert f.read(1) == _TYPE_LIST
	ret = []
	while True:
		item = bdecode(f)
		if item is None:
			break
		else:
			ret.append(item)
	return ret

def _decode_dict(f):
	assert f.read(1) == _TYPE_DICT
	ret = {}
	while True:
		key = bdecode(f)
		if key is None:
			break
		else:
			assert isinstance(key, (str, bytes))
			ret[key] = bdecode(f)
	return ret

DECODERS = {
	int:  _decode_int,
	str:  _decode_buffer,
	list: _decode_list,
	dict: _decode_dict,
}

def bdecode(f):
	"""
	bdecodes data contained in a file f opened in bytes mode.
	works by looking up the type byte,
	and using it to look up the respective decoding function,
	which in turn is used to return the decoded object
	"""
	btype = TYPES[f.read(1)]
	if btype is not None:
		f.seek(-1, SEEK_CUR)
		return DECODERS[btype](f)
	else: #Used in dicts and lists to designate an end
		return None

def bdecode_buffer(data):
	"""Convenience wrapper around bdecode that accepts strings or bytes"""
	if isinstance(data, str):
		data = data.encode()
	with BytesIO(data) as f:
		return bdecode(f)

################
### Encoding ###
################

def _encode_int(integer, f):
	f.write(_TYPE_INT)
	f.write(str(integer).encode())
	f.write(_TYPE_END)

def _encode_buffer(string, f):
	"""Writes the bencoded form of the input string or bytes"""
	if isinstance(string, str):
		string = string.encode()
	f.write(str(len(string)).encode())
	f.write(_TYPE_SEP)
	f.write(string)

def _encode_iterable(iterable, f):
	f.write(_TYPE_LIST)
	for item in iterable:
		bencode(item, f)
	f.write(_TYPE_END)

def _encode_mapping(mapping, f):
	f.write(_TYPE_DICT)
	for key, value in mapping.items():
		_encode_buffer(key, f)
		bencode(value, f)
	f.write(_TYPE_END)

def bencode(data, f):
	"""
	Writes a serializable data piece to f
	The order of tests is nonarbitrary,
	as strings and mappings are iterable.
	"""
	if isinstance(data, int):
		_encode_int(data, f)
	elif isinstance(data, (str, bytes)):
		_encode_buffer(data, f)
	elif isinstance(data, Mapping):
		_encode_mapping(data, f)
	elif isinstance(data, Iterable):
		_encode_iterable(data, f)

def bencode_buffer(data):
	"""
	Convenience wrapper around bencode that returns a byte array
	of the serialized sata
	"""
	with BytesIO() as f:
		bencode(data, f)
		return f.getvalue()

def main():
	import sys, pprint
	from argparse import ArgumentParser, FileType
	parser = ArgumentParser(description='Decodes bencoded files to python objects.')
	parser.add_argument('infile',  nargs='?', type=FileType('rb'), default=sys.stdin.buffer,
		help='bencoded file (e.g. torrent) [Default: stdin]')
	parser.add_argument('outfile', nargs='?', type=FileType('w'), default=sys.stdout,
		help='python-syntax serialization [Default: stdout]')
	args = parser.parse_args()

	data = bdecode(args.infile)
	pprint.pprint(data, stream=args.outfile)

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


<commit_before># ------------------------------------------------------------------------------
# FIXME: This is a dummy test case.
# This can be removed when ABCDatabase is used and tested with actual databases
# ------------------------------------------------------------------------------

import unittest
from collections import namedtuple

from remoteappmanager.db.interfaces import (
    ABCApplication, ABCApplicationPolicy, ABCAccounting)
from remoteappmanager.db import exceptions
from remoteappmanager.db.tests.abc_test_interfaces import (
    ABCTestDatabaseInterface)

User = namedtuple('User', ('name',))

class Application(ABCApplication):
    pass

class ApplicationPolicy(ABCApplicationPolicy):
    pass

class Accounting(ABCAccounting):

    def get_user_by_name(self, username):
        return User(name=username)

    def get_apps_for_user(self, user):
        return (('abc1',
                 Application(image=user.name+'1'), ApplicationPolicy()),
                ('abc2',
                 Application(image=user.name+'2'), ApplicationPolicy()))

    def create_user(self, user_name):
        raise exceptions.UnsupportedOperation()

    def remove_user(self, user_name):
        raise exceptions.UnsupportedOperation()

    def list_users(self):
        return []

    def create_application(self, app_name):
        raise exceptions.UnsupportedOperation()

    def remove_application(self, app_name):
        raise exceptions.UnsupportedOperation()

    def list_applications(self):
        return []

    def grant_access(self, app_name, user_name,
                     allow_home, allow_view, volume):
        raise exceptions.UnsupportedOperation()

    def revoke_access(self, app_name, user_name,
                      allow_home, allow_view, volume):
        raise exceptions.UnsupportedOperation()

class TestDatabaseInterface(ABCTestDatabaseInterface, unittest.TestCase):
    def setUp(self):
        self.addTypeEqualityFunc(Application,
                                 self.assertApplicationEqual)
        self.addTypeEqualityFunc(ApplicationPolicy,
                                 self.assertApplicationPolicyEqual)

    def create_expected_users(self):
        return [User('foo'), User('bar')]

    def create_expected_configs(self, user):
        return [(Application(image=user.name+'1'), ApplicationPolicy()),
                (Application(image=user.name+'2'), ApplicationPolicy())]

    def create_accounting(self):
        return Accounting()

    def test_get_user_by_name(self):
        database = self.create_accounting()
        self.assertEqual(database.get_user_by_name('foo'), User('foo'))
<commit_msg>Fixed tests<commit_after># ------------------------------------------------------------------------------
# FIXME: This is a dummy test case.
# This can be removed when ABCDatabase is used and tested with actual databases
# ------------------------------------------------------------------------------

import unittest
from collections import namedtuple

from remoteappmanager.db.interfaces import (
    ABCApplication, ABCApplicationPolicy, ABCAccounting)
from remoteappmanager.db import exceptions
from remoteappmanager.db.tests.abc_test_interfaces import (
    ABCTestDatabaseInterface)

User = namedtuple('User', ('name',))

class Application(ABCApplication):
    pass

class ApplicationPolicy(ABCApplicationPolicy):
    pass

class Accounting(ABCAccounting):

    def get_user_by_name(self, username):
        return User(name=username)

    def get_apps_for_user(self, user):
        return (('abc1',
                 Application(image=user.name+'1'), ApplicationPolicy()),
                ('abc2',
                 Application(image=user.name+'2'), ApplicationPolicy()))

    def create_user(self, user_name):
        raise exceptions.UnsupportedOperation()

    def remove_user(self, user_name):
        raise exceptions.UnsupportedOperation()

    def list_users(self):
        return [User('foo'), User('bar')]

    def create_application(self, app_name):
        raise exceptions.UnsupportedOperation()

    def remove_application(self, app_name):
        raise exceptions.UnsupportedOperation()

    def list_applications(self):
        return [Application(image="foo1"),
                Application(image="foo2"),
                Application(image="bar1"),
                Application(image="bar2")
                ]

    def grant_access(self, app_name, user_name,
                     allow_home, allow_view, volume):
        raise exceptions.UnsupportedOperation()

    def revoke_access(self, app_name, user_name,
                      allow_home, allow_view, volume):
        raise exceptions.UnsupportedOperation()

class TestDatabaseInterface(ABCTestDatabaseInterface, unittest.TestCase):
    def setUp(self):
        self.addTypeEqualityFunc(Application,
                                 self.assertApplicationEqual)
        self.addTypeEqualityFunc(ApplicationPolicy,
                                 self.assertApplicationPolicyEqual)

    def create_expected_users(self):
        return [User('foo'), User('bar')]

    def create_expected_configs(self, user):
        return [(Application(image=user.name+'1'), ApplicationPolicy()),
                (Application(image=user.name+'2'), ApplicationPolicy())]

    def create_accounting(self):
        return Accounting()

    def test_get_user_by_name(self):
        database = self.create_accounting()
        self.assertEqual(database.get_user_by_name('foo'), User('foo'))
<|endoftext|>