<commit_before>import mdl
from display import *
from matrix import *
from matrix import matrix_mult as mmult
from draw import *
from draw3d import *
from stack import Stack

from math import *

def run(filename):
    """
    This function runs an mdl script
    """
    p = mdl.parseFile(filename)

    if p:
        (commands, symbols) = p
    else:
        print "Parsing failed."
        return

    # Setup drawing environment *after* the error checking to prevent prematurely allocating too much memory
    color = [255, 255, 255]
    stack = Stack()
    screen = new_screen()

    env = (color, stack, screen, symbols)

    # Pick a function to execute from the dict(string, function)
    x_map = {
        # 2-D drawing routines
        "line": line,
        "circle": circle,
        "hermite": hermite,
        "bezier": bezier,
        # 3-D drawing routines
        "box": box,
        "sphere": sphere,
        "torus": torus,
        # Matrix stack operations
        "push": push,
        "pop": pop,
        # Transformations
        "move": move,
        "scale": scale,
        "rotate": rotate,
        # Display and save
        "display": display_img,
        "save": save_img
    }

    for command in commands:
        print command
        cmd = command[0]
        x_map[cmd](command, env)

# Functions for executing commands

# 2-D drawing routines

def line(args, env):
    # Semantic analyzer
    x0, y0, z0, x1, y1, z1 = args[1:]
    color, stack, screen, symbols = env

    # Immediately draw line to screen
    edges = []
    add_edge(edges, x0, y0, z0, x1, y1, z1)
    mmult(stack.peek(), edges)
    draw_lines(edges, screen, color)

def circle(args, env):
    # Semantic analyzer
    pass

def hermite(args, env):
    pass

def bezier(args, env):
    pass

# 3-D drawing routines

def box(args, env):
    x, y, z, width, height, depth = args[1:]
    color, stack, screen, symbols = env

    polygons = []
    add_box(polygons, x, y, z, width, height, depth)
    mmult(stack.peek(), polygons)
    draw_polygons(polygons, screen, color)

def sphere(args, env):
    x, y, z, r, coord_system = args[1:]
    color, stack, screen, symbols = env

    step = int(round(2 * sqrt(r)))

    polygons = []
    add_sphere(polygons, x, y, z, r, step)
    mmult(stack.peek() if coord_system is None else coord_system, polygons)
    draw_polygons(polygons, screen, color)

def torus(args, env):
    pass
    #x, y, z, r, R, coord_system = args[1:]

# Matrix stack operations

def push(args, env):
    color, stack, screen, symbols = env

    stack.push()

def pop(args, env):
    color, stack, screen, symbols = env

    stack.pop()

# Transformations

def move(args, env):
    x, y, z, knob = args[1:]
    color, stack, screen, symbols = env

    u = make_translate(x, y, z)
    stack.mult(u)

def scale(args, env):
    x, y, z, knob = args[1:]
    color, stack, screen, symbols = env

    u = make_scale(x, y, z)
    stack.mult(u)

def rotate(args, env):
    axis, degrees, knob = args[1:]
    color, stack, screen, symbols = env

    rot = {
        "x": make_rotX,
        "y": make_rotY,
        "z": make_rotZ
    }

    u = rot[axis](radians(degrees))
    stack.mult(u)

# Display and save

def display_img(args, env):
    color, stack, screen, symbols = env
    display(screen)

def save_img(args, env):
    filename = args[1]
    color, stack, screen, symbols = env

    if filename is not None:
        if filename[-4:].lower() == ".ppm":
            save_ppm(screen, filename)
        else:
            save_extension(screen, filename)
<commit_msg>Add torus code in case Deedubs tests it.<commit_after>import mdl
from display import *
from matrix import *
from matrix import matrix_mult as mmult
from draw import *
from draw3d import *
from stack import Stack

from math import *

def run(filename):
    """
    This function runs an mdl script
    """
    p = mdl.parseFile(filename)

    if p:
        (commands, symbols) = p
    else:
        print "Parsing failed."
        return

    # Setup drawing environment *after* the error checking to prevent prematurely allocating too much memory
    color = [255, 255, 255]
    stack = Stack()
    screen = new_screen()

    env = (color, stack, screen, symbols)

    # Pick a function to execute from the dict(string, function)
    x_map = {
        # 2-D drawing routines
        "line": line,
        "circle": circle,
        "hermite": hermite,
        "bezier": bezier,
        # 3-D drawing routines
        "box": box,
        "sphere": sphere,
        "torus": torus,
        # Matrix stack operations
        "push": push,
        "pop": pop,
        # Transformations
        "move": move,
        "scale": scale,
        "rotate": rotate,
        # Display and save
        "display": display_img,
        "save": save_img
    }

    for command in commands:
        print command
        cmd = command[0]
        x_map[cmd](command, env)

# Functions for executing commands

# 2-D drawing routines

def line(args, env):
    # Semantic analyzer
    x0, y0, z0, x1, y1, z1 = args[1:]
    color, stack, screen, symbols = env

    # Immediately draw line to screen
    edges = []
    add_edge(edges, x0, y0, z0, x1, y1, z1)
    mmult(stack.peek(), edges)
    draw_lines(edges, screen, color)

def circle(args, env):
    # Semantic analyzer
    pass

def hermite(args, env):
    pass

def bezier(args, env):
    pass

# 3-D drawing routines

def box(args, env):
    x, y, z, width, height, depth = args[1:]
    color, stack, screen, symbols = env

    polygons = []
    add_box(polygons, x, y, z, width, height, depth)
    mmult(stack.peek(), polygons)
    draw_polygons(polygons, screen, color)

def sphere(args, env):
    x, y, z, r, coord_system = args[1:]

    color, stack, screen, symbols = env
    step = int(round(2 * sqrt(r)))

    polygons = []
    add_sphere(polygons, x, y, z, r, step)
    mmult(stack.peek() if coord_system is None else coord_system, polygons)
    draw_polygons(polygons, screen, color)

def torus(args, env):
    x, y, z, r, R, coord_system = args[1:]
    color, stack, screen, symbols = env
    step = int(round(4 * sqrt(r)))

    polygons = []
    add_torus(polygons, x, y, z, r, R, step)
    mmult(stack.peek() if coord_system is None else coord_system, polygons)
    draw_polygons(polygons, screen, pen)

# Matrix stack operations

def push(args, env):
    color, stack, screen, symbols = env

    stack.push()

def pop(args, env):
    color, stack, screen, symbols = env

    stack.pop()

# Transformations

def move(args, env):
    x, y, z, knob = args[1:]
    color, stack, screen, symbols = env

    u = make_translate(x, y, z)
    stack.mult(u)

def scale(args, env):
    x, y, z, knob = args[1:]
    color, stack, screen, symbols = env

    u = make_scale(x, y, z)
    stack.mult(u)

def rotate(args, env):
    axis, degrees, knob = args[1:]
    color, stack, screen, symbols = env

    rot = {
        "x": make_rotX,
        "y": make_rotY,
        "z": make_rotZ
    }

    u = rot[axis](radians(degrees))
    stack.mult(u)

# Display and save

def display_img(args, env):
    color, stack, screen, symbols = env
    display(screen)

def save_img(args, env):
    filename = args[1]
    color, stack, screen, symbols = env

    if filename is not None:
        if filename[-4:].lower() == ".ppm":
            save_ppm(screen, filename)
        else:
            save_extension(screen, filename)
<|endoftext|>


<commit_before>from marshmallow import Schema

from . import fields, validate

from skylines.lib.formatter.units import DISTANCE_UNITS, SPEED_UNITS, LIFT_UNITS, ALTITUDE_UNITS

class AircraftModelSchema(Schema):
    id = fields.Integer(dump_only=True)
    name = fields.String(required=True, strip=True, validate=validate.Length(max=64))
    index = fields.Integer(attribute='dmst_index')

class ClubSchema(Schema):
    id = fields.Integer(dump_only=True)
    name = fields.String(required=True, strip=True, validate=(
        validate.NotEmpty(),
        validate.Length(min=1, max=255),
    ))
    website = fields.URL()

class IGCFileSchema(Schema):
    registration = fields.String(strip=True, validate=validate.Length(max=32))
    competitionId = fields.String(attribute='competition_id', strip=True, validate=validate.Length(max=5))
    model = fields.String(strip=True, validate=validate.Length(max=64))

class UserSchema(Schema):
    id = fields.Integer(dump_only=True)
    email = fields.Email(attribute='email_address', validate=validate.Length(max=255))
    firstName = fields.String(attribute='first_name', strip=True, validate=(
        validate.NotEmpty(),
        validate.Length(min=1, max=255),
    ))
    lastName = fields.String(attribute='last_name', strip=True, validate=(
        validate.NotEmpty(),
        validate.Length(min=1, max=255),
    ))
    name = fields.String(dump_only=True)
    trackingCallsign = fields.String(attribute='tracking_callsign', strip=True, validate=validate.Length(max=5))
    trackingDelay = fields.Integer(attribute='tracking_delay', validate=validate.Range(min=0, max=60))
    distanceUnit = fields.Integer(attribute='distance_unit', validate=validate.Range(min=0, max=len(DISTANCE_UNITS) - 1))
    speedUnit = fields.Integer(attribute='speed_unit', validate=validate.Range(min=0, max=len(SPEED_UNITS) - 1))
    liftUnit = fields.Integer(attribute='lift_unit', validate=validate.Range(min=0, max=len(LIFT_UNITS) - 1))
    altitudeUnit = fields.Integer(attribute='altitude_unit', validate=validate.Range(min=0, max=len(ALTITUDE_UNITS) - 1))

class FlightSchema(Schema):
    timeCreated = fields.DateTime(attribute='time_created')

    pilotId = fields.Integer(attribute='pilot_id', allow_none=True)
    pilot = fields.Nested(UserSchema, only=('id', 'name'))
    pilotName = fields.String(attribute='pilot_name', strip=True, allow_none=True, validate=validate.Length(max=255))

    copilotId = fields.Integer(attribute='co_pilot_id', allow_none=True)
    copilot = fields.Nested(UserSchema, attribute='co_pilot', only=('id', 'name'))
    copilotName = fields.String(attribute='co_pilot_name', strip=True, allow_none=True, validate=validate.Length(max=255))

    clubId = fields.Integer(attribute='club_id', allow_none=True)
    club = fields.Nested(ClubSchema, only=('id', 'name'))

    modelId = fields.Integer(attribute='model_id', allow_none=True)
    model = fields.Nested(AircraftModelSchema)
    registration = fields.String(strip=True, validate=validate.Length(max=32))
    competitionId = fields.String(attribute='competition_id', strip=True, validate=validate.Length(max=5))

    scoreDate = fields.Date(attribute='date_local')

    takeoffTime = fields.DateTime(attribute='takeoff_time')
    scoreStartTime = fields.DateTime(attribute='scoring_start_time')
    scoreEndTime = fields.DateTime(attribute='scoring_end_time')
    landingTime = fields.DateTime(attribute='landing_time')

    distance = fields.Integer(attribute='olc_classic_distance')
    triangleDistance = fields.Integer(attribute='olc_triangle_distance')
    score = fields.Float(attribute='olc_plus_score')

    class Meta:
        load_only = ('pilotId', 'copilotId', 'clubId', 'modelId')
        dump_only = ('pilot', 'copilot', 'club', 'model')

class FlightCommentSchema(Schema):
    user = fields.Nested(UserSchema, only=('id', 'name'))
    text = fields.String(required=True)
<commit_msg>schemas/FlightSchema: Add "takeoffAirport" and "landingAirport" attributes<commit_after>from marshmallow import Schema

from . import fields, validate

from skylines.lib.formatter.units import DISTANCE_UNITS, SPEED_UNITS, LIFT_UNITS, ALTITUDE_UNITS

class AircraftModelSchema(Schema):
    id = fields.Integer(dump_only=True)
    name = fields.String(required=True, strip=True, validate=validate.Length(max=64))
    index = fields.Integer(attribute='dmst_index')

class AirportSchema(Schema):
    id = fields.Integer(dump_only=True)
    name = fields.String(required=True, strip=True, validate=validate.Length(max=255))
    countryCode = fields.String(attribute='country_code', dump_only=True)

class ClubSchema(Schema):
    id = fields.Integer(dump_only=True)
    name = fields.String(required=True, strip=True, validate=(
        validate.NotEmpty(),
        validate.Length(min=1, max=255),
    ))
    website = fields.URL()

class IGCFileSchema(Schema):
    registration = fields.String(strip=True, validate=validate.Length(max=32))
    competitionId = fields.String(attribute='competition_id', strip=True, validate=validate.Length(max=5))
    model = fields.String(strip=True, validate=validate.Length(max=64))

class UserSchema(Schema):
    id = fields.Integer(dump_only=True)
    email = fields.Email(attribute='email_address', validate=validate.Length(max=255))
    firstName = fields.String(attribute='first_name', strip=True, validate=(
        validate.NotEmpty(),
        validate.Length(min=1, max=255),
    ))
    lastName = fields.String(attribute='last_name', strip=True, validate=(
        validate.NotEmpty(),
        validate.Length(min=1, max=255),
    ))
    name = fields.String(dump_only=True)
    trackingCallsign = fields.String(attribute='tracking_callsign', strip=True, validate=validate.Length(max=5))
    trackingDelay = fields.Integer(attribute='tracking_delay', validate=validate.Range(min=0, max=60))
    distanceUnit = fields.Integer(attribute='distance_unit', validate=validate.Range(min=0, max=len(DISTANCE_UNITS) - 1))
    speedUnit = fields.Integer(attribute='speed_unit', validate=validate.Range(min=0, max=len(SPEED_UNITS) - 1))
    liftUnit = fields.Integer(attribute='lift_unit', validate=validate.Range(min=0, max=len(LIFT_UNITS) - 1))
    altitudeUnit = fields.Integer(attribute='altitude_unit', validate=validate.Range(min=0, max=len(ALTITUDE_UNITS) - 1))

class FlightSchema(Schema):
    timeCreated = fields.DateTime(attribute='time_created')

    pilotId = fields.Integer(attribute='pilot_id', allow_none=True)
    pilot = fields.Nested(UserSchema, only=('id', 'name'))
    pilotName = fields.String(attribute='pilot_name', strip=True, allow_none=True, validate=validate.Length(max=255))

    copilotId = fields.Integer(attribute='co_pilot_id', allow_none=True)
    copilot = fields.Nested(UserSchema, attribute='co_pilot', only=('id', 'name'))
    copilotName = fields.String(attribute='co_pilot_name', strip=True, allow_none=True, validate=validate.Length(max=255))

    clubId = fields.Integer(attribute='club_id', allow_none=True)
    club = fields.Nested(ClubSchema, only=('id', 'name'))

    modelId = fields.Integer(attribute='model_id', allow_none=True)
    model = fields.Nested(AircraftModelSchema)
    registration = fields.String(strip=True, validate=validate.Length(max=32))
    competitionId = fields.String(attribute='competition_id', strip=True, validate=validate.Length(max=5))

    scoreDate = fields.Date(attribute='date_local')

    takeoffTime = fields.DateTime(attribute='takeoff_time')
    scoreStartTime = fields.DateTime(attribute='scoring_start_time')
    scoreEndTime = fields.DateTime(attribute='scoring_end_time')
    landingTime = fields.DateTime(attribute='landing_time')

    takeoffAirportId = fields.Integer(attribute='takeoff_airport_id', allow_none=True)
    takeoffAirport = fields.Nested(AirportSchema, attribute='takeoff_airport', only=('id', 'name', 'countryCode'))

    landingAirportId = fields.Integer(attribute='landing_airport_id', allow_none=True)
    landingAirport = fields.Nested(AirportSchema, attribute='landing_airport', only=('id', 'name', 'countryCode'))

    distance = fields.Integer(attribute='olc_classic_distance')
    triangleDistance = fields.Integer(attribute='olc_triangle_distance')
    score = fields.Float(attribute='olc_plus_score')

    class Meta:
        load_only = ('pilotId', 'copilotId', 'clubId', 'modelId', 'takeoffAirportId', 'landingAirportId')
        dump_only = ('pilot', 'copilot', 'club', 'model', 'takeoffAirport', 'landingAirport')

class FlightCommentSchema(Schema):
    user = fields.Nested(UserSchema, only=('id', 'name'))
    text = fields.String(required=True)
<|endoftext|>


<commit_before>import tkinter

# Privzeta minimax globina, če je nismo podali ob zagonu v ukazni vrstici
MINIMAX_PRIVZETA_GLOBINA = 3

######################################################################
## Igra

IGRALEC_RED = "rdeči"
IGRALEC_BLUE = "modri"
NI_KONEC = "ni konec"
VELIKOST_PLOSCE = 4

def nasprotnik(igralec):
    if igralec == IGRALEC_RED:
        return IGRALEC_BLUE
    else:
        return IGRALEC_RED

class Igra():
    def __init__(self):
        self.plosca = []
		for i in range(VELIKOST_PLOSCE):
			self.plosca.append([None for j in range(VELIKOST_PLOSCE)])
        self.na_potezi = IGRALEC_RED

    def veljavne_poteze(self):
        poteze = []
        for i in range(VELIKOST_PLOSCE):
            for j in range(VELIKOST_PLOSCE):
                if self.plosca[i][j] is None:
                    if self.plosca[i+1][j] is None:
                        poteze.append((i,j,i+1,j))
                    elif self.plosca[i][j+1] is None:
                        poteze.append((i,j,i,j+1))
        return poteze

    def povleci_potezi(self, i1, j1, i2, j2):
        """Povleci_potezi(i1, j1, i2, j2) vrne stanje_igre() po potezi ali None, ce je poteza neveljavna."""
        self.veljavne_poteze()
        for i in range(len(poteze)):
            if poteze[i] is (i1, j1, i2, j2) or (i2, j2, i1, j1):
                # Primerja povlečene poteze z veljavnimi
                p = self.na_potezi
                self.plosca[i1][j1] = self.na_potezi
                self.plosca[i2][j2] = self.na_potezi
                stanje = self.stanje_igre()
                if stanje == NI_KONEC:
                    # Igre ni konec, zdaj je na potezi nasprotnik
                    self.na_potezi = nasprotnik(self.na_potezi)
                else:
                    # Igre je konec
                    self.na_potezi = None
                return stanje
            else:
                # neveljavna poteza
            return None

    def stanje_igre(self):
        """Ugotovi, kakšno je trenutno stanje igre. Vrne:
           - IGRALEC_RED, če je igre konec in je zmagal IGRALEC_RED
           - IGRALEC_BLUE, če je igre konec in je zmagal IGRALEC_BLUE
           - NI_KONEC, če igre še ni konec
        """

        for i in range(VELIKOST_PLOSCE):
            for j in range(VELIKOST_PLOSCE):
                if self.plosca[i][j] is None:
                    if self.plosca[i+1][j] is None:
                        # Našli smo prazni ploscici, igre ni konec
                        return NI_KONEC
                    elif self.plosca[i][j+1] is None:
                        # Našli smo prazni ploscici, igre ni konec
                        return NI_KONEC
                    else:
                        # Igre je konec
                        return p

######################################################################
<commit_msg>Narejen razred računalnik<commit_after>import tkinter

# Privzeta minimax globina, če je nismo podali ob zagonu v ukazni vrstici
MINIMAX_PRIVZETA_GLOBINA = 3

######################################################################
## Igra

IGRALEC_RED = "rdeči"
IGRALEC_BLUE = "modri"
NEPOKRITO = "belo"
NI_KONEC = "ni konec"
VELIKOST_PLOSCE = 4

def nasprotnik(igralec):
    if igralec == IGRALEC_RED:
        return IGRALEC_BLUE
    elif igralec == IGRALEC_BLUE:
        return IGRALEC_RED
    else:
        assert False, "prepovedan nasprotnik"

class Igra():
    def __init__(self):
        self.plosca = []
		for i in range(VELIKOST_PLOSCE):
			self.plosca.append([NEPOKRITO for j in range(VELIKOST_PLOSCE)])
        self.na_potezi = IGRALEC_RED

    def kopija(self):
        """Vrni kopijo te igre."""
        k = Igra()
        k.plosca = [self.plosca[i][:] for i in range(VELIKOST_PLOSCE)]
        k.na_potezi = self.na_potezi
        return k

    def veljavne_poteze(self):
        poteze = []
        for i in range(VELIKOST_PLOSCE):
            for j in range(VELIKOST_PLOSCE):
                if self.plosca[i][j] is NEPOKRITO:
                    if self.plosca[i+1][j] is NEPOKRITO:
                        poteze.append((i,j,i+1,j))
                    elif self.plosca[i][j+1] is NEPOKRITO:
                        poteze.append((i,j,i,j+1))
        return poteze

    def povleci_potezi(self, pozicija1, pozicija2):
        """Povleci_potezi(i1, j1, i2, j2) vrne stanje_igre() po potezi ali None, ce je poteza neveljavna."""
        (i1,j1) = pozicija1
        (i2,j2) = pozicija2
        self.veljavne_poteze()
        for i in range(len(poteze)):
            if poteze[i] is (i1, j1, i2, j2) or (i2, j2, i1, j1):
                # Primerja povlečene poteze z veljavnimi
                igrac = self.na_potezi
                self.plosca[i1][j1] = self.na_potezi
                self.plosca[i2][j2] = self.na_potezi
                stanje = self.stanje_igre()
                if stanje == NI_KONEC:
                    # Igre ni konec, zdaj je na potezi nasprotnik
                    self.na_potezi = nasprotnik(self.na_potezi)
                else:
                    # Igre je konec
                    self.na_potezi = None
                return stanje
            elif (self.plosca[i1][j1] != NEPOKRITO) or (self.plosca[i2][j2] != NEPOKRITO) or (self.na_potezi == None):
                # neveljavna poteza
                return None
            else:
                assert False, "prepovedana poteza"

    def stanje_igre(self):
        """Ugotovi, kakšno je trenutno stanje igre. Vrne:
           - IGRALEC_RED, če je igre konec in je zmagal IGRALEC_RED
           - IGRALEC_BLUE, če je igre konec in je zmagal IGRALEC_BLUE
           - NI_KONEC, če igre še ni konec
        """

        for i in range(VELIKOST_PLOSCE):
            for j in range(VELIKOST_PLOSCE):
                if self.plosca[i][j] is NEPOKRITO:
                    if self.plosca[i+1][j] is NEPOKRITO:
                        # Našli smo prazni ploscici, igre ni konec
                        return NI_KONEC
                    elif self.plosca[i][j+1] is NEPOKRITO:
                        # Našli smo prazni ploscici, igre ni konec
                        return NI_KONEC
                    else:
                        # Igre je konec
                        return igrac

######################################################################
## Igralec računalnik

class Racunalnik():
    def __init__(self, gui, algoritem):
        self.gui = gui
        self.algoritem = algoritem # Algoritem, ki izračuna potezo
        self.vlakno = None # Vlakno, ki razmišlja

    def igraj(self):
        """Igraj potezo, ki jo vrne algoritem."""
        # Naredimo vlakno:
        self.vlakno = threading.Thread(...)
        # Poženemo vlakno:
        self.vlakno.start()
        # Gremo preverjat, če sta bili najdeni potezi:
        ...

    def preveri_potezi(self):
        #Vsakih 100ms preveri, ali je algoritem že izračunal potezi.

    def prekini(self):
        # To metodo kliče GUI, če je treba prekiniti razmišljanje.

    def klik(self, pozicija1):
        # Računalnik ignorira klike.
        pass

    def spust(self, pozicija2):
        # Računalnik ignorira spuste.
        pass

######################################################################
<|endoftext|>


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

# Copyright 2008 Brigham Young University
#
# This file is part of Mrs.
#
# Mrs is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# Mrs is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# Mrs.  If not, see <http://www.gnu.org/licenses/>.
#
# Inquiries regarding any further use of the Materials contained on this site,
# please contact the Copyright Licensing Office, Brigham Young University,
# 3760 HBLL, Provo, UT 84602, (801) 422-9339 or 422-3821, e-mail
# copyright@byu.edu.

__all__ = ['Buffer', 'TextFormat', 'HexFormat', 'hexformat_sort',
        'fileformat', 'openfile']

from textformat import TextFormat
from hexformat import HexFormat, hexformat_sort

format_map = {
        '.txt': TextFormat,
        '.mrsx': HexFormat,
        }
default_format = TextFormat

def fileformat(filename):
    """Guess the file format according to extension of the given filename."""
    import os
    extension = os.path.splitext(filename)[1]
    return format_map.get(extension, default_format)

# TODO: Find a better way to infer the file format.
def openfile(url, mode='r'):
    """Open a url or file to be read or written as a list of key-value pairs.

    The file format is inferred from the filename.
    """
    import urlparse, urllib2
    parsed_url = urlparse.urlparse(url, 'file')
    if parsed_url.scheme == 'file':
        f = open(parsed_url.path, mode)
    else:
        f = urllib2.urlopen(url)
    input_format = fileformat(url)
    return input_format(f)

# vim: et sw=4 sts=4
<commit_msg>replaced openfile with openbuf, for better concurrency<commit_after>#!/usr/bin/env python

# Copyright 2008 Brigham Young University
#
# This file is part of Mrs.
#
# Mrs is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# Mrs is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# Mrs.  If not, see <http://www.gnu.org/licenses/>.
#
# Inquiries regarding any further use of the Materials contained on this site,
# please contact the Copyright Licensing Office, Brigham Young University,
# 3760 HBLL, Provo, UT 84602, (801) 422-9339 or 422-3821, e-mail
# copyright@byu.edu.

__all__ = ['Buffer', 'TextFormat', 'HexFormat', 'hexformat_sort',
        'fileformat', 'openbuf']

from textformat import TextFormat
from hexformat import HexFormat, hexformat_sort
from buffer import Buffer

format_map = {
        '.txt': TextFormat,
        '.mrsx': HexFormat,
        }
default_format = TextFormat

# TODO: Find a better way to infer the file format.
def fileformat(filename):
    """Guess the file format according to extension of the given filename."""
    import os
    extension = os.path.splitext(filename)[1]
    return format_map.get(extension, default_format)

def openbuf(url, mode='r'):
    """Open a url or file into a Mrs Buffer

    Initially, the Buffers will be empty.  However, when Twisted's
    reactor.run() is called, data will be read into all Buffers
    simultaneously.
    """
    import urlparse, urllib2
    parsed_url = urlparse.urlparse(url, 'file')
    if parsed_url.scheme == 'file':
        f = open(parsed_url.path, mode)
        buf = Buffer(filelike=f)
    else:
        from net import download
        buf = download(url)
    return buf

# vim: et sw=4 sts=4
<|endoftext|>


<commit_before>import threading
import Queue
import array
import logging
from logging.handlers import TimedRotatingFileHandler

class PackageHandlerThread (threading.Thread):

	FIXED_BYTES_PART_1 = ['H', 'D', 'L', 'M', 'I', 'R', 'A', 'C', 'L', 'E']
	FIXED_BYTES_PART_2 = [-86, -86] # = 0xAA
	BYTE_POSITION_SOURCE_SUBNET_ID = 17
	BYTE_POSITION_SOURCE_DEVICE_ID = 18
	BYTE_POSITION_DEVICE_TYPE_BYTE_1 = 19
	BYTE_POSITION_DEVICE_TYPE_BYTE_2 = 20
	BYTE_POSITION_OPERATION_CODE_BYTE_1 = 21
	BYTE_POSITION_OPERATION_CODE_BYTE_2 = 22
	BYTE_POSITION_TARGET_SUBNET_ID = 23
	BYTE_POSITION_TARGET_DEVICE_ID = 24
	LOG_TYPE_FILE_HUMAN_READABLE = 1
	OPERATION_CODES = {
		0x0031: "Single channel control",
		0x0032: "Response single channel control",
		0x15D0: "Read dry contact status",
		0x15D1: "Response read dry contact status",
		0x1647: "Broadcast sensors status",
		0x1948: "Read temperature",
		0x1949: "Response read temperature",
		0x1C5C: "Control floor heating status",
		0x1C5D: "Response control floor heating status",
		0xE3E5: "Broadcast temperature",
		0xDA44: "Broadcast date and time (every minute)"
	}
	COMPONENT_TYPES = {
		0x0138: "Ceiling Mount PIR Sensor"
	}

	def __init__(self, messageQueue):
		threading.Thread.__init__(self)
		self.messageQueue = messageQueue
		logHandler = TimedRotatingFileHandler("network.log", when="midnight", backupCount=7)
		logHandler.setFormatter(logging.Formatter('%(asctime)s %(message)s'))
		self.log = logging.getLogger()
		self.log.setLevel(logging.DEBUG)
		self.log.addHandler(logHandler)

	def run(self):
		print "Starting package handler thread..."
		self.running = True
		while self.running:
			message = self.messageQueue.get()
			if message is None:
				break
			self.processMessage(message)
		print "Stopping " + self.__class__.__name__ + "..."

	def stop(self):
		self.running = False # This will stop the thread even though we have a lot of work left
		self.messageQueue.put(None) # This will stop the thread even though the thread is blocking

	def processMessage(self, rawMessageStr):
		rawBytes = array.array("b", rawMessageStr)
		if(self.isMessageValid(rawBytes)):
			operationCodeInt = (((rawBytes[self.BYTE_POSITION_OPERATION_CODE_BYTE_1] & 0xFF) << 8) + (rawBytes[self.BYTE_POSITION_OPERATION_CODE_BYTE_2] & 0xFF))
			operationCode =  "0x" + ("%X" % operationCodeInt).zfill(4)
			sourceTypeInt = (((rawBytes[self.BYTE_POSITION_DEVICE_TYPE_BYTE_1] & 0xFF) << 8) + (rawBytes[self.BYTE_POSITION_DEVICE_TYPE_BYTE_2] & 0xFF))
			sourceType = "0x" + ("%X" % sourceTypeInt).zfill(4)
			sourceSubnetAndDeviceId = '{0:<5}'.format(str(rawBytes[self.BYTE_POSITION_SOURCE_SUBNET_ID] & 0xFF) + "/" + str(rawBytes[self.BYTE_POSITION_SOURCE_DEVICE_ID] & 0xFF))
			destinationSubnetAndDeviceId = '{0:<7}'.format(str(rawBytes[self.BYTE_POSITION_TARGET_SUBNET_ID] & 0xFF) + "/" + str(rawBytes[self.BYTE_POSITION_TARGET_DEVICE_ID] & 0xFF))
			self.log.info("Op: %s" % operationCode + " (" + self.getOperationName(operationCodeInt) + "), src: " + sourceSubnetAndDeviceId + " (" + sourceType + "/" + self.getTypeName(sourceTypeInt) + "), dst: " + destinationSubnetAndDeviceId + "")

	def isMessageValid(self, bytes):
		if(bytes is not None and len(bytes) >= 23):
			for i in range(0, len(self.FIXED_BYTES_PART_1)):
				if(ord(self.FIXED_BYTES_PART_1[i]) is not bytes[i + 4]):
					return False
			for i in range(0, len(self.FIXED_BYTES_PART_2)):
				if(self.FIXED_BYTES_PART_2[i] != bytes[i + 14]):
					return False
			# TODO: Verify CRC
			return True
		return False

	def getOperationName(self, operationCodeInt):
		if(operationCodeInt in self.OPERATION_CODES):
			name = self.OPERATION_CODES[operationCodeInt]
		else:
			name = "Unknown operation"
		return '{0:<30.30}'.format(name)

	def getTypeName(self, type):
		if(type in self.COMPONENT_TYPES):
			name = self.COMPONENT_TYPES[type]
		else:
			name = "Unknown component"
		return '{0:<30.30}'.format(name)

<commit_msg>Added logging of contents part of package.<commit_after>import threading
import Queue
import array
import logging
from logging.handlers import TimedRotatingFileHandler

class PackageHandlerThread (threading.Thread):

	OPERATION_CODES = {
		0x0031: "Single channel control",
		0x0032: "Response single channel control",
		0x15D0: "Read dry contact status",
		0x15D1: "Response read dry contact status",
		0x1647: "Broadcast sensors status",
		0x1948: "Read temperature",
		0x1949: "Response read temperature",
		0x1C00: "Read temperature",
		0x1C01: "Response read temperature",
		0x1C5C: "Control floor heating status",
		0x1C5D: "Response control floor heating status",
		0xE3E5: "Broadcast temperature",
		0xDA44: "Broadcast date and time (every minute)"
	}
	COMPONENT_TYPES = {
		0x0138: "Ceiling Mount PIR Sensor"
	}
	FIXED_BYTES_PART_1 = ['H', 'D', 'L', 'M', 'I', 'R', 'A', 'C', 'L', 'E']
	FIXED_BYTES_PART_2 = [0xAA, 0xAA] # = 0xAA
	BYTE_POSITION_LENGTH = 16
	BYTE_POSITION_SOURCE_SUBNET_ID = 17
	BYTE_POSITION_SOURCE_DEVICE_ID = 18
	BYTE_POSITION_DEVICE_TYPE_BYTE_1 = 19
	BYTE_POSITION_DEVICE_TYPE_BYTE_2 = 20
	BYTE_POSITION_OPERATION_CODE_BYTE_1 = 21
	BYTE_POSITION_OPERATION_CODE_BYTE_2 = 22
	BYTE_POSITION_TARGET_SUBNET_ID = 23
	BYTE_POSITION_TARGET_DEVICE_ID = 24
	BYTE_POSITION_CONTENT = 25
	LOG_TYPE_FILE_HUMAN_READABLE = 1

	def __init__(self, messageQueue):
		threading.Thread.__init__(self)
		self.messageQueue = messageQueue
		logHandler = TimedRotatingFileHandler("network.log", when="midnight", backupCount=7)
		logHandler.setFormatter(logging.Formatter('%(asctime)s %(message)s'))
		self.log = logging.getLogger()
		self.log.setLevel(logging.DEBUG)
		self.log.addHandler(logHandler)

	def run(self):
		print "Starting package handler thread..."
		self.running = True
		while self.running:
			message = self.messageQueue.get()
			if message is None:
				break
			self.processMessage(message)
		print "Stopping " + self.__class__.__name__ + "..."

	def stop(self):
		self.running = False # This will stop the thread even though we have a lot of work left
		self.messageQueue.put(None) # This will stop the thread even though the thread is blocking

	def processMessage(self, rawMessageStr):
		rawBytes = array.array("B", rawMessageStr)
		if(self.isMessageValid(rawBytes)):
			operationCodeInt = (((rawBytes[self.BYTE_POSITION_OPERATION_CODE_BYTE_1] & 0xFF) << 8) + (rawBytes[self.BYTE_POSITION_OPERATION_CODE_BYTE_2] & 0xFF))
			operationCode =  "0x" + ("%X" % operationCodeInt).zfill(4)
			sourceTypeInt = (((rawBytes[self.BYTE_POSITION_DEVICE_TYPE_BYTE_1] & 0xFF) << 8) + (rawBytes[self.BYTE_POSITION_DEVICE_TYPE_BYTE_2] & 0xFF))
			sourceType = "0x" + ("%X" % sourceTypeInt).zfill(4)
			sourceSubnetAndDeviceId = '{0:<5}'.format(str(rawBytes[self.BYTE_POSITION_SOURCE_SUBNET_ID] & 0xFF) + "/" + str(rawBytes[self.BYTE_POSITION_SOURCE_DEVICE_ID] & 0xFF))
			destinationSubnetAndDeviceId = '{0:<7}'.format(str(rawBytes[self.BYTE_POSITION_TARGET_SUBNET_ID] & 0xFF) + "/" + str(rawBytes[self.BYTE_POSITION_TARGET_DEVICE_ID] & 0xFF))
			contentLength = rawBytes[self.BYTE_POSITION_LENGTH] & 0xFF
			if(contentLength > 78 or contentLength < 11):
				self.log.warn("WARNING: Unexpected contents length [" + contentLength + "] of package:")
			contentLength = min(contentLength, 78)
			if(contentLength > 11):
				contentBytes = rawBytes[self.BYTE_POSITION_CONTENT:self.BYTE_POSITION_CONTENT + contentLength - 11]
				contents = "contents: " + "[" + self.getContentsAsText(contentBytes) + "]/[" + self.getContentsAsInts(contentBytes) + "]"
			else:
				contents = "no contents"

			self.log.info("Op: %s" % operationCode + " (" + self.getOperationName(operationCodeInt) + "), src: " + sourceSubnetAndDeviceId + " (" + sourceType + "/" + self.getTypeName(sourceTypeInt) + "), dst: " + destinationSubnetAndDeviceId + ", \n                        " + contents + "\n")

	def isMessageValid(self, bytes):
		if(bytes is not None and len(bytes) >= 23):
			for i in range(0, len(self.FIXED_BYTES_PART_1)):
				if(ord(self.FIXED_BYTES_PART_1[i]) is not bytes[i + 4]):
					return False
			for i in range(0, len(self.FIXED_BYTES_PART_2)):
				if(self.FIXED_BYTES_PART_2[i] != bytes[i + 14]):
					return False
			# TODO: Verify CRC
			return True
		return False

	def getOperationName(self, operationCodeInt):
		if(operationCodeInt in self.OPERATION_CODES):
			name = self.OPERATION_CODES[operationCodeInt]
		else:
			name = "Unknown operation"
		return '{0:<30.30}'.format(name)

	def getTypeName(self, type):
		if(type in self.COMPONENT_TYPES):
			name = self.COMPONENT_TYPES[type]
		else:
			name = "Unknown component"
		return '{0:<30.30}'.format(name)

	def getContentsAsText(self, contentBytes):
		# TODO: How can we convert this unsigned char array to ISO-8859-1?
		return contentBytes.tostring().replace("\r\n", "").replace("\n", "").replace("\r", "")

	def getContentsAsInts(self, contentBytes):
		return ' '.join(str(c).rjust(3) for c in contentBytes)
<|endoftext|>


<commit_before>from death_extractor import youtube as yt
from death_extractor import set_interval
from death_extractor import extract_and_upload

def death_as_a_service(vid_path = 'vids', post_interval=3600*2, search_interval=3600*12, dl_interval=3600*6, max_downloads=5, to_imgur=True, to_tumblr=True):
  """Run periodic search/download/extract_and_upload operations"""
  #print "Fetching new videos and consolidating queue..."
  #yt.populate_queue()
  #print "Downloading up to",max_downloads,"videos..."
  #yt.dl(max_downloads)
  extract_and_upload(vid_path, to_imgur, to_tumblr)

  if search_interval:
    search_timer = set_interval(search_interval, yt.populate_queue)
  if dl_interval:
    dl_timer = set_interval(dl_interval, yt.dl, max_downloads)
  if post_interval:
    post_timer = set_interval(post_interval, extract_and_upload, vid_path, to_imgur, to_tumblr)

if __name__ == '__main__':
  print "Running from console..."
  death_as_a_service()
<commit_msg>Stop getting videos every time script starts<commit_after>import os
from death_extractor import youtube as yt
from death_extractor import set_interval
from death_extractor import extract_and_upload

def death_as_a_service(vid_path = 'vids', post_interval=3600*2, search_interval=3600*6, dl_interval=3600*3, max_downloads=4, to_imgur=True, to_tumblr=True):
  """Run periodic search/download/extract_and_upload operations"""
  print "Fetching new videos and consolidating queue..."
  yt.populate_queue()
  if len([file for file in os.listdir(vid_path) if not file.endswith('part') and not file.startswith('.')]) < 4:
    print "Downloading up to",max_downloads,"videos..."
    yt.dl(max_downloads)
  extract_and_upload(vid_path, to_imgur, to_tumblr)

  if search_interval:
    search_timer = set_interval(search_interval, yt.populate_queue)
  if dl_interval:
    dl_timer = set_interval(dl_interval, yt.dl, max_downloads)
  if post_interval:
    post_timer = set_interval(post_interval, extract_and_upload, vid_path, to_imgur, to_tumblr)

if __name__ == '__main__':
  print "Running from console..."
  death_as_a_service()
<|endoftext|>


<commit_before>import re
import os
import sys
import time
import logging
import hashlib

from itertools import cycle
from datetime import datetime
from daftlistings import Daft, RentType
from elasticsearch import Elasticsearch

def main():
    host = os.environ.get('ES_HOST')
    index = os.environ.get('INDEX')
    doc_type = os.environ.get('DOC_TYPE')

    if not host:
        sys.exit('Invalid ES_HOST value: {}'.format(host))
    if not index:
        sys.exit('Invalid INDEX value: {}'.format(index))
    if not doc_type:
        sys.exit('Invalid DOC_TYPE value: {}'.format(doc_type))

    es = Elasticsearch([host])

    while True:
        for rent_type in RentType:
            try:
                for doc, id in documents(rent_type):
                    es.index(index,
                             doc_type,
                             doc,
                             id)
            except Exception as exp:
                logging.error('Unexpected error: {}. Sleeping a while'.format(exp))
                time.sleep(60)
        logging.info('Resting a bit')
        time.sleep(60 * 10)

def to_dict(listing):
    price = listing.get_price()
    price_number = None
    price_month = None

    try:
        price_number = int(re.sub('\D', '', price))
        if 'week' in price.lower():
            price_month = price_number * 4
        else:
            price_month = price_number
    except:
        pass

    return {
        'price': listing.get_price(),
        'price_number': price_number,
        'price_month': price_month,
        'price_change': listing.get_price_change(),
        'viewings': listing.get_upcoming_viewings(),
        'facilities': [l for sl in listing.get_facilities() for l in sl] if listing.get_facilities() else None,
        'features': listing.get_features(),
        'formalised_address': listing.get_formalised_address(),
        'address_line_1': listing.get_address_line_1(),
        'address_line_2': listing.get_address_line_2(),
        'town': listing.get_town(),
        'county': listing.get_county(),
        'listing_image': listing.get_listing_image(),
        'agent': listing.get_agent(),
        'agent_url': listing.get_agent_url(),
        'contact_number': listing.get_contact_number(),
        'daft_link': listing.get_daft_link(),
        'dwelling_type': listing.get_dwelling_type(),
        'posted_since': listing.get_posted_since(),
        'num_bedrooms': listing.get_num_bedrooms(),
        'num_bathrooms': listing.get_num_bathrooms(),
        'area_size': listing.get_area_size(),
        'timestamp': datetime.now()
    }

def documents(rent_type):
    for dwelling in dwellings(rent_type):
        url = dwelling.get('daft_link', '')
        if url:
            yield dwelling, hashlib.sha1(url).hexdigest()

def dwellings(rent_type):
    offset = 0
    daft = Daft()
    daft.set_listing_type(rent_type)
    daft.set_county('Dublin City')
    daft.set_offset(offset)

    listings = True
    while listings:
        listings = daft.get_listings()
        for listing in listings:
            yield to_dict(listing)

        offset += len(listings)
        daft.set_offset(offset)

if __name__ == '__main__':
    main()
<commit_msg>- Add date to logging - Add shuffling to rent types list<commit_after>import re
import os
import sys
import time
import random
import logging
import hashlib
import warnings

from datetime import datetime
from elasticsearch import Elasticsearch
from daftlistings import Daft, RentType

def main():
    host = os.environ.get('ES_HOST')
    index = os.environ.get('INDEX')
    doc_type = os.environ.get('DOC_TYPE')

    if not host:
        sys.exit('Invalid ES_HOST value: {}'.format(host))
    if not index:
        sys.exit('Invalid INDEX value: {}'.format(index))
    if not doc_type:
        sys.exit('Invalid DOC_TYPE value: {}'.format(doc_type))

    es = Elasticsearch([host])
    rent_types = list(RentType)
    while True:
        random.shuffle(rent_types)
        for rent_type in rent_types:
            try:
                for doc, id in documents(rent_type):
                    es.index(index,
                             doc_type,
                             doc,
                             id)
            except Exception as exp:
                logging.error('Unexpected error: {}. Sleeping a while'.format(exp))
                time.sleep(60)
        logging.info('Resting a bit')
        time.sleep(60 * 10)

def to_dict(listing):
    price = listing.get_price()
    price_number = None
    price_month = None

    try:
        price_number = int(re.sub('\D', '', price))
        if 'week' in price.lower():
            price_month = price_number * 4
        else:
            price_month = price_number
    except:
        pass

    return {
        'price': listing.get_price(),
        'price_number': price_number,
        'price_month': price_month,
        'price_change': listing.get_price_change(),
        'viewings': listing.get_upcoming_viewings(),
        'facilities': [l for sl in listing.get_facilities() for l in sl] if listing.get_facilities() else None,
        'features': listing.get_features(),
        'formalised_address': listing.get_formalised_address(),
        'address_line_1': listing.get_address_line_1(),
        'address_line_2': listing.get_address_line_2(),
        'town': listing.get_town(),
        'county': listing.get_county(),
        'listing_image': listing.get_listing_image(),
        'agent': listing.get_agent(),
        'agent_url': listing.get_agent_url(),
        'contact_number': listing.get_contact_number(),
        'daft_link': listing.get_daft_link(),
        'dwelling_type': listing.get_dwelling_type(),
        'posted_since': listing.get_posted_since(),
        'num_bedrooms': listing.get_num_bedrooms(),
        'num_bathrooms': listing.get_num_bathrooms(),
        'area_size': listing.get_area_size(),
        'timestamp': datetime.now()
    }

def documents(rent_type):
    for dwelling in dwellings(rent_type):
        url = dwelling.get('daft_link', '')
        if url:
            yield dwelling, hashlib.sha1(url).hexdigest()

def dwellings(rent_type):
    offset = 0
    daft = Daft()
    daft.set_listing_type(rent_type)
    daft.set_county('Dublin City')
    daft.set_offset(offset)

    listings = True
    while listings:
        listings = daft.get_listings()
        for listing in listings:
            yield to_dict(listing)

        offset += len(listings)
        daft.set_offset(offset)

if __name__ == '__main__':
    warnings.simplefilter('ignore')
    logging.basicConfig(format='%(asctime)s: %(message)s', level=logging.INFO)
    main()
<|endoftext|>


<commit_before>import socket
import threading
import re
import time

class ircOutputBuffer:
    # Delays consecutive messages by at least 1 second.
    # This prevents the bot spamming the IRC server.
    def __init__(self, irc):
        self.waiting = False
        self.irc = irc
        self.queue = []
        self.error = False
    def __pop(self):
        if len(self.queue) == 0:
            self.waiting = False
        else:
            self.sendImmediately(self.queue[0])
            self.queue = self.queue[1:]
            self.__startPopTimer()
    def __startPopTimer(self):
        self.timer = threading.Timer(1, self.__pop)
        self.timer.start()
    def sendBuffered(self, string):
        # Sends the given string after the rest of the messages in the buffer.
        # There is a 1 second gap between each message.
        if self.waiting:
            self.queue.append(string)
        else:
            self.waiting = True
            self.sendImmediately(string)
            self.__startPopTimer()
    def sendImmediately(self, string):
        # Sends the given string without buffering.
        if not self.error:
            try:
                self.irc.send(bytes(string) + b"\r\n")
            except socket.error, msg:
                self.error = True
                print "Output error", msg
                print "Was sending \"" + string + "\""
    def isInError(self):
        return self.error

class ircInputBuffer:
    # Keeps a record of the last line fragment received by the socket which is usually not a complete line.
    # It is prepended onto the next block of data to make a complete line.
    def __init__(self, irc):
        self.buffer = ""
        self.irc = irc
        self.lines = []
    def __recv(self):
        # Receives new data from the socket and splits it into lines.
        # Last (incomplete) line is kept for buffer purposes.
        try:
            data = self.buffer + self.irc.recv(4096)
        except socket.error, msg:
            raise socket.error, msg
        self.lines += data.split(b"\r\n")
        self.buffer = self.lines[len(self.lines) - 1]
        self.lines = self.lines[:len(self.lines) - 1]
    def getLine(self):
        # Returns the next line of IRC received by the socket.
        # Converts the received string to standard string format before returning.
        while len(self.lines) == 0:
            try:
                self.__recv()
            except socket.error, msg:
                raise socket.error, msg
            time.sleep(1);
        line = self.lines[0]
        self.lines = self.lines[1:]
        return str(line)

class ircBot(threading.Thread):
    def __init__(self, network, port, name, description):
        threading.Thread.__init__(self)
        self.keepGoing = True
        self.name = name
        self.desc = description
        self.network = network
        self.port = port
        self.identifyNickCommands = []
        self.identifyLock = False
        self.binds = []
        self.debug = False
    # PRIVATE FUNCTIONS
    def __identAccept(self, nick):
        # Calls the given "approved" callbacks for all functions called by that nick.
        i = 0
        while i < len(self.identifyNickCommands):
            (nickName, accept, acceptParams, reject, rejectParams) = self.identifyNickCommands[i]
            if nick == nickName:
                accept(*acceptParams)
                self.identifyNickCommands.pop(i)
            else:
                i += 1
    def __identReject(self, nick):
        # Calls the given "denied" callback for all functions called by that nick.
        i = 0
        while i < len(self.identifyNickCommands):
            (nickName, accept, acceptParams, reject, rejectParams) = self.identifyNickCommands[i]
            if nick == nickName:
                reject(*rejectParams)
                self.identifyNickCommands.pop(i)
            else:
                i += 1
    def __callBind(self, msgtype, sender, headers, message):
        # Calls the function associated with the given msgtype.
        for (messageType, callback) in self.binds:
            if (messageType == msgtype):
                callback(sender, headers, message)
    def __processLine(self, line):
        # Does most of the parsing of the line received from the IRC network.
        secondColon = line[1:].find(":") + 1
        if secondColon == 0:
            headers = line[1:].strip().split(" ")
            message = ""
        else:
            headers = line[1:secondColon].strip().split(" ")
            message = line[secondColon+1:]
        sender = headers[0]
        if len(headers) < 2:
            self.__debugPrint("Unhelpful number of messages in message: \"" + line + "\"")
        else:
            if "!" in sender:
                cut = headers[0].find('!')
                if cut != -1:
                    sender = sender[:cut]
                msgtype = headers[1]
                if msgtype == "PRIVMSG" and message.startswith("ACTION ") and message.endswith(""):
                    msgtype = "ACTION"
                    message = message[8:-1]
                self.__callBind(msgtype, sender, headers[2:], message)
            else:
                self.__debugPrint("[" + headers[1] + "] " + message)
                if (headers[1] == "307" or headers[1] == "330") and len(headers) >= 4:
                    self.__identAccept(headers[3])
                if headers[1] == "318" and len(headers) >= 4:
                    self.__identReject(headers[3])
                    #identifys the next user in the nick commands list
                    if len(self.identifyNickCommands) == 0:
                        self.identifyLock = False
                    else:
                        self.outBuf.sendBuffered("WHOIS " + self.identifyNickCommands[0][0])
                self.__callBind(headers[1], sender, headers[2:], message)

    def __debugPrint(self, s):
        if self.debug:
            print s
    # PUBLIC FUNCTIONS
    def ban(self, banMask, channel, reason):
        self.__debugPrint("Banning " + banMask + "...")
        self.outBuf.sendBuffered("MODE +b " + channel + " " + banMask)
        self.kick(nick, channel, reason)
    def bind(self, msgtype, callback):
        for i in xrange(0, len(self.binds)):
            if self.binds[i][0] == msgtype:
                self.binds.remove(i)
        self.binds.append((msgtype, callback))
    def connect(self):
        self.__debugPrint("Connecting...")
        self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.irc.connect((self.network, self.port))
        self.inBuf = ircInputBuffer(self.irc)
        self.outBuf = ircOutputBuffer(self.irc)
        self.outBuf.sendBuffered("NICK " + self.name)
        self.outBuf.sendBuffered("USER " + self.name + " " + self.name + " " + self.name + " :" + self.desc)
    def debugging(self, state):
        self.debug = state
    def disconnect(self, qMessage):
        self.__debugPrint("Disconnecting...")
        self.outBuf.sendBuffered("QUIT :" + qMessage)
        self.irc.close()
    def identify(self, nick, approvedFunc, approvedParams, deniedFunc, deniedParams):
        self.__debugPrint("Verifying " + nick + "...")
        self.identifyNickCommands += [(nick, approvedFunc, approvedParams, deniedFunc, deniedParams)]
        if not self.identifyLock:
            self.outBuf.sendBuffered("WHOIS " + nick)
            self.identifyLock = True
    def joinchan(self, channel):
        self.__debugPrint("Joining " + channel + "...")
        self.outBuf.sendBuffered("JOIN " + channel)
    def kick(self, nick, channel, reason):
        self.__debugPrint("Kicking " + nick + "...")
        self.outBuf.sendBuffered("KICK " + channel + " " + nick + " :" + reason)
    def reconnect(self):
        self.disconnect("Reconnecting")
        self.__debugPrint("Pausing before reconnecting...")
        time.sleep(5)
        self.connect()
    def run(self):
        self.__debugPrint("Bot is now running.")
        self.connect()
        while self.keepGoing:
            line = ""
            while len(line) == 0:
                try:
                    line = self.inBuf.getLine()
                except socket.error, msg:
                    print "Input error", msg
                    self.reconnect()
            if line.startswith("PING"):
                self.outBuf.sendImmediately("PONG " + line.split()[1])
            else:
                self.__processLine(line)
            if self.outBuf.isInError():
                self.reconnect()
    def say(self, recipient, message):
        self.outBuf.sendBuffered("PRIVMSG " + recipient + " :" + message)
    def send(self, string):
        self.outBuf.sendBuffered(string)
    def stop(self):
        self.keepGoing = False
    def unban(self, banMask, channel):
        self.__debugPrint("Unbanning " + banMask + "...")
        self.outBuf.sendBuffered("MODE -b " + channel + " " + banMask)

<commit_msg>Fixed the way lines are processed to allow for messages from a user with an IPv6 domain. Previously, lines were split by finding the ":" character and this would not work for IPv6 addresses.<commit_after>import socket
import threading
import re
import time

class ircOutputBuffer:
    # Delays consecutive messages by at least 1 second.
    # This prevents the bot spamming the IRC server.
    def __init__(self, irc):
        self.waiting = False
        self.irc = irc
        self.queue = []
        self.error = False
    def __pop(self):
        if len(self.queue) == 0:
            self.waiting = False
        else:
            self.sendImmediately(self.queue[0])
            self.queue = self.queue[1:]
            self.__startPopTimer()
    def __startPopTimer(self):
        self.timer = threading.Timer(1, self.__pop)
        self.timer.start()
    def sendBuffered(self, string):
        # Sends the given string after the rest of the messages in the buffer.
        # There is a 1 second gap between each message.
        if self.waiting:
            self.queue.append(string)
        else:
            self.waiting = True
            self.sendImmediately(string)
            self.__startPopTimer()
    def sendImmediately(self, string):
        # Sends the given string without buffering.
        if not self.error:
            try:
                self.irc.send(bytes(string) + b"\r\n")
            except socket.error, msg:
                self.error = True
                print "Output error", msg
                print "Was sending \"" + string + "\""
    def isInError(self):
        return self.error

class ircInputBuffer:
    # Keeps a record of the last line fragment received by the socket which is usually not a complete line.
    # It is prepended onto the next block of data to make a complete line.
    def __init__(self, irc):
        self.buffer = ""
        self.irc = irc
        self.lines = []
    def __recv(self):
        # Receives new data from the socket and splits it into lines.
        # Last (incomplete) line is kept for buffer purposes.
        try:
            data = self.buffer + self.irc.recv(4096)
        except socket.error, msg:
            raise socket.error, msg
        self.lines += data.split(b"\r\n")
        self.buffer = self.lines[len(self.lines) - 1]
        self.lines = self.lines[:len(self.lines) - 1]
    def getLine(self):
        # Returns the next line of IRC received by the socket.
        # Converts the received string to standard string format before returning.
        while len(self.lines) == 0:
            try:
                self.__recv()
            except socket.error, msg:
                raise socket.error, msg
            time.sleep(1);
        line = self.lines[0]
        self.lines = self.lines[1:]
        return str(line)

class ircBot(threading.Thread):
    def __init__(self, network, port, name, description):
        threading.Thread.__init__(self)
        self.keepGoing = True
        self.name = name
        self.desc = description
        self.network = network
        self.port = port
        self.identifyNickCommands = []
        self.identifyLock = False
        self.binds = []
        self.debug = False
    # PRIVATE FUNCTIONS
    def __identAccept(self, nick):
        """ Executes all the callbacks that have been approved for this nick
    	"""
        i = 0
        while i < len(self.identifyNickCommands):
            (nickName, accept, acceptParams, reject, rejectParams) = self.identifyNickCommands[i]
            if nick == nickName:
                accept(*acceptParams)
                self.identifyNickCommands.pop(i)
            else:
                i += 1
    def __identReject(self, nick):
        # Calls the given "denied" callback for all functions called by that nick.
        i = 0
        while i < len(self.identifyNickCommands):
            (nickName, accept, acceptParams, reject, rejectParams) = self.identifyNickCommands[i]
            if nick == nickName:
                reject(*rejectParams)
                self.identifyNickCommands.pop(i)
            else:
                i += 1
    def __callBind(self, msgtype, sender, headers, message):
        # Calls the function associated with the given msgtype.
        for (messageType, callback) in self.binds:
            if (messageType == msgtype):
                callback(sender, headers, message)
    def __processLine(self, line):
        # If a message comes from another user, it will have an @ symbol
        if "@" in line:
            # Location of the @ symbol in the line (proceeds sender's domain)
            at = line.find("@")
            # Location of the first gap, this immediately follows the sender's domain
            gap = line[at:].find(" ") + at + 1
            lastColon = line[gap+1:].find(":") + 2 + gap
        else:
            lastColon = line[1:].find(":") + 1

        # Does most of the parsing of the line received from the IRC network.
        # if there is no message to the line. ie. only one colon at the start of line
        if ":" not in line[1:]:
            headers = line[1:].strip().split(" ")
            message = ""
        else:
            # Split everything up to the lastColon (ie. the headers)
            headers = line[1:lastColon-1].strip().split(" ")
            message = line[lastColon:]

        sender = headers[0]
        if len(headers) < 2:
            self.__debugPrint("Unhelpful number of messages in message: \"" + line + "\"")
        else:
            if "!" in sender:
                cut = headers[0].find('!')
                if cut != -1:
                    sender = sender[:cut]
                msgtype = headers[1]
                if msgtype == "PRIVMSG" and message.startswith("ACTION ") and message.endswith(""):
                    msgtype = "ACTION"
                    message = message[8:-1]
                self.__callBind(msgtype, sender, headers[2:], message)
            else:
                self.__debugPrint("[" + headers[1] + "] " + message)
                if (headers[1] == "307" or headers[1] == "330") and len(headers) >= 4:
                    self.__identAccept(headers[3])
                if headers[1] == "318" and len(headers) >= 4:
                    self.__identReject(headers[3])
                    #identifies the next user in the nick commands list
                    if len(self.identifyNickCommands) == 0:
                        self.identifyLock = False
                    else:
                        self.outBuf.sendBuffered("WHOIS " + self.identifyNickCommands[0][0])
                self.__callBind(headers[1], sender, headers[2:], message)

    def __debugPrint(self, s):
        if self.debug:
            print s
    # PUBLIC FUNCTIONS
    def ban(self, banMask, channel, reason):
        self.__debugPrint("Banning " + banMask + "...")
        self.outBuf.sendBuffered("MODE +b " + channel + " " + banMask)
        self.kick(nick, channel, reason)

    def bind(self, msgtype, callback):
        # Check if the msgtype already exists
        for i in xrange(0, len(self.binds)):
            # Remove msgtype if it has already been "binded" to
            if self.binds[i][0] == msgtype:
                self.binds.remove(i)
        self.binds.append((msgtype, callback))

    def connect(self):
        self.__debugPrint("Connecting...")
        self.irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.irc.connect((self.network, self.port))
        self.inBuf = ircInputBuffer(self.irc)
        self.outBuf = ircOutputBuffer(self.irc)
        self.outBuf.sendBuffered("NICK " + self.name)
        self.outBuf.sendBuffered("USER " + self.name + " " + self.name + " " + self.name + " :" + self.desc)
    def debugging(self, state):
        self.debug = state
    def disconnect(self, qMessage):
        self.__debugPrint("Disconnecting...")
        self.outBuf.sendBuffered("QUIT :" + qMessage)
        self.irc.close()
    def identify(self, nick, approvedFunc, approvedParams, deniedFunc, deniedParams):
        self.__debugPrint("Verifying " + nick + "...")
        self.identifyNickCommands += [(nick, approvedFunc, approvedParams, deniedFunc, deniedParams)]
        if not self.identifyLock:
            self.outBuf.sendBuffered("WHOIS " + nick)
            self.identifyLock = True
    def joinchan(self, channel):
        self.__debugPrint("Joining " + channel + "...")
        self.outBuf.sendBuffered("JOIN " + channel)
    def kick(self, nick, channel, reason):
        self.__debugPrint("Kicking " + nick + "...")
        self.outBuf.sendBuffered("KICK " + channel + " " + nick + " :" + reason)
    def reconnect(self):
        self.disconnect("Reconnecting")
        self.__debugPrint("Pausing before reconnecting...")
        time.sleep(5)
        self.connect()
    def run(self):
        self.__debugPrint("Bot is now running.")
        self.connect()
        while self.keepGoing:
            line = ""
            while len(line) == 0:
                try:
                    line = self.inBuf.getLine()
                except socket.error, msg:
                    print "Input error", msg
                    self.reconnect()
            if line.startswith("PING"):
                self.outBuf.sendImmediately("PONG " + line.split()[1])
            else:
                self.__processLine(line)
            if self.outBuf.isInError():
                self.reconnect()
    def say(self, recipient, message):
        self.outBuf.sendBuffered("PRIVMSG " + recipient + " :" + message)
    def send(self, string):
        self.outBuf.sendBuffered(string)
    def stop(self):
        self.keepGoing = False
    def unban(self, banMask, channel):
        self.__debugPrint("Unbanning " + banMask + "...")
        self.outBuf.sendBuffered("MODE -b " + channel + " " + banMask)

<|endoftext|>


<commit_before>import datetime

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.core.urlresolvers import reverse
from django.db import models
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _

from iris.conf import settings

class TopicManager(models.Manager):

    def with_participant(self, obj):
        content_type = ContentType.objects.get_for_model(obj)
        return self.filter(
            participants__content_type__pk=content_type.id,
            participants__object_id=obj.id,
        )

class Topic(models.Model):
    """A topic of conversation."""

    subject = models.CharField(max_length=255)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(blank=True, null=True, db_index=True)

    creator_content_type = models.ForeignKey(ContentType, blank=True, null=True)
    creator_object_id = models.PositiveIntegerField(blank=True, null=True)
    creator = generic.GenericForeignKey("creator_content_type", "creator_object_id")

    objects = TopicManager()

    class Meta:
        ordering = ('modified', )
        permissions = (
            ('view_topic', 'Can view topic(s).'),
            ('join_topic', 'Can participate in topic(s).'),
            ('add_to_topic', 'Can add items to topic(s).'),
        )

    def __unicode__(self):
        return self.subject

    def get_absolute_url(self):
        return reverse('iris_topic_slug', kwargs=dict(
            topic_id=self.id,
            slug=slugify(self.subject),
        ))

    def add_item(self, creator, obj):
        """Add the object as an item, returning a saved item."""
        item = Item(
            topic=self,
            creator=creator,
            content=obj,
        )
        item.save()
        return item

    def add_participant(self, creator, obj):
        """Add the object as a participant, returning the ParticipantJoin item created."""
        participant = Participant(
            topic=self,
            content=obj,
        )
        participant.save()
        joined = ParticipantJoin(
            participant=participant,
        )
        joined.save()
        return self.add_item(creator, joined)

    def get_participant(self, obj):
        """Get participation information for the given object."""
        content_type = ContentType.objects.get_for_model(obj)
        try:
            return Participant.objects.get(
                topic=self,
                content_type=content_type,
                object_id=obj.id,
            )
        except Participant.DoesNotExist:
            return None

    def has_participant(self, obj):
        if not isinstance(obj, models.Model):
            return False
        participant = self.get_participant(obj)
        return participant is not None

    def item_last_read_by(self, obj):
        content_type = ContentType.objects.get_for_model(obj)
        participant = Participant.objects.get(
            topic=self,
            content_type=content_type,
            object_id=obj.id,
        )
        return participant.item_last_read

    def participants_of_type(self, model_class):
        content_type = ContentType.objects.get_for_model(model_class)
        return self.participants.filter(
            content_type=content_type,
        )

class Item(models.Model):
    """An item in a conversation."""

    topic = models.ForeignKey('Topic', related_name='items', db_index=True)
    created = models.DateTimeField(default=datetime.datetime.now, db_index=True) # don't use auto_now_add since we sometimes want to override this on create

    content_type = models.ForeignKey(ContentType, blank=True, null=True, related_name='+')
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content = generic.GenericForeignKey("content_type", "object_id")

    creator_content_type = models.ForeignKey(ContentType, blank=True, null=True, related_name='+')
    creator_object_id = models.PositiveIntegerField(blank=True, null=True)
    creator = generic.GenericForeignKey("creator_content_type", "creator_object_id")

    class Meta:
        ordering = ('created',)

    def __unicode__(self):
        return u"{0}: {1}".format(self.creator, self.content)

    def get_absolute_url(self):
        """Return the topic's absolute url with a query string and hash for this item."""
        return '{0}?i={1}#i{1}'.format(self.topic.get_absolute_url(), self.id)

    def get_items_after_url(self):
        """Return an URL that will return all of the items in the topic after this item."""
        return reverse('iris_items_after', kwargs=dict(
            topic_id=self.topic_id,
            after_item_id=self.id,
        ))

    def save(self, *args, **kwargs):
        super(Item, self).save(*args, **kwargs)
        topic = self.topic
        topic.modified = self.created
        topic.save()

    def css_class(self):
        """Return a CSS class corresponding to this item's content type."""
        ct = self.content_type
        return '{0}-{1}'.format(ct.app_label, ct.model)

    def view_template(self):
        """Return the name of the view template according to the content type."""
        ct = self.content_type
        return 'iris/items/{0}.{1}.view.html'.format(ct.app_label, ct.model)

class Participant(models.Model):
    """A user or other object participating in a topic."""

    topic = models.ForeignKey('Topic', related_name='participants')

    content_type = models.ForeignKey(ContentType, blank=True, null=True)
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content = generic.GenericForeignKey("content_type", "object_id")

    item_last_read = models.ForeignKey(Item, blank=True, null=True)

    class Meta:
        pass

    def __unicode__(self):
        return unicode(self.content)

class ParticipantJoin(models.Model):
    """Information about someone joining a conversation."""

    participant = models.ForeignKey('Participant', related_name='+')

    class Meta:
        pass

    def __unicode__(self):
        return u"{0} joined".format(self.participant)
<commit_msg>Allow latest() on Item-based querysets<commit_after>import datetime

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.core.urlresolvers import reverse
from django.db import models
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _

from iris.conf import settings

class TopicManager(models.Manager):

    def with_participant(self, obj):
        content_type = ContentType.objects.get_for_model(obj)
        return self.filter(
            participants__content_type__pk=content_type.id,
            participants__object_id=obj.id,
        )

class Topic(models.Model):
    """A topic of conversation."""

    subject = models.CharField(max_length=255)
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(blank=True, null=True, db_index=True)

    creator_content_type = models.ForeignKey(ContentType, blank=True, null=True)
    creator_object_id = models.PositiveIntegerField(blank=True, null=True)
    creator = generic.GenericForeignKey("creator_content_type", "creator_object_id")

    objects = TopicManager()

    class Meta:
        ordering = ('modified', )
        permissions = (
            ('view_topic', 'Can view topic(s).'),
            ('join_topic', 'Can participate in topic(s).'),
            ('add_to_topic', 'Can add items to topic(s).'),
        )

    def __unicode__(self):
        return self.subject

    def get_absolute_url(self):
        return reverse('iris_topic_slug', kwargs=dict(
            topic_id=self.id,
            slug=slugify(self.subject),
        ))

    def add_item(self, creator, obj):
        """Add the object as an item, returning a saved item."""
        item = Item(
            topic=self,
            creator=creator,
            content=obj,
        )
        item.save()
        return item

    def add_participant(self, creator, obj):
        """Add the object as a participant, returning the ParticipantJoin item created."""
        participant = Participant(
            topic=self,
            content=obj,
        )
        participant.save()
        joined = ParticipantJoin(
            participant=participant,
        )
        joined.save()
        return self.add_item(creator, joined)

    def get_participant(self, obj):
        """Get participation information for the given object."""
        content_type = ContentType.objects.get_for_model(obj)
        try:
            return Participant.objects.get(
                topic=self,
                content_type=content_type,
                object_id=obj.id,
            )
        except Participant.DoesNotExist:
            return None

    def has_participant(self, obj):
        if not isinstance(obj, models.Model):
            return False
        participant = self.get_participant(obj)
        return participant is not None

    def item_last_read_by(self, obj):
        content_type = ContentType.objects.get_for_model(obj)
        participant = Participant.objects.get(
            topic=self,
            content_type=content_type,
            object_id=obj.id,
        )
        return participant.item_last_read

    def participants_of_type(self, model_class):
        content_type = ContentType.objects.get_for_model(model_class)
        return self.participants.filter(
            content_type=content_type,
        )

class Item(models.Model):
    """An item in a conversation."""

    topic = models.ForeignKey('Topic', related_name='items', db_index=True)
    created = models.DateTimeField(default=datetime.datetime.now, db_index=True) # don't use auto_now_add since we sometimes want to override this on create

    content_type = models.ForeignKey(ContentType, blank=True, null=True, related_name='+')
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content = generic.GenericForeignKey("content_type", "object_id")

    creator_content_type = models.ForeignKey(ContentType, blank=True, null=True, related_name='+')
    creator_object_id = models.PositiveIntegerField(blank=True, null=True)
    creator = generic.GenericForeignKey("creator_content_type", "creator_object_id")

    class Meta:
        get_latest_by = 'created'
        ordering = ('created',)

    def __unicode__(self):
        return u"{0}: {1}".format(self.creator, self.content)

    def get_absolute_url(self):
        """Return the topic's absolute url with a query string and hash for this item."""
        return '{0}?i={1}#i{1}'.format(self.topic.get_absolute_url(), self.id)

    def get_items_after_url(self):
        """Return an URL that will return all of the items in the topic after this item."""
        return reverse('iris_items_after', kwargs=dict(
            topic_id=self.topic_id,
            after_item_id=self.id,
        ))

    def save(self, *args, **kwargs):
        super(Item, self).save(*args, **kwargs)
        topic = self.topic
        topic.modified = self.created
        topic.save()

    def css_class(self):
        """Return a CSS class corresponding to this item's content type."""
        ct = self.content_type
        return '{0}-{1}'.format(ct.app_label, ct.model)

    def view_template(self):
        """Return the name of the view template according to the content type."""
        ct = self.content_type
        return 'iris/items/{0}.{1}.view.html'.format(ct.app_label, ct.model)

class Participant(models.Model):
    """A user or other object participating in a topic."""

    topic = models.ForeignKey('Topic', related_name='participants')

    content_type = models.ForeignKey(ContentType, blank=True, null=True)
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content = generic.GenericForeignKey("content_type", "object_id")

    item_last_read = models.ForeignKey(Item, blank=True, null=True)

    class Meta:
        pass

    def __unicode__(self):
        return unicode(self.content)

class ParticipantJoin(models.Model):
    """Information about someone joining a conversation."""

    participant = models.ForeignKey('Participant', related_name='+')

    class Meta:
        pass

    def __unicode__(self):
        return u"{0} joined".format(self.participant)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
'''
Smoothtest

Copyright (c) 2014, Juju inc.
Copyright (c) 2011-2013, Joaquin G. Duo

'''
import rel_imp; rel_imp.init()
from ..base import SmoothTestBase
from collections import namedtuple
import multiprocessing
from types import MethodType, FunctionType
import sys
import traceback

AutotestCmd = namedtuple('AutotestCmd', 'cmd args kwargs')
AutotestAnswer = namedtuple('AutotestAnswer', 'sent_cmd result error')

TestResult = namedtuple('TestResult', 'testsRun errors failures')
TestException = namedtuple('TestException', 'msg repr traceback')

class AutoTestBase(SmoothTestBase):
    def reprex(self, e, print_=True):
        #TODO: shuoldn't format last exception,but passed one
        if print_:
            traceback.print_exc()
        return TestException(str(e), repr(e), traceback.format_exc())

class ChildBase(AutoTestBase):
    _kill_command = 'raise SystemExit'
    _kill_answer = 'doing SystemExit'
    def _dispatch_cmds(self, io_conn, duplex=True):
        commands = io_conn.recv()
        send = lambda msg: duplex and io_conn.send(msg)
        answers = []
        for cmd in commands:
            self.log.d('Receiving command: {cmd!r}'.format(cmd=cmd))
            if cmd.cmd == self._kill_command:
                self.log.d('Start killing myself...')
                self._receive_kill(*cmd.args, **cmd.kwargs)
                answers.append(AutotestAnswer(cmd, self._kill_answer, None))
                send(answers)
                io_conn.close()
                raise SystemExit(0)
            result = error = None
            try:
                result = getattr(self, cmd.cmd)(*cmd.args, **cmd.kwargs)
            except Exception as e:
                error = self.reprex(e)
            answers.append(AutotestAnswer(cmd, result, error))
        self.log.d('Answering {answers}'.format(answers=answers))
        send(answers)
        return answers

    def to_pickable_result(self, result):
        errors = [repr(e) for e in result.errors]
        failures = [repr(f) for f in result.failures]
        return TestResult(result.testsRun, errors, failures)

    def _receive_kill(self, *args, **kwargs):
        pass

    def _get_cmd_str(self, cmd):
        if isinstance(cmd, MethodType):
            cmd = cmd.im_func.func_name
        if isinstance(cmd, FunctionType):
            cmd = cmd.func_name
        return cmd

    def cmd(self, cmd, *args, **kwargs):
        #Make it ready for sending
        return [self._cmd(self._get_cmd_str(cmd), *args, **kwargs)]

    def _cmd(self, cmd, *args, **kwargs):
        #use when queying several commands
        return AutotestCmd(cmd, args, kwargs)

class TargetFunction(SmoothTestBase):
    def __init__(self, callback, parent_conn, child_conn, pre, close_stdin=False):
        self.callback = callback
        self.parent_conn = parent_conn
        self.conn = child_conn
        self.pre = pre
        self.close_stdin = close_stdin

    def __call__(self):
        self.parent_conn.close()
        if self.close_stdin:
            self.log.d('Closing stdin')
            sys.stdin.close()
        self.log.set_pre_post(pre=self.pre)
        self.log.d('Forked process started...')
        self.callback(self.conn)

class ParentBase(ChildBase):
    def start_subprocess(self, callback, pre='', close_stdin=True):
        parent, child = multiprocessing.Pipe()
        #Add space if defined
        pre = pre if not pre else pre + ' '
        #Windows needs target to be pickable
        target = TargetFunction(callback, parent, child, pre, close_stdin)

        self._subprocess = multiprocessing.Process(target=target)
        self._subprocess.start()
        self._subprocess_conn = parent
        child.close()

    def restart_subprocess(self, callback):
        self.kill(block=True, timeout=self._timeout)
        self.start_subprocess(callback)

    def kill(self, block=False, timeout=None):
        return self._kill_subprocess(block, timeout)

    def send(self, cmd, *args, **kwargs):
        self._subprocess_conn.send(self.cmd(cmd, *args, **kwargs))

    def recv(self):
        return self._subprocess_conn.recv()

    def send_recv(self, cmd, *args, **kwargs):
        self.send(cmd, *args, **kwargs)
        return self._get_answer(self.recv(), cmd)

    def call_remote(self, cmd, *args, **kwargs):
        return self.send_recv(cmd, *args, **kwargs).result

    def poll(self):
        return self._subprocess_conn.poll()

    def fmt_answers(self, msg):
        output = ''
        for ans in msg:
            output += str(self._fmt_answer(ans)) + '\n'
        return output

    def _fmt_answer(self, answer):
        return 'cmd:%s result:%r error:%r' % (answer.sent_cmd.cmd,
                                              answer.result, answer.error)

    def _get_answer(self, answers, cmd):
        cmd = self._get_cmd_str(cmd)
        # Get the latest cmd matching
        for ans in reversed(answers):
            if ans.sent_cmd.cmd == cmd:
                return ans

    def get_conn(self):
        return self._subprocess_conn

    def _kill_subprocess(self, block=False, timeout=None):
        self.log.d('Killing Slave child with pid %r.' % self._subprocess.ident)
        answer = None
        def end():
            self._subprocess.join()
            self._suprocess = None
            self._subprocess_conn.close()
            self._subprocess_conn = None

        if not self._subprocess:
            return answer

        if not self._subprocess.is_alive():
            self.log.w('Child terminated by himself.'
                       ' Exitcode: %r' % self._subprocess.exitcode)
            end()
            return answer

        self.send(self._kill_command)

        if not block:
            return answer

        if self._subprocess_conn.poll(timeout):
            answer = self._subprocess_conn.recv()
            answer = self._get_answer(answer, self._kill_command)
            assert answer, 'No answer for the kill command sent.'
            self.log.d('Received kill answer %s' % self._fmt_answer(answer))
            pid, status = self._subprocess.ident, self._subprocess.exitcode
            self.log.i('Child with pid {pid} gently terminated with exit '
                       'status {status}.'.format(pid=pid, status=status))
        else:
            self._subprocess.terminate()
            pid, status = self._subprocess.ident, self._subprocess.exitcode
            self.log.w('Child pid {pid} killed by force with exit status {status}.'
                       ''.format(pid=pid, status=status))
        end()
        return answer

def smoke_test_module():
    class TR(object):
        def test(self):
            pass
    base = ChildBase()
    base.log.d(base.cmd(TR.test))
    base.log.d('Debug')
    base.log.i('Info')
    test_path = 'smoothtest.tests.example.Example.Example.test_example'
    base.log.i(base.split_test_path(test_path))
    base.log.i(base.split_test_path(test_path, meth=True))
    class PBTest(ParentBase):
        def dummy_cmd(self, *args, **kwargs):
            self.log.d(str(args))
            self.log.d(str(kwargs))
            return 'dummy answer'
    pb = PBTest()
    def build_callback(secs):
        def callback(conn):
            import time
            pb.log('Child callback')
            time.sleep(secs)
            while True:
                pb._dispatch_cmds(conn)
        return callback
    pb.start_subprocess(build_callback(0), pre='Child1')
    args = (1, 'two', set())
    kwargs = dict(example=30)
    pb.send(pb.dummy_cmd, *args, **kwargs)
    ans = pb.recv()[0]
    pb.log.d(ans)
    assert ans.sent_cmd.args == args
    assert ans.sent_cmd.kwargs == kwargs
    pb.kill(block=True, timeout=0.1)
    pb.start_subprocess(build_callback(0.5), pre='Child2')
    pb.kill(block=True, timeout=0.1)

if __name__ == "__main__":
    smoke_test_module()
<commit_msg>Clean code.<commit_after># -*- coding: utf-8 -*-
'''
Smoothtest

Copyright (c) 2014, Juju inc.
Copyright (c) 2011-2013, Joaquin G. Duo

'''
import rel_imp; rel_imp.init()
from ..base import SmoothTestBase
from collections import namedtuple
import multiprocessing
from types import MethodType, FunctionType
import sys
import traceback

AutotestCmd = namedtuple('AutotestCmd', 'cmd args kwargs')
AutotestAnswer = namedtuple('AutotestAnswer', 'sent_cmd result error')

TestResult = namedtuple('TestResult', 'testsRun errors failures')
TestException = namedtuple('TestException', 'msg repr traceback')

class AutoTestBase(SmoothTestBase):
    def reprex(self, e, print_=True):
        #TODO: shuoldn't format last exception,but passed one
        if print_:
            traceback.print_exc()
        return TestException(str(e), repr(e), traceback.format_exc())

class ChildBase(AutoTestBase):
    _kill_command = 'raise SystemExit'
    _kill_answer = 'doing SystemExit'
    def _dispatch_cmds(self, io_conn, duplex=True):
        commands = io_conn.recv()
        send = lambda msg: duplex and io_conn.send(msg)
        answers = []
        for cmd in commands:
            self.log.d('Receiving command: {cmd!r}'.format(cmd=cmd))
            if cmd.cmd == self._kill_command:
                self.log.d('Start killing myself...')
                self._receive_kill(*cmd.args, **cmd.kwargs)
                answers.append(AutotestAnswer(cmd, self._kill_answer, None))
                send(answers)
                io_conn.close()
                raise SystemExit(0)
            result = error = None
            try:
                result = getattr(self, cmd.cmd)(*cmd.args, **cmd.kwargs)
            except Exception as e:
                error = self.reprex(e)
            answers.append(AutotestAnswer(cmd, result, error))
        self.log.d('Answering {answers}'.format(answers=answers))
        send(answers)
        return answers

    def to_pickable_result(self, result):
        errors = [repr(e) for e in result.errors]
        failures = [repr(f) for f in result.failures]
        return TestResult(result.testsRun, errors, failures)

    def _receive_kill(self, *args, **kwargs):
        pass

    def _get_cmd_str(self, cmd):
        if isinstance(cmd, MethodType):
            cmd = cmd.im_func.func_name
        if isinstance(cmd, FunctionType):
            cmd = cmd.func_name
        return cmd

    def cmd(self, cmd, *args, **kwargs):
        #Make it ready for sending
        return [self._cmd(self._get_cmd_str(cmd), *args, **kwargs)]

    def _cmd(self, cmd, *args, **kwargs):
        #use when queying several commands
        return AutotestCmd(cmd, args, kwargs)

class TargetFunction(SmoothTestBase):
    def __init__(self, callback, parent_conn, child_conn, pre, close_stdin=False):
        self.callback = callback
        self.parent_conn = parent_conn
        self.conn = child_conn
        self.pre = pre
        self.close_stdin = close_stdin

    def __call__(self):
        self.parent_conn.close()
        if self.close_stdin:
            self.log.d('Closing stdin')
            sys.stdin.close()
        self.log.set_pre_post(pre=self.pre)
        self.log.d('Forked process started...')
        self.callback(self.conn)

class ParentBase(ChildBase):
    def start_subprocess(self, callback, pre='', close_stdin=True):
        parent, child = multiprocessing.Pipe()
        #Add space if defined
        pre = pre if not pre else pre + ' '
        #Windows needs target to be pickable
        target = TargetFunction(callback, parent, child, pre, close_stdin)

        self._subprocess = multiprocessing.Process(target=target)
        self._subprocess.start()
        self._subprocess_conn = parent
        child.close()

    def restart_subprocess(self, callback):
        self.kill(block=True, timeout=self._timeout)
        self.start_subprocess(callback)

    def kill(self, block=False, timeout=None):
        return self._kill_subprocess(block, timeout)

    def send(self, cmd, *args, **kwargs):
        self._subprocess_conn.send(self.cmd(cmd, *args, **kwargs))

    def recv(self):
        return self._subprocess_conn.recv()

    def send_recv(self, cmd, *args, **kwargs):
        self.send(cmd, *args, **kwargs)
        return self.recv()

    def call_remote(self, cmd, *args, **kwargs):
        ans = self.send_recv(cmd, *args, **kwargs)
        return self._get_answer(ans, cmd).result

    def poll(self):
        return self._subprocess_conn.poll()

    def fmt_answers(self, msg):
        output = ''
        for ans in msg:
            output += str(self._fmt_answer(ans)) + '\n'
        return output

    def _fmt_answer(self, answer):
        return 'cmd:%s result:%r error:%r' % (answer.sent_cmd.cmd,
                                              answer.result, answer.error)

    def _get_answer(self, answers, cmd):
        cmd = self._get_cmd_str(cmd)
        # Get the latest cmd matching
        for ans in reversed(answers):
            if ans.sent_cmd.cmd == cmd:
                return ans

    def get_conn(self):
        return self._subprocess_conn

    def _kill_subprocess(self, block=False, timeout=None):
        self.log.d('Killing Slave child with pid %r.' % self._subprocess.ident)
        answer = None
        def end():
            self._subprocess.join()
            self._suprocess = None
            self._subprocess_conn.close()
            self._subprocess_conn = None

        if not self._subprocess:
            return answer

        if not self._subprocess.is_alive():
            self.log.w('Child terminated by himself.'
                       ' Exitcode: %r' % self._subprocess.exitcode)
            end()
            return answer

        self.send(self._kill_command)

        if not block:
            return answer

        if self._subprocess_conn.poll(timeout):
            answer = self._subprocess_conn.recv()
            answer = self._get_answer(answer, self._kill_command)
            assert answer, 'No answer for the kill command sent.'
            self.log.d('Received kill answer %s' % self._fmt_answer(answer))
            pid, status = self._subprocess.ident, self._subprocess.exitcode
            self.log.i('Child with pid {pid} gently terminated with exit '
                       'status {status}.'.format(pid=pid, status=status))
        else:
            self._subprocess.terminate()
            pid, status = self._subprocess.ident, self._subprocess.exitcode
            self.log.w('Child pid {pid} killed by force with exit status {status}.'
                       ''.format(pid=pid, status=status))
        end()
        return answer

def smoke_test_module():
    class TR(object):
        def test(self):
            pass
    base = ChildBase()
    base.log.d(base.cmd(TR.test))
    base.log.d('Debug')
    base.log.i('Info')
    test_path = 'smoothtest.tests.example.Example.Example.test_example'
    base.log.i(base.split_test_path(test_path))
    base.log.i(base.split_test_path(test_path, meth=True))
    class PBTest(ParentBase):
        def dummy_cmd(self, *args, **kwargs):
            self.log.d(str(args))
            self.log.d(str(kwargs))
            return 'dummy answer'
    pb = PBTest()
    def build_callback(secs):
        def callback(conn):
            import time
            pb.log('Child callback')
            time.sleep(secs)
            while True:
                pb._dispatch_cmds(conn)
        return callback
    pb.start_subprocess(build_callback(0), pre='Child1')
    args = (1, 'two', set())
    kwargs = dict(example=30)
    pb.send(pb.dummy_cmd, *args, **kwargs)
    ans = pb.recv()[0]
    pb.log.d(ans)
    assert ans.sent_cmd.args == args
    assert ans.sent_cmd.kwargs == kwargs
    pb.kill(block=True, timeout=0.1)
    pb.start_subprocess(build_callback(0.5), pre='Child2')
    pb.kill(block=True, timeout=0.1)

if __name__ == "__main__":
    smoke_test_module()
<|endoftext|>