<commit_before>from django.test import TestCase
from django.core.urlresolvers import reverse
from django.core.validators import ValidationError
from ansible.models import Playbook
import utils.repository as utils
import utils.slugify as slugify

class UtilsRepositoryTest(TestCase):

    def setUp(self):
        self.playbook = Playbook.query_set.get(id=1)

    @classmethod
    def setUpTestData(cls):
        Playbook.query_set.create(username='lozadaomr',repository='ansi-dst',
                inventory='hosts',user='ubuntu')

    # TODO: Find a way to mock this during test
    def test_generate_command_blank_data(self):
        cmd = utils.generate_command('')
        self.assertEqual(cmd, 'ansible-playbook ')

    def test_generate_command_data(self):
        cmd = utils.generate_command('/opt/app/playbooks/ansi-dst/test.yml')
        expected = 'ansible-playbook test.yml'
        self.assertEqual(cmd, 'ansible-playbook test.yml')

    def test_get_dir_name(self):
        repository_path = utils.get_dir_name(self.playbook.repository)
        self.assertEqual(repository_path, '/opt/app/playbooks/ansi-dst')

    def test_get_remote_repo_url(self):
        repo_url = utils.get_remote_repo_url(self.playbook.username,
                self.playbook.repository)
        self.assertEqual(repo_url, 'https://github.com/lozadaomr/ansi-dst.git')

    def test_validate_repository_raise_validation_error(self):
        with self.assertRaises(ValidationError):
            utils.validate_repository(self.playbook.repository)

    def test_validate_inventory_raise_validation_error(self):
        with self.assertRaises(ValidationError):
            utils.validate_inventory(self.playbook.repository,
                    '/opt/app/playbooks/ansi-dst/none.yml')

class UtilsSlugifyTest(TestCase):

    def setUp(self):
        self.data = "Lorem ipsum dolor sit amet"
        self.expected = u'lorem-ipsum-dolor-sit-amet'

    def test_slugify_string_equal(self):
       slug = slugify.to_slug(self.data)
       self.assertEqual(slug, self.expected)
<commit_msg>Start testing clone_repository<commit_after>from django.test import TestCase
from django.core.urlresolvers import reverse
from django.core.validators import ValidationError
from django.conf import settings
from ansible.models import Playbook
import utils.repository as utils
import utils.slugify as slugify
import shutil

class UtilsRepositoryTest(TestCase):

    def setUp(self):
        self.playbook = Playbook.query_set.get(id=1)

    @classmethod
    def setUpTestData(cls):
        Playbook.query_set.create(username='lozadaomr',repository='ansi-dst',
                inventory='hosts',user='ubuntu')

    def test_clone_repository(self):
        utils.clone_repository(self.playbook.username, self.playbook.repository)
        repo_path = os.path.exists(os.path.join(settings.PLAYBOOK_DIR, self.playbook.repository)
        self.assertTrue(repo_path)

    # TODO: Find a way to mock this during test
    def test_generate_command_blank_data(self):
        cmd = utils.generate_command('')
        self.assertEqual(cmd, 'ansible-playbook ')

    def test_generate_command_data(self):
        cmd = utils.generate_command('/opt/app/playbooks/ansi-dst/test.yml')
        expected = 'ansible-playbook test.yml'
        self.assertEqual(cmd, 'ansible-playbook test.yml')

    def test_get_dir_name(self):
        repository_path = utils.get_dir_name(self.playbook.repository)
        self.assertEqual(repository_path, '/opt/app/playbooks/ansi-dst')

    def test_get_remote_repo_url(self):
        repo_url = utils.get_remote_repo_url(self.playbook.username,
                self.playbook.repository)
        self.assertEqual(repo_url, 'https://github.com/lozadaomr/ansi-dst.git')

    def test_validate_repository_raise_validation_error(self):
        with self.assertRaises(ValidationError):
            utils.validate_repository(self.playbook.repository)

    def test_validate_inventory_raise_validation_error(self):
        with self.assertRaises(ValidationError):
            utils.validate_inventory(self.playbook.repository,
                    '/opt/app/playbooks/ansi-dst/none.yml')

class UtilsSlugifyTest(TestCase):

    def setUp(self):
        self.data = "Lorem ipsum dolor sit amet"
        self.expected = u'lorem-ipsum-dolor-sit-amet'

    def test_slugify_string_equal(self):
       slug = slugify.to_slug(self.data)
       self.assertEqual(slug, self.expected)
<|endoftext|>


<commit_before>#!/usr/bin/env python
"""
Loads a json molecule and draws atoms in Blender.

Blender scripts are weird. Either run this inside of Blender or in a shell with:
    blender foo.blend -P molecule_to_blender.py

The script expects an input file named "molecule.json" and should be in the
same directory as "atom_diameters.json" and "atom_colors.json"

Written by Patrick Fuller, patrickfuller@gmail.com, 28 Nov 12
"""

import bpy
from math import acos
from mathutils import Vector
import json

# Atomic radii from wikipedia, scaled to Blender diameters (C = 0.8 units)
# http://en.wikipedia.org/wiki/Atomic_radii_of_the_elements_(data_page)
with open("atom_diameters.json") as atom_diameters:
    diameters = json.load(atom_diameters)

# Atomic colors from cpk
# http://jmol.sourceforge.net/jscolors/
with open("atom_colors.json") as atom_colors:
    colors = json.load(atom_colors)

# Atoms that exist in both dictionaries. Only use these.
available_atoms = set(diameters.keys()) & set(colors.keys())

# Add atom materials to blender
for key in available_atoms:
    bpy.data.materials.new(name=key)
    bpy.data.materials[key].diffuse_color = colors[key]
    bpy.data.materials[key].specular_intensity = 0.2

def draw_molecule(molecule, center=(0,0,0), max_molecule_size=5,
                  show_bonds=True):
    """ Draw a molecule to blender. Uses loaded json molecule data. """

    # Get scale factor - only scales large molecules down
    max_coord = 0
    for atom in molecule["atoms"]:
        max_coord = max(max_coord, *[abs(a) for a in atom["location"]])
    scale = min(max_molecule_size / max_coord, 1)

    # Scale location coordinates and add specified center
    for atom in molecule["atoms"]:
        atom["location"] = [c+x*scale for c,x in zip(center, atom["location"])]

    # Add some mesh primitives
    bpy.ops.object.select_all(action='DESELECT')
    bpy.ops.mesh.primitive_uv_sphere_add()
    sphere = bpy.context.object
    bpy.ops.mesh.primitive_cylinder_add()
    cylinder = bpy.context.object
    cylinder.active_material = bpy.data.materials["bond"]

    # Keep references to all atoms and bonds
    shapes = []

    # If using space_filling model, scale up atom size and remove bonds
    if not show_bonds:
        scale *= 2.5
        molecule["bonds"] = []

    # Draw atoms
    for atom in molecule["atoms"]:

        # If element is not in dictionary, use undefined values
        if atom["element"] not in available_atoms:
            atom["element"] = "undefined"

        # Copy mesh primitive and edit to make atom
        atom_sphere = sphere.copy()
        atom_sphere.data = sphere.data.copy()
        atom_sphere.location = atom["location"]
        atom_sphere.dimensions = [diameters[atom["element"]] * scale]*3
        atom_sphere.active_material = bpy.data.materials[atom["element"]]
        bpy.context.scene.objects.link(atom_sphere)
        shapes.append(atom_sphere)

    # Draw bonds
    for bond in molecule["bonds"]:

        # Extracting locations
        first_loc = molecule["atoms"][bond["source"]]["location"]
        second_loc = molecule["atoms"][bond["target"]]["location"]
        diff = [c2-c1 for c2, c1 in zip(first_loc, second_loc)]
        cent = [(c2+c1)/2 for c2, c1 in zip(first_loc, second_loc)]
        mag = sum([(c2-c1)**2 for c1, c2 in zip(first_loc, second_loc)])**0.5

        # Euler rotation calculation
        v_axis = Vector(diff).normalized()
        v_obj = Vector((0,0,1))
        v_rot = v_obj.cross(v_axis)
        angle = acos(v_obj.dot(v_axis))

        # Check that the number of bonds is logical
        if bond["order"] not in range(1,4):
            print("Improper number of bonds! Defaulting to 1.")
            bond["order"] = 1

        # Specify locations of each bond in every scenario
        if bond["order"] == 1:
            trans = [[0]*3]
        elif bond["order"] == 2:
            trans = [[0.7 * diameters["bond"] * x for x in v_obj],
                    [-0.7 * diameters["bond"] * x for x in v_obj]]
        elif bond["order"] == 3:
            trans = [[0]*3, [1.1*diameters["bond"] * x for x in v_obj],
                    [-1.1*diameters["bond"] * x for x in v_obj]]
        # Draw bonds
        for i in range(bond["order"]):
            bond_cylinder = cylinder.copy()
            bond_cylinder.data = cylinder.data.copy()
            bond_cylinder.dimensions = [diameters["bond"] * scale]*2 + [mag]
            bond_cylinder.location = [c+v for c,v in zip(cent, trans[i])]
            bond_cylinder.rotation_mode = "AXIS_ANGLE"
            bond_cylinder.rotation_axis_angle = [angle] + list(v_rot)
            bpy.context.scene.objects.link(bond_cylinder)
            shapes.append(bond_cylinder)

    # Remove primitive meshes
    bpy.ops.object.select_all(action='DESELECT')
    sphere.select = True
    cylinder.select = True
    # If the starting cube is there, remove it
    if "Cube" in bpy.data.objects.keys():
        bpy.data.objects.get("Cube").select = True
    bpy.ops.object.delete()

    # Smooth and join molecule shapes
    for shape in shapes:
        shape.select = True
    bpy.context.scene.objects.active = shapes[0]
    bpy.ops.object.shade_smooth()
    bpy.ops.object.join()

    # Center object origin to geometry
    bpy.ops.object.origin_set(type="ORIGIN_GEOMETRY", center="MEDIAN")

    # Refresh scene
    bpy.context.scene.update()

# Runs the method
with open("molecule.json") as molecule_file:
    molecule = json.load(molecule_file)
draw_molecule(molecule, show_bonds=True)<commit_msg>if __name__ == __main__<commit_after>#!/usr/bin/env python
"""
Loads a json molecule and draws atoms in Blender.

Blender scripts are weird. Either run this inside of Blender or in a shell with:
    blender foo.blend -P molecule_to_blender.py

The script expects an input file named "molecule.json" and should be in the
same directory as "atom_diameters.json" and "atom_colors.json"

Written by Patrick Fuller, patrickfuller@gmail.com, 28 Nov 12
"""

import bpy
from math import acos
from mathutils import Vector
import json

# Atomic radii from wikipedia, scaled to Blender diameters (C = 0.8 units)
# http://en.wikipedia.org/wiki/Atomic_radii_of_the_elements_(data_page)
with open("atom_diameters.json") as atom_diameters:
    diameters = json.load(atom_diameters)

# Atomic colors from cpk
# http://jmol.sourceforge.net/jscolors/
with open("atom_colors.json") as atom_colors:
    colors = json.load(atom_colors)

# Atoms that exist in both dictionaries. Only use these.
available_atoms = set(diameters.keys()) & set(colors.keys())

# Add atom materials to blender
for key in available_atoms:
    bpy.data.materials.new(name=key)
    bpy.data.materials[key].diffuse_color = colors[key]
    bpy.data.materials[key].specular_intensity = 0.2

def draw_molecule(molecule, center=(0,0,0), max_molecule_size=5,
                  show_bonds=True):
    """ Draw a molecule to blender. Uses loaded json molecule data. """

    # Get scale factor - only scales large molecules down
    max_coord = 0
    for atom in molecule["atoms"]:
        max_coord = max(max_coord, *[abs(a) for a in atom["location"]])
    scale = min(max_molecule_size / max_coord, 1)

    # Scale location coordinates and add specified center
    for atom in molecule["atoms"]:
        atom["location"] = [c+x*scale for c,x in zip(center, atom["location"])]

    # Add some mesh primitives
    bpy.ops.object.select_all(action='DESELECT')
    bpy.ops.mesh.primitive_uv_sphere_add()
    sphere = bpy.context.object
    bpy.ops.mesh.primitive_cylinder_add()
    cylinder = bpy.context.object
    cylinder.active_material = bpy.data.materials["bond"]

    # Keep references to all atoms and bonds
    shapes = []

    # If using space_filling model, scale up atom size and remove bonds
    if not show_bonds:
        scale *= 2.5
        molecule["bonds"] = []

    # Draw atoms
    for atom in molecule["atoms"]:

        # If element is not in dictionary, use undefined values
        if atom["element"] not in available_atoms:
            atom["element"] = "undefined"

        # Copy mesh primitive and edit to make atom
        atom_sphere = sphere.copy()
        atom_sphere.data = sphere.data.copy()
        atom_sphere.location = atom["location"]
        atom_sphere.dimensions = [diameters[atom["element"]] * scale]*3
        atom_sphere.active_material = bpy.data.materials[atom["element"]]
        bpy.context.scene.objects.link(atom_sphere)
        shapes.append(atom_sphere)

    # Draw bonds
    for bond in molecule["bonds"]:

        # Extracting locations
        first_loc = molecule["atoms"][bond["source"]]["location"]
        second_loc = molecule["atoms"][bond["target"]]["location"]
        diff = [c2-c1 for c2, c1 in zip(first_loc, second_loc)]
        cent = [(c2+c1)/2 for c2, c1 in zip(first_loc, second_loc)]
        mag = sum([(c2-c1)**2 for c1, c2 in zip(first_loc, second_loc)])**0.5

        # Euler rotation calculation
        v_axis = Vector(diff).normalized()
        v_obj = Vector((0,0,1))
        v_rot = v_obj.cross(v_axis)
        angle = acos(v_obj.dot(v_axis))

        # Check that the number of bonds is logical
        if bond["order"] not in range(1,4):
            print("Improper number of bonds! Defaulting to 1.")
            bond["order"] = 1

        # Specify locations of each bond in every scenario
        if bond["order"] == 1:
            trans = [[0]*3]
        elif bond["order"] == 2:
            trans = [[0.7 * diameters["bond"] * x for x in v_obj],
                    [-0.7 * diameters["bond"] * x for x in v_obj]]
        elif bond["order"] == 3:
            trans = [[0]*3, [1.1*diameters["bond"] * x for x in v_obj],
                    [-1.1*diameters["bond"] * x for x in v_obj]]
        # Draw bonds
        for i in range(bond["order"]):
            bond_cylinder = cylinder.copy()
            bond_cylinder.data = cylinder.data.copy()
            bond_cylinder.dimensions = [diameters["bond"] * scale]*2 + [mag]
            bond_cylinder.location = [c+v for c,v in zip(cent, trans[i])]
            bond_cylinder.rotation_mode = "AXIS_ANGLE"
            bond_cylinder.rotation_axis_angle = [angle] + list(v_rot)
            bpy.context.scene.objects.link(bond_cylinder)
            shapes.append(bond_cylinder)

    # Remove primitive meshes
    bpy.ops.object.select_all(action='DESELECT')
    sphere.select = True
    cylinder.select = True
    # If the starting cube is there, remove it
    if "Cube" in bpy.data.objects.keys():
        bpy.data.objects.get("Cube").select = True
    bpy.ops.object.delete()

    # Smooth and join molecule shapes
    for shape in shapes:
        shape.select = True
    bpy.context.scene.objects.active = shapes[0]
    bpy.ops.object.shade_smooth()
    bpy.ops.object.join()

    # Center object origin to geometry
    bpy.ops.object.origin_set(type="ORIGIN_GEOMETRY", center="MEDIAN")

    # Refresh scene
    bpy.context.scene.update()

# Runs the method
if __name__ == "__main__":
    with open("molecule.json") as molecule_file:
        molecule = json.load(molecule_file)
    draw_molecule(molecule, show_bonds=True)
<|endoftext|>


<commit_before>"""Discord bot for Discord."""

from collections import OrderedDict
import asyncio
import logging
import random
import json
import sys
import os

from discord.ext import commands
import discord
import creds

# Bot Owner Discord ID
bot_owner = '103714384802480128'

# Discord Client/Bot
bot = commands.Bot(command_prefix='!')
bot.remove_command('help')

app_path = os.path.split(os.path.abspath(sys.argv[0]))[0]
data_path = os.path.join(app_path, 'data')
log_file = os.path.join(app_path, 'bot.log')
stream_file = os.path.join(data_path, 'stream.json')

try:
    with open(stream_file, 'r') as fp:
        streamers = json.load(fp)
except:
    streamers = {}

if not os.path.isdir(data_path):
    os.mkdir(data_path)

emotes = OrderedDict([
    ('disapprove', 'ಠ_ಠ'),
    ('lenny', '( ͡° ͜ʖ ͡°)'),
    ('lennies', '( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°)'),
    ('fight', '(ง ͠° ͟ل͜ ͡°)ง'),
    ('shrug', '¯\_(ツ)_/¯'),
    ('donger', 'ヽ༼ຈل͜ຈ༽ﾉ raise your dongers ヽ༼ຈل͜ຈ༽ﾉ'),
    ('give', '༼ つ ◕_◕ ༽つ'),
    ('zoidberg', '(\/) (°,,,°) (\/)'),
    ('ayy', ':alien: ayy lmao')])

# Logging Setup
log = logging.getLogger('discord')
log.setLevel(logging.INFO)
fhandler = logging.FileHandler(
    filename=log_file,
    encoding='utf-8',
    mode='a')
fhandler.setFormatter(logging.Formatter(
    '%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
log.addHandler(fhandler)

# General helper functions.

def func_desc(func):
    """Get first sentence/description of function from docstring.

    Arguments:
    func -- function to get description from

    Returns:
    str -- "No description." or first sentence of docstring
    """
    doc = func.__doc__
    if doc is None:
        return 'No description.'
    desc = ''
    for c in doc:
        if c == '\n':
            desc += ' '
        desc += c
        if c == '.':
            break
    return desc

def list_align(words):
    """Find word of greatest length and return list of differences in length.

    Arguments:
    words -- list of words

    Returns:
    lens -- list of ints
    """
    longest = 0
    lens = []
    for word in words:
        if len(word) > longest:
            longest = len(word)
    for word in words:
        lens.append(longest - len(word))
    return lens

def stream_name_link(nl):
    """Get stream link from name or vice-versa."""
    if nl.startswith('http://'):
        link = nl
        name = link.split('/')[-1]
    else:
        name = nl
        link = 'http://twitch.tv/{}'.format(name.lower())
    return name, link

def unformat_str(raw):
    """Make a string discord-friendly."""
    new = ''
    rep = ['_', '*', '`', '~']
    for c in raw:
        if c in rep:
            new += '\\'
        new += c
    return new

def stream_message(*args):
    """Get message in stream announcement."""
    message = ''
    if '#' in args:
        for i, a in enumerate(args):
            if a == '#':
                message = '@everyone ' + ' '.join(args[i + 1:])
                break
    elif '$' in args:
        for i, a in enumerate(args):
            if a == '$':
                message = ' '.join(args[i + 1:])
                break
    if message:
        message += '\n'
    return message

@bot.command()
async def info():
    """Print bot information."""
    lib_link = unformat_str('https://github.com/Rapptz/discord.py/tree/async')
    source_link = unformat_str('https://github.com/mikevb1/discordbot')
    message = """This bot is written in Python using discord.py from {}
    The source code can be found at {}""".format(lib_link, source_link)
    await bot.say(message)

@bot.command(name='emotes')
async def emotes_com():
    """Print all emotes available."""
    message = 'Available emotes:\n'
    space = list_align(emotes.keys())
    for i, emote in enumerate(emotes):
        message += '`{}{}:` {}\n'.format(
            emote,
            ' ' * (space[i] + 1),
            unformat_str(repr(emotes[emote]))[1:-1])
    await bot.say(message)

@bot.command(aliases=emotes.keys(), pass_context=True)
async def do_emote(ctx):
    """Send emote, with mentions."""
    emote = emotes[ctx.invoked_with]
    mentions = ' '.join([m.mention for m in ctx.message.mentions])
    await bot.say('{}: {} {}'.format(ctx.message.author.name, emote, mentions))
    try:
        await bot.delete_message(ctx.message)
    except:
        pass

@bot.command()
async def poke():
    """Make sure bot is working."""
    replies = ['Hey!', 'Ow!', 'Stop that!', "I'm here!", 'I need an adult!']
    await bot.say(random.choice(replies))

@bot.group(pass_context=True)
async def stream(ctx, *args):
    """Announce that you or someone else is streaming.

    Usage:
    !stream http://twitch.tv/user  (announce someone not in discord)
    !stream @user                  (announce someone else)
    !stream                        (announce yourself)
    !stream # announcement message (announce with message, mention everyone)
    !stream $ announcement message (announce with message, no mention)
    """
    if ctx.invoked_subcommand is None:
        stream_text = '{} is streaming at {}'
        msg = ctx.message
        message = stream_message(args)
        message += stream_text
        if len(args) == 0 or args[0] in ('#', '$'):
            try:
                author = msg.author
                link = streamers[author.id]
                await bot.say(message.format(author.name, link))
            except KeyError:
                await bot.say('You are not in the list of streamers.')
        elif len(msg.mentions) == 0:
            if args[0].startswith('http:'):
                name, link = stream_name_link(args[0])
                await bot.say(message.format(name, link))
        else:
            for m in msg.mentions:
                try:
                    await bot.say(message.format(m.name, streamers[m.id]))
                except:
                    await bot.say('{} is not in the list of streamers.'.format(
                        m.name))
        try:
            await bot.delete_message(msg)
        except:
            pass

@stream.command(name='add')
async def add_stream(member, link):
    """Add or update a streamer's link.

    Usage:
    !stream add @user http://twitch.tv/user
    """
    global streamers
    try:
        name, link = member.name, link
        sid = member.id
    except:
        return
    streamers[sid] = link
    with open(stream_file, 'w') as s:
        json.dump(streamers, s)
    await bot.say('Added {} ({}) to steamer list.'.format(name, link))

@stream.command(name='remove', aliases=['rem'])
async def remove_stream(member):
    """Remove streamer from list.

    Usage:
    !stream rem @user
    """
    global streamers
    try:
        name, sid = member.name, member.id
    except:
        return
    try:
        del streamers[sid]
    except:
        return
    with open(stream_file, 'w') as s:
        json.dump(streamers, s)
    await bot.say('{} has been removed.'.format(name))

@bot.command()
async def join(channel):
    """Tell bot to join server using ID or discordgg link.

    Usage:
    !join 0h4QlpGEPGkSCO6I                    (invite ID)
    !join https://discord.gg/0h4QlpGEPGkSCO6I (invite link)
    """
    try:
        await bot.accept_invite(channel)
    except:
        pass

@bot.command(pass_context=True)
@commands.has_permissions(kick_members=True)
@commands.bot_has_permissions(kick_members=True)
async def leave(ctx):
    """Tell bot to leave server.

    Usage: !leave
    """
    await bot.leave_server(ctx.message.server)

@bot.command(pass_context=True)
@commands.has_permissions(kick_members=True)
@commands.bot_has_permissions(kick_members=True)
async def kick(ctx):
    """Kick user from server if you have permission.

    Usage:
    !kick @user
    """
    for m in ctx.message.mentions:
        await bot.kick(m)

@bot.command()
@commands.has_permissions(ban_members=True)
@commands.bot_has_permissions(ban_members=True)
async def ban(member, days=1):
    """Ban user from server if you have permission.

    Usage:
    !ban @user
    """
    days = int(days)
    if days > 7:
        days = 7
    elif days < 0:
        days = 0
    await bot.ban(member, days)

@bot.event
async def on_ready():
    """Called when bot is ready."""
    log.info('Bot ready!')
    await bot.change_status(game=discord.Game(name='Destroy All Humans!'))

if __name__ == '__main__':
    bot.run(creds.dis_name, creds.dis_pass)
<commit_msg>fix !stream and subcommands<commit_after>"""Discord bot for Discord."""

from collections import OrderedDict
import asyncio
import logging
import random
import json
import sys
import os

from discord.ext import commands
import discord
import creds

# Bot Owner Discord ID
bot_owner = '103714384802480128'

# Discord Client/Bot
bot = commands.Bot(command_prefix='!')
bot.remove_command('help')

app_path = os.path.split(os.path.abspath(sys.argv[0]))[0]
data_path = os.path.join(app_path, 'data')
log_file = os.path.join(app_path, 'bot.log')
stream_file = os.path.join(data_path, 'stream.json')

try:
    with open(stream_file, 'r') as fp:
        streamers = json.load(fp)
except:
    streamers = {}

if not os.path.isdir(data_path):
    os.mkdir(data_path)

emotes = OrderedDict([
    ('disapprove', 'ಠ_ಠ'),
    ('lenny', '( ͡° ͜ʖ ͡°)'),
    ('lennies', '( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°)'),
    ('fight', '(ง ͠° ͟ل͜ ͡°)ง'),
    ('shrug', '¯\_(ツ)_/¯'),
    ('donger', 'ヽ༼ຈل͜ຈ༽ﾉ raise your dongers ヽ༼ຈل͜ຈ༽ﾉ'),
    ('give', '༼ つ ◕_◕ ༽つ'),
    ('zoidberg', '(\/) (°,,,°) (\/)'),
    ('ayy', ':alien: ayy lmao')])

# Logging Setup
log = logging.getLogger('discord')
log.setLevel(logging.INFO)
fhandler = logging.FileHandler(
    filename=log_file,
    encoding='utf-8',
    mode='a')
fhandler.setFormatter(logging.Formatter(
    '%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
log.addHandler(fhandler)

# General helper functions.

def func_desc(func):
    """Get first sentence/description of function from docstring.

    Arguments:
    func -- function to get description from

    Returns:
    str -- "No description." or first sentence of docstring
    """
    doc = func.__doc__
    if doc is None:
        return 'No description.'
    desc = ''
    for c in doc:
        if c == '\n':
            desc += ' '
        desc += c
        if c == '.':
            break
    return desc

def list_align(words):
    """Find word of greatest length and return list of differences in length.

    Arguments:
    words -- list of words

    Returns:
    lens -- list of ints
    """
    longest = 0
    lens = []
    for word in words:
        if len(word) > longest:
            longest = len(word)
    for word in words:
        lens.append(longest - len(word))
    return lens

def stream_name_link(nl):
    """Get stream link from name or vice-versa."""
    if nl.startswith('http://'):
        link = nl
        name = link.split('/')[-1]
    else:
        name = nl
        link = 'http://twitch.tv/{}'.format(name.lower())
    return name, link

def unformat_str(raw):
    """Make a string discord-friendly."""
    new = ''
    rep = ['_', '*', '`', '~']
    for c in raw:
        if c in rep:
            new += '\\'
        new += c
    return new

def stream_message(*args):
    """Get message in stream announcement."""
    message = ''
    if '#' in args:
        for i, a in enumerate(args):
            if a == '#':
                message = '@everyone ' + ' '.join(args[i + 1:])
                break
    elif '$' in args:
        for i, a in enumerate(args):
            if a == '$':
                message = ' '.join(args[i + 1:])
                break
    if message:
        message += '\n'
    return message

@bot.command()
async def info():
    """Print bot information."""
    lib_link = unformat_str('https://github.com/Rapptz/discord.py/tree/async')
    source_link = unformat_str('https://github.com/mikevb1/discordbot')
    message = """This bot is written in Python using discord.py from {}
    The source code can be found at {}""".format(lib_link, source_link)
    await bot.say(message)

@bot.command(name='emotes')
async def emotes_com():
    """Print all emotes available."""
    message = 'Available emotes:\n'
    space = list_align(emotes.keys())
    for i, emote in enumerate(emotes):
        message += '`{}{}:` {}\n'.format(
            emote,
            ' ' * (space[i] + 1),
            unformat_str(repr(emotes[emote]))[1:-1])
    await bot.say(message)

@bot.command(aliases=emotes.keys(), pass_context=True)
async def do_emote(ctx):
    """Send emote, with mentions."""
    emote = emotes[ctx.invoked_with]
    mentions = ' '.join([m.mention for m in ctx.message.mentions])
    await bot.say('{}: {} {}'.format(ctx.message.author.name, emote, mentions))
    try:
        await bot.delete_message(ctx.message)
    except:
        pass

@bot.command()
async def poke():
    """Make sure bot is working."""
    replies = ['Hey!', 'Ow!', 'Stop that!', "I'm here!", 'I need an adult!']
    await bot.say(random.choice(replies))

@bot.group(pass_context=True, invoke_without_command=True)
async def stream(ctx, *args):
    """Announce that you or someone else is streaming.

    Usage:
    !stream http://twitch.tv/user  (announce someone not in discord)
    !stream @user                  (announce someone else)
    !stream                        (announce yourself)
    !stream # announcement message (announce with message, mention everyone)
    !stream $ announcement message (announce with message, no mention)
    """
    if ctx.invoked_subcommand is None:
        stream_text = '{} is streaming at {}'
        msg = ctx.message
        message = stream_message(args)
        message += stream_text
        if len(args) == 0 or args[0] in ('#', '$'):
            try:
                author = msg.author
                link = streamers[author.id]
                await bot.say(message.format(author.name, link))
            except KeyError:
                await bot.say('You are not in the list of streamers.')
        elif len(msg.mentions) == 0:
            if args[0].startswith('http:'):
                name, link = stream_name_link(args[0])
                await bot.say(message.format(name, link))
        else:
            for m in msg.mentions:
                try:
                    await bot.say(message.format(m.name, streamers[m.id]))
                except:
                    await bot.say('{} is not in the list of streamers.'.format(
                        m.name))
        try:
            await bot.delete_message(msg)
        except:
            pass

@stream.command(name='add', pass_context=True)
async def add_stream(ctx, _, link):
    """Add or update a streamer's link.

    Usage:
    !stream add @user http://twitch.tv/user
    """
    global streamers
    member = ctx.message.mentions[0]
    try:
        name, link = member.name, link
        sid = member.id
    except:
        return
    streamers[sid] = link
    with open(stream_file, 'w') as s:
        json.dump(streamers, s)
    await bot.say('Added {} ({}) to steamer list.'.format(name, link))

@stream.command(name='remove', aliases=['rem'], pass_context=True)
async def remove_stream(ctx, _):
    """Remove streamer from list.

    Usage:
    !stream rem @user
    """
    global streamers
    member = ctx.message.mentions[0]
    try:
        name, sid = member.name, member.id
    except:
        return
    try:
        del streamers[sid]
    except:
        return
    with open(stream_file, 'w') as s:
        json.dump(streamers, s)
    await bot.say('{} has been removed.'.format(name))

@bot.command()
async def join(channel):
    """Tell bot to join server using ID or discordgg link.

    Usage:
    !join 0h4QlpGEPGkSCO6I                    (invite ID)
    !join https://discord.gg/0h4QlpGEPGkSCO6I (invite link)
    """
    try:
        await bot.accept_invite(channel)
    except:
        pass

@bot.command(pass_context=True)
@commands.has_permissions(kick_members=True)
@commands.bot_has_permissions(kick_members=True)
async def leave(ctx):
    """Tell bot to leave server.

    Usage: !leave
    """
    await bot.leave_server(ctx.message.server)

@bot.command(pass_context=True)
@commands.has_permissions(kick_members=True)
@commands.bot_has_permissions(kick_members=True)
async def kick(ctx):
    """Kick user from server if you have permission.

    Usage:
    !kick @user
    """
    for m in ctx.message.mentions:
        await bot.kick(m)

@bot.command()
@commands.has_permissions(ban_members=True)
@commands.bot_has_permissions(ban_members=True)
async def ban(member, days=1):
    """Ban user from server if you have permission.

    Usage:
    !ban @user
    """
    days = int(days)
    if days > 7:
        days = 7
    elif days < 0:
        days = 0
    await bot.ban(member, days)

@bot.event
async def on_ready():
    """Called when bot is ready."""
    log.info('Bot ready!')
    await bot.change_status(game=discord.Game(name='Destroy All Humans!'))

if __name__ == '__main__':
    bot.run(creds.dis_name, creds.dis_pass)
<|endoftext|>


<commit_before>from django.db.models.aggregates import Count, Sum

from .base import BaseGradingPolicy

class PointsEarnedGradingPolicy(BaseGradingPolicy):
    """Grading policy class calculate grade based upon users earned points."""

    public_name = 'Points earned'
    require = {
        'threshold': True
    }

    summary_text = """Overall score is the proportion of points earned out of either the total possible points
    earnable, or the threshold Q, whichever is higher."""

    detail_text = """Let a_i denote the points available for the i'th activity in the sequence. Let e_i denote the
    student's points earned for the i'th activity in the sequence. Let Q, the threshold (a configurable parameter) be a
    positive integer. Then the sequence score is sum(e_i)/(max(Q,sum_i(a_i)).
    The effect of Q, a "minimum available points threshold" is to encourage students to keep doing problems in the
    sequence until the sum of the available points in the sequence is greater than Q, otherwise they will not be able
    to attain full credit.
    """

    def _get_points_earned_trials_count(self):
        """Get points earned and trials count from the sequence.

        :return tuple([trials_count, points_earned])
        """
        items_result = self.sequence.items.exclude(is_problem=False).aggregate(
            points_earned=Sum('score'), trials_count=Count('score')
        )
        return items_result['trials_count'], items_result['points_earned']

    def _calculate(self):
        trials_count, points_earned = self._get_points_earned_trials_count()
        return round(float(points_earned) / max(self.policy.threshold, trials_count), 4)

    @classmethod
    def get_form_class(cls):
        from module.forms import ThresholdGradingPolicyForm
        return ThresholdGradingPolicyForm

    def send_grade(self):
        """Send grade to LMS system.

        :return: nothing.
        """
        self._send_grade(with_request=True)
<commit_msg>Fix points earned policy for the first sequence non-problem item (#156)<commit_after>from django.db.models.aggregates import Count, Sum

from .base import BaseGradingPolicy

class PointsEarnedGradingPolicy(BaseGradingPolicy):
    """Grading policy class calculate grade based upon users earned points."""

    public_name = 'Points earned'
    require = {
        'threshold': True
    }

    summary_text = """Overall score is the proportion of points earned out of either the total possible points
    earnable, or the threshold Q, whichever is higher."""

    detail_text = """Let a_i denote the points available for the i'th activity in the sequence. Let e_i denote the
    student's points earned for the i'th activity in the sequence. Let Q, the threshold (a configurable parameter) be a
    positive integer. Then the sequence score is sum(e_i)/(max(Q,sum_i(a_i)).
    The effect of Q, a "minimum available points threshold" is to encourage students to keep doing problems in the
    sequence until the sum of the available points in the sequence is greater than Q, otherwise they will not be able
    to attain full credit.
    """

    def _get_points_earned_trials_count(self):
        """Get points earned and trials count from the sequence.

        :return tuple([trials_count, points_earned])
        """
        items_result = self.sequence.items.exclude(is_problem=False).aggregate(
            points_earned=Sum('score'), trials_count=Count('score')
        )
        return items_result['trials_count'], items_result['points_earned']

    def _calculate(self):
        trials_count, points_earned = self._get_points_earned_trials_count()
        return round(float(points_earned if points_earned else 0) / max(self.policy.threshold, trials_count), 4)

    @classmethod
    def get_form_class(cls):
        from module.forms import ThresholdGradingPolicyForm
        return ThresholdGradingPolicyForm

    def send_grade(self):
        """Send grade to LMS system.

        :return: nothing.
        """
        self._send_grade(with_request=True)
<|endoftext|>


<commit_before># Copyright (c) 2016-2019 Renata Hodovan, Akos Kiss.
#
# Licensed under the BSD 3-Clause License
# <LICENSE.rst or https://opensource.org/licenses/BSD-3-Clause>.
# This file may not be copied, modified, or distributed except
# according to those terms.

try:
    # FIXME: very nasty, but a recent PyGithub version began to depend on
    # pycrypto transitively, which is a PITA on Windows (can easily fail with an
    # ``ImportError: No module named 'winrandom'``) -- so, we just don't care
    # for now if we cannot load the github module at all. This workaround just
    # postpones the error to the point when ``GithubReport`` is actually used,
    # so be warned, don't do that on Windows!
    from github import Github
except ImportError:
    pass

from .base import BaseTracker

class GithubTracker(BaseTracker):

    def __init__(self, repository, token=None):
        self.repository = repository
        self.ghapi = Github(login_or_token=token)
        self.project = self.ghapi.get_repo(self.repository)

    def find_issue(self, query):
        options = []
        pages = self.project.get_issues(state='open')
        idx = 0
        while True:
            page = pages.get_page(idx)
            idx += 1
            if not page:
                break
            for entry in page:
                if all(word in entry.body for word in query.split()):
                    options.append(entry)
        return options

    def report_issue(self, title, body):
        return self.project.create_issue(title=title, body=body)

    def __call__(self, issue):
        pass

    def issue_url(self, issue):
        return issue.html_url
<commit_msg>Simplify Github issues search by using the search API<commit_after># Copyright (c) 2016-2019 Renata Hodovan, Akos Kiss.
#
# Licensed under the BSD 3-Clause License
# <LICENSE.rst or https://opensource.org/licenses/BSD-3-Clause>.
# This file may not be copied, modified, or distributed except
# according to those terms.

try:
    # FIXME: very nasty, but a recent PyGithub version began to depend on
    # pycrypto transitively, which is a PITA on Windows (can easily fail with an
    # ``ImportError: No module named 'winrandom'``) -- so, we just don't care
    # for now if we cannot load the github module at all. This workaround just
    # postpones the error to the point when ``GithubReport`` is actually used,
    # so be warned, don't do that on Windows!
    from github import Github
except ImportError:
    pass

from .base import BaseTracker

class GithubTracker(BaseTracker):

    def __init__(self, repository, token=None):
        self.org, self.repository = repository.split('/')
        self.ghapi = Github(login_or_token=token)
        self.project = self.ghapi.get_repo(repository)

    def find_issue(self, query):
        return list(self.ghapi.search_issues('+'.join(query.split()), state='open', org=self.org, repo=self.repository))

    def report_issue(self, title, body):
        return self.project.create_issue(title=title, body=body)

    def __call__(self, issue):
        pass

    def issue_url(self, issue):
        return issue.html_url
<|endoftext|>


<commit_before>import xml.etree.cElementTree as ET
from collections import defaultdict

def _parse(file_name):
    lines = tuple(open(file_name, 'r'))
    parsed = defaultdict(list)

    for line in lines:
        splitted = line.split(":")

        # Skip invalid lines
        if len(splitted) == 4:
            error = {
                'file': splitted[0].strip(),
                'line': splitted[1].strip(),
                'col': splitted[2].strip(),
                'detail': splitted[3].strip(),
                'code': splitted[3].strip()[:4]
            }

            parsed[error['file']].append(error)

    return dict(parsed)

def _convert(origin, destination):
    parsed = _parse(origin)

    if len(parsed) < 1:
        return

    testsuite = ET.Element("testsuite")
    testsuite.attrib["errors"] = str(len(parsed))
    testsuite.attrib["failures"] = "0"
    testsuite.attrib["name"] = "flake8 failures"
    testsuite.attrib["tests"] = str(len(parsed))
    testsuite.attrib["time"] = "1"

    for file_name, errors in parsed.items():
        testcase = ET.SubElement(testsuite, "testcase", name=file_name)

        for error in errors:
            ET.SubElement(testcase, "failure", file=error['file'], line=error['line'], col=error['col'],
                          message=error['detail'], type="flake8 %s" % error['code']) \
                          .text = "{}:{} {}".format(error['line'], error['col'], error['detail'])

    tree = ET.ElementTree(testsuite)
    tree.write(destination, encoding='utf-8', xml_declaration=True)
<commit_msg>Py26 compatibility<commit_after>import xml.etree.cElementTree as ET
import sys
from collections import defaultdict

def _parse(file_name):
    lines = tuple(open(file_name, 'r'))
    parsed = defaultdict(list)

    for line in lines:
        splitted = line.split(":")

        # Skip invalid lines
        if len(splitted) == 4:
            error = {
                'file': splitted[0].strip(),
                'line': splitted[1].strip(),
                'col': splitted[2].strip(),
                'detail': splitted[3].strip(),
                'code': splitted[3].strip()[:4]
            }

            parsed[error['file']].append(error)

    return dict(parsed)

def _convert(origin, destination):
    parsed = _parse(origin)

    if len(parsed) < 1:
        return

    testsuite = ET.Element("testsuite")
    testsuite.attrib["errors"] = str(len(parsed))
    testsuite.attrib["failures"] = "0"
    testsuite.attrib["name"] = "flake8 failures"
    testsuite.attrib["tests"] = str(len(parsed))
    testsuite.attrib["time"] = "1"

    for file_name, errors in parsed.items():
        testcase = ET.SubElement(testsuite, "testcase", name=file_name)

        for error in errors:
            ET.SubElement(testcase, "failure", file=error['file'], line=error['line'], col=error['col'],
                          message=error['detail'], type="flake8 %s" % error['code']) \
                          .text = "{0}:{1} {2}".format(error['line'], error['col'], error['detail'])

    tree = ET.ElementTree(testsuite)
    if (2, 6) == sys.version_info[:2]:  # py26
        tree.write(destination, encoding='utf-8')
    else:
        tree.write(destination, encoding='utf-8', xml_declaration=True)

<|endoftext|>


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

"""
PyAero is an airfoil CFD meshing (2D) and contour analysis tool.

The meshing tool provides features to be able to create 2D CFD meshes
for numerical airfoil analysis (virtual wind tunnel).

The purpose of the contour analysis tool is to be able to read airfoil contour
data and analyze them with respect to smoothness and similar properties.
Functions allow splining, refinement, smoothing, etc. in order to provide
accurate input to the subsequent meshing process.
"""

import os
import sys
import platform

path_of_this_file = os.path.dirname(__file__)
sys.path.append(path_of_this_file)

import datetime

from PySide6 import QtGui, QtCore, QtWidgets

import MenusTools
import GraphicsView
import GraphicsScene
import GuiSlots
import ContourAnalysis
import ToolBox
from Settings import ICONS, LOCALE, STYLE, EXITONESCAPE, \
                      OUTPUTDATA, MENUDATA, VIEWSTYLE, LOGDATA
import Logger
import ShortCuts
import BatchMode

__appname__ = 'PyAero'
__author__ = 'Andreas Ennemoser'
__credits__ = 'Internet and open source'
__copyright__ = '2014-' + str(datetime.date.today().strftime("%Y")) + \
                ' ' + __author__
__license__ = 'MIT'
__version__ = '2.1.0'
__email__ = 'andreas.ennemoser@aon.at'
__status__ = 'Release'

class MainWindow(QtWidgets.QMainWindow):
    """PyAero's main QT window"""
    # constructor of MainWindow
    def __init__(self, app, style):
        # constructor of QMainWindow
        super().__init__()

        self.checkEnvironment()

        # set application wide attributes
        # access via "QtCore.QCoreApplication.instance().xxx"
        # helps to overcome nested usage of "parent"
        self.app = app
        self.app.mainwindow = self
        # identify platform (one of Windows, Linux, or Darwin for macOS)
        self.platform = platform.system()

        self.style = style
        # styles do not work anymore; need to come back
        # style_keys = [x.lower() for x in QtWidgets.QStyleFactory.keys()]
        # FIXME
        # FIXME currently leads to segmentation faults
        # FIXME
        # if self.style.lower() in style_keys:
        #     QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create(style))

        # holds active airfoil
        self.airfoil = None
        # container for all loaded airfoils
        self.airfoils = list()

        self.scene = GraphicsScene.GraphicsScene(self)

        self.view = GraphicsView.GraphicsView(self, self.scene)
        self.view.viewstyle = VIEWSTYLE

        # prepare additional views for tabs in right splitter window
        self.contourview = ContourAnalysis.ContourAnalysis(canvas=True)

        # create slots (i.e. handlers or callbacks)
        self.slots = GuiSlots.Slots(self)

        # set central widget for the application
        self.centralwidget = CentralWidget(self)

        self.setCentralWidget(self.centralwidget)

        # add a shortcut for toggling the message window
        sc = ShortCuts.ShortCuts(self)
        sc.addShortcut('ALT+m', 'toggleLogDock', 'shortcut')

        # shortcut for test items
        sc.addShortcut('ALT+t', 'toggleTestObjects')

        # initialize test items (checked in toggleTestObjects)
        self.testitems = False

        # setup user interface and menus
        self.init_GUI()

        # prepare logger
        Logger.log(self)

    def init_GUI(self):

        # window size, position and title
        # self.setGeometry(700, 100, 1200, 900)
        self.showMaximized()
        title = __appname__ + ' - Airfoil Contour Analysis and CFD Meshing'
        self.setWindowTitle = title

        # create menus and tools of main window
        menusTools = MenusTools.MenusTools(self)
        menusTools.createMenus()
        menusTools.createTools()
        menusTools.createDocks()

        # create statusbar in main window
        self.statusbar = self.statusBar()
        self.statusbar.setFixedHeight(22)
        style = (""" QStatusBar {background-color:rgb(232,232,232); \
                border: 1px solid grey;}""")
        self.statusbar.setStyleSheet(style)
        self.statusbar.setSizeGripEnabled(False)
        self.statusbar.showMessage('Ready', 3000)

        # show the GUI
        self.show()

    def checkEnvironment(self):

        # check if path is correct
        if not os.path.exists(MENUDATA):
            print(f'\n PyAero ERROR: Folder {MENUDATA} does not exist.')
            print(' PyAero ERROR: Maybe you are starting '
                  'PyAero from the wrong location.\n')
            sys.exit()

        # check if output folder does exist
        if not os.path.exists(OUTPUTDATA):
            os.mkdir(OUTPUTDATA, mode=0o777)
            print('Folder %s created.' % (OUTPUTDATA))

        # check if logs folder does exist
        if not os.path.exists(LOGDATA):
            os.mkdir(LOGDATA, mode=0o777)
            print('Folder %s created.' % (LOGDATA))

    # ********************************
    # slots which are not in PGuiSlots
    # ********************************

    def keyPressEvent(self, event):
        """Catch keypress events in main window

        Args:
            event (QKeyEvent): key event sent to the widget with
            keyboard input focus
        """
        key = event.key()

        if key == QtCore.Qt.Key_Escape and EXITONESCAPE:
            sys.exit(self.app.exit(retcode=0))
        elif key == QtCore.Qt.Key_Home:
            self.slots.onViewAll()
        else:
            # progress event
            super().keyPressEvent(event)

class CentralWidget(QtWidgets.QWidget):
    # call constructor of CentralWidget
    def __init__(self, parent=None):
        # call constructor of QWidget
        super().__init__(parent)

        self.parent = parent

        # split main window horizontally into two panes
        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)

        # create QToolBox widget
        self.toolbox = ToolBox.Toolbox(self.parent)

        # create box where viewing options are placed
        self.viewingOptions()

        verticalSpacer = QtWidgets.QSpacerItem(50, 15,
                                               QtWidgets.QSizePolicy.Minimum,
                                               QtWidgets.QSizePolicy.Fixed)

        horizontal_line = QtWidgets.QFrame()
        horizontal_line.setFrameShape(QtWidgets.QFrame.HLine)
        horizontal_line.setFrameShadow(QtWidgets.QFrame.Sunken)

        self.left_pane = QtWidgets.QWidget()
        vbox = QtWidgets.QVBoxLayout(self)
        vbox.addWidget(self.toolbox)
        vbox.addItem(verticalSpacer)
        vbox.addWidget(horizontal_line)
        vbox.addItem(verticalSpacer)
        vbox.addWidget(self.viewing_options)
        self.left_pane.setLayout(vbox)

        # create tabbed windows for viewing
        self.tabs = QtWidgets.QTabWidget()
        self.tabs.addTab(self.parent.view, 'Airfoil Viewer')
        self.tabs.addTab(self.parent.contourview, 'Contour Analysis')

        # connect tab changed signal to slot
        self.tabs.currentChanged.connect(self.parent.slots.onTabChanged)

        # add splitter panes
        self.splitter.addWidget(self.left_pane)
        self.splitter.addWidget(self.tabs)

        self.splitter.setSizes([100, 1300])  # initial hint for splitter spacing

        # put splitter in a layout box
        hbox = QtWidgets.QHBoxLayout(self)
        hbox.addWidget(self.splitter)
        self.setLayout(hbox)

    def viewingOptions(self):
        self.viewing_options = QtWidgets.QGroupBox('Viewing Options')
        hbox = QtWidgets.QHBoxLayout()
        vbox1 = QtWidgets.QVBoxLayout()
        vbox2 = QtWidgets.QVBoxLayout()
        self.viewing_options.setLayout(hbox)
        self.cb1 = QtWidgets.QCheckBox('Message Window')
        self.cb1.setChecked(True)
        self.cb2 = QtWidgets.QCheckBox('Airfoil Points')
        self.cb2.setChecked(False)
        self.cb2.setEnabled(False)
        self.cb3 = QtWidgets.QCheckBox('Airfoil Spline Points')
        self.cb3.setChecked(False)
        self.cb3.setEnabled(False)
        self.cb4 = QtWidgets.QCheckBox('Airfoil Spline Contour')
        self.cb4.setChecked(False)
        self.cb4.setEnabled(False)
        self.cb5 = QtWidgets.QCheckBox('Airfoil Chord')
        self.cb5.setChecked(False)
        self.cb5.setEnabled(False)
        self.cb6 = QtWidgets.QCheckBox('Mesh')
        self.cb6.setChecked(False)
        self.cb6.setEnabled(False)
        self.cb7 = QtWidgets.QCheckBox('Leading Edge Circle')
        self.cb7.setChecked(False)
        self.cb7.setEnabled(False)
        self.cb8 = QtWidgets.QCheckBox('Mesh Blocks')
        self.cb8.setChecked(False)
        self.cb8.setEnabled(False)
        self.cb9 = QtWidgets.QCheckBox('Airfoil Camber Line')
        self.cb9.setChecked(False)
        self.cb9.setEnabled(False)
        vbox1.addWidget(self.cb2)
        vbox1.addWidget(self.cb3)
        vbox1.addWidget(self.cb4)
        vbox1.addWidget(self.cb5)
        vbox1.addWidget(self.cb9)
        vbox2.addWidget(self.cb1)
        vbox2.addWidget(self.cb6)
        vbox2.addWidget(self.cb8)
        vbox2.addWidget(self.cb7)
        hbox.addLayout(vbox1)
        hbox.addLayout(vbox2)
        hbox.setAlignment(QtCore.Qt.AlignTop)
        # connect signals to slots
        # lambda allows to send extra parameters
        self.cb1.clicked.connect(
            lambda: self.parent.slots.toggleLogDock('tick'))
        self.cb2.clicked.connect(self.toolbox.toggleRawPoints)
        self.cb3.clicked.connect(self.toolbox.toggleSplinePoints)
        self.cb4.clicked.connect(self.toolbox.toggleSpline)
        self.cb5.clicked.connect(self.toolbox.toggleChord)
        self.cb6.clicked.connect(self.toolbox.toggleMesh)
        self.cb7.clicked.connect(self.toolbox.toggleLeCircle)
        self.cb8.clicked.connect(self.toolbox.toggleMeshBlocks)
        self.cb9.clicked.connect(self.toolbox.toggleCamberLine)

def main():

    # FIXME
    # FIXME this is a preparation for a batch version of PyAero
    # FIXME
    useGUI = '-no-gui' not in sys.argv

    # run PyAero in batch mode
    if not useGUI:
        app = QtCore.QCoreApplication(sys.argv)

        # FIXME
        # FIXME check for proper batch control file
        # FIXME
        if sys.argv[-1] == '-no-gui':
            print('No batch control file specified.')
            sys.exit()

        # prepare logger
        Logger.log('file_only')

        batch_controlfile = sys.argv[-1]
        batchmode = BatchMode.Batch(app, batch_controlfile, __version__)
        batchmode.run_batch()

        return

    # main application (contains the main event loop)
    # run PyAero in GUI mode
    app = QtWidgets.QApplication(sys.argv)

    # set icon for the application ( upper left window icon and taskbar icon)
    # and add specialization icons per size
    # (needed depending on the operating system)
    app_icon = QtGui.QIcon(os.path.join(ICONS, 'app_image.png'))
    app_icon.addFile(os.path.join(ICONS, 'app_image_16x16.png'), QtCore.QSize(16, 16))
    app_icon.addFile(os.path.join(ICONS, 'app_image_24x24.png'), QtCore.QSize(24, 24))
    app_icon.addFile(os.path.join(ICONS, 'app_image_32x32.png'), QtCore.QSize(32, 32))
    app_icon.addFile(os.path.join(ICONS, 'app_image_48x48.png'), QtCore.QSize(48, 48))
    app_icon.addFile(os.path.join(ICONS, 'app_image_256x256.png'), QtCore.QSize(256, 256))

    app.setWindowIcon(app_icon)

    if LOCALE == 'C':
        # set default locale to C, so that decimal separator is a
        # dot in spin boxes, etc.
        QtCore.QLocale.setDefault(QtCore.QLocale.c())

    # window style set in Settings.py
    window = MainWindow(app, STYLE)
    window.show()

    sys.exit(app.exec())

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

"""
PyAero is an airfoil CFD meshing (2D) and contour analysis tool.

The meshing tool provides features to be able to create 2D CFD meshes
for numerical airfoil analysis (virtual wind tunnel).

The purpose of the contour analysis tool is to be able to read airfoil contour
data and analyze them with respect to smoothness and similar properties.
Functions allow splining, refinement, smoothing, etc. in order to provide
accurate input to the subsequent meshing process.
"""

import os
import sys
import platform

path_of_this_file = os.path.dirname(__file__)
sys.path.append(path_of_this_file)

import datetime

from PySide6 import QtGui, QtCore, QtWidgets

import MenusTools
import GraphicsView
import GraphicsScene
import GuiSlots
import ContourAnalysis
import ToolBox
from Settings import ICONS, LOCALE, STYLE, EXITONESCAPE, \
                      OUTPUTDATA, MENUDATA, VIEWSTYLE, LOGDATA
import Logger
import ShortCuts
import BatchMode

__appname__ = 'PyAero'
__author__ = 'Andreas Ennemoser'
__credits__ = 'Internet and open source'
__copyright__ = '2014-' + str(datetime.date.today().strftime("%Y")) + \
                ' ' + __author__
__license__ = 'MIT'
__version__ = '2.1.1'
__email__ = 'andreas.ennemoser@aon.at'
__status__ = 'Release'

class MainWindow(QtWidgets.QMainWindow):
    """PyAero's main QT window"""
    # constructor of MainWindow
    def __init__(self, app, style):
        # constructor of QMainWindow
        super().__init__()

        self.checkEnvironment()

        # set application wide attributes
        # access via "QtCore.QCoreApplication.instance().xxx"
        # helps to overcome nested usage of "parent"
        self.app = app
        self.app.mainwindow = self
        # identify platform (one of Windows, Linux, or Darwin for macOS)
        self.platform = platform.system()

        self.style = style
        # styles do not work anymore; need to come back
        # style_keys = [x.lower() for x in QtWidgets.QStyleFactory.keys()]
        # FIXME
        # FIXME currently leads to segmentation faults
        # FIXME
        # if self.style.lower() in style_keys:
        #     QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create(style))

        # holds active airfoil
        self.airfoil = None
        # container for all loaded airfoils
        self.airfoils = list()

        self.scene = GraphicsScene.GraphicsScene(self)

        self.view = GraphicsView.GraphicsView(self, self.scene)
        self.view.viewstyle = VIEWSTYLE

        # prepare additional views for tabs in right splitter window
        self.contourview = ContourAnalysis.ContourAnalysis(canvas=True)

        # create slots (i.e. handlers or callbacks)
        self.slots = GuiSlots.Slots(self)

        # set central widget for the application
        self.centralwidget = CentralWidget(self)

        self.setCentralWidget(self.centralwidget)

        # add a shortcut for toggling the message window
        sc = ShortCuts.ShortCuts(self)
        sc.addShortcut('ALT+m', 'toggleLogDock', 'shortcut')

        # shortcut for test items
        sc.addShortcut('ALT+t', 'toggleTestObjects')

        # initialize test items (checked in toggleTestObjects)
        self.testitems = False

        # setup user interface and menus
        self.init_GUI()

        # prepare logger
        Logger.log(self)

    def init_GUI(self):

        # window size, position and title
        # self.setGeometry(700, 100, 1200, 900)
        self.showMaximized()
        title = __appname__ + ' - Airfoil Contour Analysis and CFD Meshing'
        self.setWindowTitle = title

        # create menus and tools of main window
        menusTools = MenusTools.MenusTools(self)
        menusTools.createMenus()
        menusTools.createTools()
        menusTools.createDocks()

        # create statusbar in main window
        self.statusbar = self.statusBar()
        self.statusbar.setFixedHeight(22)
        style = (""" QStatusBar {background-color:rgb(232,232,232); \
                border: 1px solid grey;}""")
        self.statusbar.setStyleSheet(style)
        self.statusbar.setSizeGripEnabled(False)
        self.statusbar.showMessage('Ready', 3000)

        # show the GUI
        self.show()

    def checkEnvironment(self):

        # check if path is correct
        if not os.path.exists(MENUDATA):
            print(f'\n PyAero ERROR: Folder {MENUDATA} does not exist.')
            print(' PyAero ERROR: Maybe you are starting '
                  'PyAero from the wrong location.\n')
            sys.exit()

        # check if output folder does exist
        if not os.path.exists(OUTPUTDATA):
            os.mkdir(OUTPUTDATA, mode=0o777)
            print('Folder %s created.' % (OUTPUTDATA))

        # check if logs folder does exist
        if not os.path.exists(LOGDATA):
            os.mkdir(LOGDATA, mode=0o777)
            print('Folder %s created.' % (LOGDATA))

    # ********************************
    # slots which are not in PGuiSlots
    # ********************************

    def keyPressEvent(self, event):
        """Catch keypress events in main window

        Args:
            event (QKeyEvent): key event sent to the widget with
            keyboard input focus
        """
        key = event.key()

        if key == QtCore.Qt.Key_Escape and EXITONESCAPE:
            sys.exit(self.app.exit(retcode=0))
        elif key == QtCore.Qt.Key_Home:
            self.slots.onViewAll()
        else:
            # progress event
            super().keyPressEvent(event)

class CentralWidget(QtWidgets.QWidget):
    # call constructor of CentralWidget
    def __init__(self, parent=None):
        # call constructor of QWidget
        super().__init__(parent)

        self.parent = parent

        # split main window horizontally into two panes
        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)

        # create QToolBox widget
        self.toolbox = ToolBox.Toolbox(self.parent)

        # create box where viewing options are placed
        self.viewingOptions()

        verticalSpacer = QtWidgets.QSpacerItem(50, 15,
                                               QtWidgets.QSizePolicy.Minimum,
                                               QtWidgets.QSizePolicy.Fixed)

        horizontal_line = QtWidgets.QFrame()
        horizontal_line.setFrameShape(QtWidgets.QFrame.HLine)
        horizontal_line.setFrameShadow(QtWidgets.QFrame.Sunken)

        self.left_pane = QtWidgets.QWidget()
        vbox = QtWidgets.QVBoxLayout(self)
        vbox.addWidget(self.toolbox)
        vbox.addItem(verticalSpacer)
        vbox.addWidget(horizontal_line)
        vbox.addItem(verticalSpacer)
        vbox.addWidget(self.viewing_options)
        self.left_pane.setLayout(vbox)

        # create tabbed windows for viewing
        self.tabs = QtWidgets.QTabWidget()
        self.tabs.addTab(self.parent.view, 'Airfoil Viewer')
        self.tabs.addTab(self.parent.contourview, 'Contour Analysis')

        # connect tab changed signal to slot
        self.tabs.currentChanged.connect(self.parent.slots.onTabChanged)

        # add splitter panes
        self.splitter.addWidget(self.left_pane)
        self.splitter.addWidget(self.tabs)

        self.splitter.setSizes([100, 1300])  # initial hint for splitter spacing

        # put splitter in a layout box
        hbox = QtWidgets.QHBoxLayout(self)
        hbox.addWidget(self.splitter)
        self.setLayout(hbox)

    def viewingOptions(self):
        self.viewing_options = QtWidgets.QGroupBox('Viewing Options')
        hbox = QtWidgets.QHBoxLayout()
        vbox1 = QtWidgets.QVBoxLayout()
        vbox2 = QtWidgets.QVBoxLayout()
        self.viewing_options.setLayout(hbox)
        self.cb1 = QtWidgets.QCheckBox('Message Window')
        self.cb1.setChecked(True)
        self.cb2 = QtWidgets.QCheckBox('Airfoil Points')
        self.cb2.setChecked(False)
        self.cb2.setEnabled(False)
        self.cb3 = QtWidgets.QCheckBox('Airfoil Spline Points')
        self.cb3.setChecked(False)
        self.cb3.setEnabled(False)
        self.cb4 = QtWidgets.QCheckBox('Airfoil Spline Contour')
        self.cb4.setChecked(False)
        self.cb4.setEnabled(False)
        self.cb5 = QtWidgets.QCheckBox('Airfoil Chord')
        self.cb5.setChecked(False)
        self.cb5.setEnabled(False)
        self.cb6 = QtWidgets.QCheckBox('Mesh')
        self.cb6.setChecked(False)
        self.cb6.setEnabled(False)
        self.cb7 = QtWidgets.QCheckBox('Leading Edge Circle')
        self.cb7.setChecked(False)
        self.cb7.setEnabled(False)
        self.cb8 = QtWidgets.QCheckBox('Mesh Blocks')
        self.cb8.setChecked(False)
        self.cb8.setEnabled(False)
        self.cb9 = QtWidgets.QCheckBox('Airfoil Camber Line')
        self.cb9.setChecked(False)
        self.cb9.setEnabled(False)
        vbox1.addWidget(self.cb2)
        vbox1.addWidget(self.cb3)
        vbox1.addWidget(self.cb4)
        vbox1.addWidget(self.cb5)
        vbox1.addWidget(self.cb9)
        vbox2.addWidget(self.cb1)
        vbox2.addWidget(self.cb6)
        vbox2.addWidget(self.cb8)
        vbox2.addWidget(self.cb7)
        hbox.addLayout(vbox1)
        hbox.addLayout(vbox2)
        hbox.setAlignment(QtCore.Qt.AlignTop)
        # connect signals to slots
        # lambda allows to send extra parameters
        self.cb1.clicked.connect(
            lambda: self.parent.slots.toggleLogDock('tick'))
        self.cb2.clicked.connect(self.toolbox.toggleRawPoints)
        self.cb3.clicked.connect(self.toolbox.toggleSplinePoints)
        self.cb4.clicked.connect(self.toolbox.toggleSpline)
        self.cb5.clicked.connect(self.toolbox.toggleChord)
        self.cb6.clicked.connect(self.toolbox.toggleMesh)
        self.cb7.clicked.connect(self.toolbox.toggleLeCircle)
        self.cb8.clicked.connect(self.toolbox.toggleMeshBlocks)
        self.cb9.clicked.connect(self.toolbox.toggleCamberLine)

def main():

    # FIXME
    # FIXME this is a preparation for a batch version of PyAero
    # FIXME
    useGUI = '-no-gui' not in sys.argv

    # run PyAero in batch mode
    if not useGUI:
        app = QtCore.QCoreApplication(sys.argv)

        # FIXME
        # FIXME check for proper batch control file
        # FIXME
        if sys.argv[-1] == '-no-gui':
            print('No batch control file specified.')
            sys.exit()

        # prepare logger
        Logger.log('file_only')

        batch_controlfile = sys.argv[-1]
        batchmode = BatchMode.Batch(app, batch_controlfile, __version__)
        batchmode.run_batch()

        return

    # main application (contains the main event loop)
    # run PyAero in GUI mode
    app = QtWidgets.QApplication(sys.argv)

    # set icon for the application ( upper left window icon and taskbar icon)
    # and add specialization icons per size
    # (needed depending on the operating system)
    app_icon = QtGui.QIcon(os.path.join(ICONS, 'app_image.png'))
    app_icon.addFile(os.path.join(ICONS, 'app_image_16x16.png'), QtCore.QSize(16, 16))
    app_icon.addFile(os.path.join(ICONS, 'app_image_24x24.png'), QtCore.QSize(24, 24))
    app_icon.addFile(os.path.join(ICONS, 'app_image_32x32.png'), QtCore.QSize(32, 32))
    app_icon.addFile(os.path.join(ICONS, 'app_image_48x48.png'), QtCore.QSize(48, 48))
    app_icon.addFile(os.path.join(ICONS, 'app_image_256x256.png'), QtCore.QSize(256, 256))

    app.setWindowIcon(app_icon)

    if LOCALE == 'C':
        # set default locale to C, so that decimal separator is a
        # dot in spin boxes, etc.
        QtCore.QLocale.setDefault(QtCore.QLocale.c())

    # window style set in Settings.py
    window = MainWindow(app, STYLE)
    window.show()

    sys.exit(app.exec())

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


<commit_before>import rhinoscriptsyntax as rs
import random

ptArray = list()
nodeList = list()

class node:
	def __init__(self, position, parent = None):
		self.pos = position
		self.child = list()#this is a list of references to the childnodes of this node
		self.parent = None
		self.index = len(ptArray)
		ptArray.append(self.pos)
		nodeList.append(self)

		self.isDone = False
		#this is a oolean which storess whether this has been drawn in the model
		#space as a part of a twig or not

		if not parent is None:
			parent.child.append(self)
			self.parent = parent

	def depth(self):
		#this method returns the depth of this node in the tree
		#root depth is 0 and leaf depth is maximum
		if self.parent is None:
			return 0
		else:
			return 1+self.parent.depth()

	def renderSubTreeWF(self):
		#render the subtree starting at this node
		#but renders just a wireframe
		#WF stands for wireframe
		for ch in self.child:
			rs.AddLine(self.pos, ch.pos)
			ch.renderSubTreeWF()

	def deepestChild(self, depth = 0):
		if len(self.child)  ==  0:
			if self.isDone:
				return [self.parent, 0]
			else:
				return [self,depth]
		else:
			if self.isDone:
				maxDepth = 0
				deepChild = self.parent
			else:
				maxDepth = depth
				deepChild = self

			for ch in self.child:
				childDepth = ch.deepestChild(1+depth)
				if maxDepth < childDepth[1]:
					maxDepth = childDepth[1]
					deepChild = childDepth[0]

			return [deepChild,maxDepth]

	def childDoneStatus(self, ptList = []):
		#this method marks the isDone status of all the nodes of the subtree
		#by marking the done nodes in red and others in blue
		#this method also returns the list of the added point objects
		#so that they can be easily removed
		newPt = rs.AddPoint(self.pos)
		if self.isDone:
			#Add a red Point
			rs.ObjectColor(newPt, (255,0,0))
		else:
			#Add a blue point
			rs.ObjectColor(newPt, (0,0,255))

		ptList.append(newPt)
		for ch in self.child:
			ptList = ch.childDoneStatus(ptList)

		return ptList

def randomPt(x1,x2,y1,y2,z1,z2):
	px = random.uniform(x1,x2)
	py = random.uniform(y1,y2)
	pz = random.uniform(z1,z2)

	return [px,py,pz]

def grow(num):
	if num == 0:
		return 0
	randPt = randomPt(-50,50,-50,50,0,100)

	joinNode = nodeList[rs.PointArrayClosestPoint(ptArray, randPt)]
	joinPt = joinNode.pos
	joinVec = rs.VectorSubtract(randPt, joinPt)

	growthVec = rs.VectorUnitize(joinVec)
	newPt = rs.VectorAdd(joinPt, growthVec)

	newNode = node(newPt, joinNode)
	g = grow(num-1)

rs.EnableRedraw(False)
root = node([0,0,0])

g = grow(20)

root.renderSubTreeWF()
deepCh = root.deepestChild()

rs.EnableRedraw(True)<commit_msg>finished writing the basic render function that renders the tree in the corret way suitable for the final render method which renders the tree not as a wire frame but with athickness<commit_after>import rhinoscriptsyntax as rs
import random

ptArray = list()
nodeList = list()

class node:
	def __init__(self, position, parent = None):
		self.pos = position
		self.child = list()#this is a list of references to the childnodes of this node
		self.parent = None
		self.index = len(ptArray)
		ptArray.append(self.pos)
		nodeList.append(self)

		self.isDone = False
		#this is a oolean which storess whether this has been drawn in the model
		#space as a part of a twig or not

		if not parent is None:
			parent.child.append(self)
			self.parent = parent

	def depth(self):
		#this method returns the depth of this node in the tree
		#root depth is 0 and leaf depth is maximum
		if self.parent is None:
			return 0
		else:
			return 1+self.parent.depth()

	def renderSubTreeWF(self):
		#render the subtree starting at this node
		#but renders just a wireframe
		#WF stands for wireframe
		for ch in self.child:
			rs.AddLine(self.pos, ch.pos)
			ch.renderSubTreeWF()

	def deepestChild(self, depth = 0):
		if len(self.child)  ==  0:
			if self.isDone:
				return [self.parent, 0]
			else:
				return [self,depth]
		else:
			if self.isDone:
				maxDepth = 0
				deepChild = self.parent
			else:
				maxDepth = depth
				deepChild = self

			for ch in self.child:
				childDepth = ch.deepestChild(1+depth)
				if maxDepth < childDepth[1]:
					maxDepth = childDepth[1]
					deepChild = childDepth[0]

			return [deepChild,maxDepth]

	def childDoneStatus(self, ptList = []):
		#this method marks the isDone status of all the nodes of the subtree
		#by marking the done nodes in red and others in blue
		#this method also returns the list of the added point objects
		#so that they can be easily removed
		newPt = rs.AddPoint(self.pos)
		if self.isDone:
			#Add a red Point
			rs.ObjectColor(newPt, (255,0,0))
		else:
			#Add a blue point
			rs.ObjectColor(newPt, (0,0,255))

		ptList.append(newPt)
		for ch in self.child:
			ptList = ch.childDoneStatus(ptList)

		return ptList

	def renderSubTree(self, startRadius, growthFactor, curveDegree):
		while True:
			deepCh = self.deepestChild()
			startNode = deepCh[0]
			if startNode == None:
				#this is the case where the whole tree is rendered
				#later return the group id of the group
				#that contains the whole tree from here
				return True

			curNode = startNode
			nodeList = [startNode]
			while (not curNode.parent is None) and (not curNode.isDone):
				nodeList.append(curNode.parent)
				curNode = curNode.parent

			posList = []
			i = 0
			while i < len(nodeList):
				posList.append(nodeList[i].pos)
				i += 1

			curveId = rs.AddCurve(posList,curveDegree)

			for nd in nodeList:
				nd.isDone = True

def randomPt(x1,x2,y1,y2,z1,z2):
	px = random.uniform(x1,x2)
	py = random.uniform(y1,y2)
	pz = random.uniform(z1,z2)

	return [px,py,pz]

def grow(num):
	#this method grows the global ptArray list
	#this method grows teh pointClooud represented by this list
	if num == 0:
		return 0
	randPt = randomPt(-50,50,-50,50,0,100)

	joinNode = nodeList[rs.PointArrayClosestPoint(ptArray, randPt)]
	joinPt = joinNode.pos
	joinVec = rs.VectorSubtract(randPt, joinPt)

	growthVec = rs.VectorUnitize(joinVec)
	newPt = rs.VectorAdd(joinPt, growthVec)

	newNode = node(newPt, joinNode)
	g = grow(num-1)

rs.EnableRedraw(False)
root = node([0,0,0])

g = grow(20)

root.renderSubTreeWF()
root.renderSubTree(0.1, 1.2, 1)

rs.EnableRedraw(True)<|endoftext|>


<commit_before>import xml.etree.cElementTree as ET
import sys
from collections import defaultdict

def _parse(file_name):
    lines = tuple(open(file_name, 'r'))
    parsed = defaultdict(list)

    for line in lines:
        splitted = line.split(":")

        # Skip invalid lines
        if len(splitted) == 4:
            error = {
                'file': splitted[0].strip(),
                'line': splitted[1].strip(),
                'col': splitted[2].strip(),
                'detail': splitted[3].strip(),
                'code': splitted[3].strip()[:4]
            }

            parsed[error['file']].append(error)

    return dict(parsed)

def _convert(origin, destination):
    parsed = _parse(origin)

    testsuite = ET.Element("testsuite")
    testsuite.attrib["errors"] = str(len(parsed))
    testsuite.attrib["failures"] = "0"
    testsuite.attrib["name"] = "flake8"
    testsuite.attrib["tests"] = str(len(parsed))
    testsuite.attrib["time"] = "1"

    for file_name, errors in parsed.items():
        testcase = ET.SubElement(testsuite, "testcase", name=file_name)

        for error in errors:
            ET.SubElement(testcase, "failure", file=error['file'], line=error['line'], col=error['col'],
                          message=error['detail'], type="flake8 %s" % error['code']) \
                          .text = "{0}:{1} {2}".format(error['line'], error['col'], error['detail'])

    tree = ET.ElementTree(testsuite)
    if (2, 6) == sys.version_info[:2]:  # py26
        tree.write(destination, encoding='utf-8')
    else:
        tree.write(destination, encoding='utf-8', xml_declaration=True)

<commit_msg>always return at least one test<commit_after>import xml.etree.cElementTree as ET
import sys
from collections import defaultdict

def _parse(file_name):
    lines = tuple(open(file_name, 'r'))
    parsed = defaultdict(list)

    for line in lines:
        splitted = line.split(":")

        # Skip invalid lines
        if len(splitted) == 4:
            error = {
                'file': splitted[0].strip(),
                'line': splitted[1].strip(),
                'col': splitted[2].strip(),
                'detail': splitted[3].strip(),
                'code': splitted[3].strip()[:4]
            }

            parsed[error['file']].append(error)

    return dict(parsed)

def _convert(origin, destination):
    parsed = _parse(origin)

    testsuite = ET.Element("testsuite")
    testsuite.attrib["errors"] = str(len(parsed))
    testsuite.attrib["failures"] = "0"
    testsuite.attrib["name"] = "flake8"
    testsuite.attrib["tests"] = str(len(parsed)) or "1"
    testsuite.attrib["time"] = "1"

    if len(parsed) < 1:
        testcase = ET.SubElement(testsuite, "testcase", name="Flake8Tests")
    else:
        for file_name, errors in parsed.items():
            testcase = ET.SubElement(testsuite, "testcase", name=file_name)

            for error in errors:
                ET.SubElement(testcase, "failure", file=error['file'],
                              line=error['line'], col=error['col'],
                              message=error['detail'],
                              type="flake8 %s" % error['code']) \
                    .text = "{0}:{1} {2}".format(error['line'],
                                                 error['col'],
                                                 error['detail'])

    tree = ET.ElementTree(testsuite)
    if (2, 6) == sys.version_info[:2]:  # py26
        tree.write(destination, encoding='utf-8')
    else:
        tree.write(destination, encoding='utf-8', xml_declaration=True)
<|endoftext|>


<commit_before>from candidates.popit import PopItApiMixin, popit_unwrap_pagination
from candidates.static_data import MapItData, PartyData

from django.core.management.base import BaseCommand

from cached_counts.models import CachedCount

class Command(PopItApiMixin, BaseCommand):

    def add_or_update(self, obj):
        CachedCount.objects.update_or_create(
            object_id=obj['object_id'], count_type=obj['count_type'],
            defaults={'count': obj['count'], 'name': obj['name']})

    def handle(self, **options):
        all_constituencies = MapItData.constituencies_2010_name_sorted
        all_parties = PartyData.party_id_to_name
        counts = {
            'candidates_2010': 0,
            'candidates_2015': 0,
            'parties': {party_id: {'count': 0, 'party_name': name}
                        for party_id, name in all_parties.items()},
            'constituencies': {n[1]['name']: {'count': 0, 'con_id':n[1]['id']}
                                for n in all_constituencies},
        }
        standing_again_same_party = 0
        standing_again_different_party = 0
        all_people = 0
        new_candidates = 0
        # Loop over everything, counting things we're interseted in
        for person in popit_unwrap_pagination(
                self.api.persons,
                embed="membership.organization",
                per_page=100
        ):
            all_people += 1
            if not person.get('standing_in'):
                continue
            if person['standing_in'].get('2010'):
                counts['candidates_2010'] += 1
            if person['standing_in'].get('2015'):
                counts['candidates_2015'] += 1
                party_id = person['party_memberships']['2015']['id']
                counts['parties'][party_id]['count'] += 1
                constituency_name = person['standing_in']['2015']['name']
                counts['constituencies'][constituency_name]['count'] += 1
                if person['standing_in'].get('2010'):
                    if party_id == person['party_memberships']['2010']['id']:
                        standing_again_same_party += 1
                    else:
                        standing_again_different_party += 1
                else:
                    new_candidates += 1

        # Add or create objects in the database
        # Parties
        for party_id, data in counts['parties'].items():
            obj = {
                'count_type': 'party',
                'name': data['party_name'],
                'count': data['count'],
                'object_id': party_id

            }

            self.add_or_update(obj)

        # Constituencies
        for constituency_name, data in counts['constituencies'].items():
            obj = {
                'count_type': 'constituency',
                'name': constituency_name,
                'count': data['count'],
                'object_id': data['con_id']

            }

            self.add_or_update(obj)

        for name, count, object_id in (
            ('new_candidates', new_candidates, 'new_candidates'),
            ('total_2010', counts['candidates_2010'], 'candidates_2010'),
            ('total_2015', counts['candidates_2015'], 'candidates_2015'),
            ('standing_again_same_party',
             standing_again_same_party,
             'standing_again_same_party'),
            ('standing_again_different_party',
             standing_again_different_party,
             'standing_again_different_party'),
            ('standing_again',
             standing_again_same_party + standing_again_different_party,
             'standing_again'),
        ):
            obj = {
                'count_type': 'total',
                'name': name,
                'count': count,
                'object_id': object_id,
            }
            self.add_or_update(obj)
<commit_msg>Update constituency counts based on post_id rather than name<commit_after>from candidates.popit import PopItApiMixin, popit_unwrap_pagination
from candidates.static_data import MapItData, PartyData

from django.core.management.base import BaseCommand

from cached_counts.models import CachedCount

class Command(PopItApiMixin, BaseCommand):

    def add_or_update(self, obj):
        CachedCount.objects.update_or_create(
            object_id=obj['object_id'], count_type=obj['count_type'],
            defaults={'count': obj['count'], 'name': obj['name']})

    def handle(self, **options):
        all_constituencies = MapItData.constituencies_2010_name_sorted
        all_parties = PartyData.party_id_to_name
        counts = {
            'candidates_2010': 0,
            'candidates_2015': 0,
            'parties': {party_id: {'count': 0, 'party_name': name}
                        for party_id, name in all_parties.items()},
            'constituencies': {str(n[1]['id']): {'count': 0, 'con_name': n[1]['name']}
                                for n in all_constituencies},
        }
        standing_again_same_party = 0
        standing_again_different_party = 0
        all_people = 0
        new_candidates = 0
        # Loop over everything, counting things we're interseted in
        for person in popit_unwrap_pagination(
                self.api.persons,
                embed="membership.organization",
                per_page=100
        ):
            all_people += 1
            if not person.get('standing_in'):
                continue
            if person['standing_in'].get('2010'):
                counts['candidates_2010'] += 1
            if person['standing_in'].get('2015'):
                counts['candidates_2015'] += 1
                party_id = person['party_memberships']['2015']['id']
                counts['parties'][party_id]['count'] += 1
                constituency_id = person['standing_in']['2015']['post_id']
                counts['constituencies'][constituency_id]['count'] += 1
                if person['standing_in'].get('2010'):
                    if party_id == person['party_memberships']['2010']['id']:
                        standing_again_same_party += 1
                    else:
                        standing_again_different_party += 1
                else:
                    new_candidates += 1

        # Add or create objects in the database
        # Parties
        for party_id, data in counts['parties'].items():
            obj = {
                'count_type': 'party',
                'name': data['party_name'],
                'count': data['count'],
                'object_id': party_id

            }

            self.add_or_update(obj)

        # Constituencies
        for constituency_id, data in counts['constituencies'].items():
            obj = {
                'count_type': 'constituency',
                'name': data['con_name'],
                'count': data['count'],
                'object_id': constituency_id

            }

            self.add_or_update(obj)

        for name, count, object_id in (
            ('new_candidates', new_candidates, 'new_candidates'),
            ('total_2010', counts['candidates_2010'], 'candidates_2010'),
            ('total_2015', counts['candidates_2015'], 'candidates_2015'),
            ('standing_again_same_party',
             standing_again_same_party,
             'standing_again_same_party'),
            ('standing_again_different_party',
             standing_again_different_party,
             'standing_again_different_party'),
            ('standing_again',
             standing_again_same_party + standing_again_different_party,
             'standing_again'),
        ):
            obj = {
                'count_type': 'total',
                'name': name,
                'count': count,
                'object_id': object_id,
            }
            self.add_or_update(obj)
<|endoftext|>


<commit_before>"""Base routing service class"""

import requests
from cachecontrol import CacheControl
from . import __version__
from . import errors

def Session():
    """Returns an HTTP session.
    """
    session = requests.Session()
    session.headers.update({
        'User-Agent': 'rap/{0} {1}'.format(__version__,
                                           requests.utils.default_user_agent())
    })
    return session

class RoutingService(object):
    """Routing service base class.
    """

    def __init__(self, api_key=None, cache=None, daily_quota=-1, rate_limit=-1):
        """Constructs a routing service object.

        :param api_key: API key for a routing service if needed
        :param cache: CacheControl cache instance (Dict or FileCache).
        """
        self.api_key = api_key
        self.session = Session()
        self.daily_quota = daily_quota
        self.rate_limit = rate_limit
        if cache:
            self.session = CacheControl(self.session, cache=cache)

    def handle_http_error(self,
                          response,
                          custom_messages=None,
                          raise_for_status=False):
        """ Error handler
        """
        if not custom_messages:
            custom_messages = {}
        if response.status_code in custom_messages.keys():
            raise errors.HTTPError(custom_messages[response.status_code])
        if raise_for_status:
            response.raise_for_status()
<commit_msg>remove quota as it's difficult to handle for the moment<commit_after>"""Base routing service class"""

import requests
from cachecontrol import CacheControl
from . import __version__
from . import errors

def Session():
    """Returns an HTTP session.
    """
    session = requests.Session()
    session.headers.update({
        'User-Agent': 'rap/{0} {1}'.format(__version__,
                                           requests.utils.default_user_agent())
    })
    return session

class RoutingService(object):
    """Routing service base class.
    """

    def __init__(self, api_key=None, cache=None, rate_limit=-1):
        """Constructs a routing service object.

        :param api_key: API key for a routing service if needed
        :param cache: CacheControl cache instance (Dict or FileCache).
        """
        self.api_key = api_key
        self.session = Session()
        self.rate_limit = rate_limit
        if cache:
            self.session = CacheControl(self.session, cache=cache)

    def handle_http_error(self,
                          response,
                          custom_messages=None,
                          raise_for_status=False):
        """ Error handler
        """
        if not custom_messages:
            custom_messages = {}
        if response.status_code in custom_messages.keys():
            raise errors.HTTPError(custom_messages[response.status_code])
        if raise_for_status:
            response.raise_for_status()
<|endoftext|>


<commit_before>import pytest, shutil, os

import urllib.parse

from tornado.escape import url_escape

from traitlets import Unicode

from jupyterlab import LabApp
from jupyterlab_server import LabConfig
from jupyterlab_server.tests.utils import here
from jupyterlab_server.app import LabServerApp
from jupyter_server.utils import url_path_join

def mkdir(tmp_path, *parts):
    path = tmp_path.joinpath(*parts)
    if not path.exists():
        path.mkdir(parents=True)
    return path

app_settings_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'app_settings'))
user_settings_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'user_settings'))
schemas_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'schemas'))
workspaces_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'workspaces'))

@pytest.fixture
def make_lab_app(root_dir, template_dir, app_settings_dir, user_settings_dir, schemas_dir, workspaces_dir):
    def _make_lab_app(**kwargs):
        class TestLabApp(LabApp):
            base_url = '/lab'
            extension_url = '/lab'
            default_url = Unicode('/',
                                help='The default URL to redirect to from `/`')
            lab_config = LabConfig(
                app_name = 'JupyterLab Test App',
                static_dir = str(root_dir),
                templates_dir = str(template_dir),
                app_url = '/lab',
                app_settings_dir = str(app_settings_dir),
                user_settings_dir = str(user_settings_dir),
                schemas_dir = str(schemas_dir),
                workspaces_dir = str(workspaces_dir),
            )
        app = TestLabApp()
        return app

    # Create the index files.
    index = template_dir.joinpath('index.html')
    index.write_text("""
<!DOCTYPE html>
<html>
<head>
  <title>{{page_config['appName'] | e}}</title>
</head>
<body>
    {# Copy so we do not modify the page_config with updates. #}
    {% set page_config_full = page_config.copy() %}

    {# Set a dummy variable - we just want the side effect of the update. #}
    {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}

      <script id="jupyter-config-data" type="application/json">
        {{ page_config_full | tojson }}
      </script>
  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>

  <script type="text/javascript">
    /* Remove token from URL. */
    (function () {
      var parsedUrl = new URL(window.location.href);
      if (parsedUrl.searchParams.get('token')) {
        parsedUrl.searchParams.delete('token');
        window.history.replaceState({ }, '', parsedUrl.href);
      }
    })();
  </script>
</body>
</html>
""")

    return _make_lab_app

@pytest.fixture
def labapp(serverapp, make_lab_app):
    app = make_lab_app()
    app.initialize(serverapp)
    return app

@pytest.fixture
def fetch_long(http_server_client, auth_header, base_url):
    """fetch fixture that handles auth, base_url, and path"""
    def client_fetch(*parts, headers={}, params={}, **kwargs):
        # Handle URL strings
        path_url = url_escape(url_path_join(base_url, *parts), plus=False)
        params_url = urllib.parse.urlencode(params)
        url = path_url + "?" + params_url
        # Add auth keys to header
        headers.update(auth_header)
        # Make request.
        return http_server_client.fetch(
            url, headers=headers, request_timeout=150, **kwargs
        )
    return client_fetch
<commit_msg>app link to serverapp fixture<commit_after>import pytest, shutil, os

import urllib.parse

from tornado.escape import url_escape

from traitlets import Unicode

from jupyterlab import LabApp
from jupyterlab_server import LabConfig
from jupyterlab_server.tests.utils import here
from jupyterlab_server.app import LabServerApp
from jupyter_server.utils import url_path_join

def mkdir(tmp_path, *parts):
    path = tmp_path.joinpath(*parts)
    if not path.exists():
        path.mkdir(parents=True)
    return path

app_settings_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'app_settings'))
user_settings_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'user_settings'))
schemas_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'schemas'))
workspaces_dir = pytest.fixture(lambda tmp_path: mkdir(tmp_path, 'workspaces'))

@pytest.fixture
def make_lab_app(root_dir, template_dir, app_settings_dir, user_settings_dir, schemas_dir, workspaces_dir):
    def _make_lab_app(**kwargs):
        class TestLabApp(LabApp):
            base_url = '/lab'
            extension_url = '/lab'
            default_url = Unicode('/',
                                help='The default URL to redirect to from `/`')
            lab_config = LabConfig(
                app_name = 'JupyterLab Test App',
                static_dir = str(root_dir),
                templates_dir = str(template_dir),
                app_url = '/lab',
                app_settings_dir = str(app_settings_dir),
                user_settings_dir = str(user_settings_dir),
                schemas_dir = str(schemas_dir),
                workspaces_dir = str(workspaces_dir),
            )
        app = TestLabApp()
        return app

    # Create the index files.
    index = template_dir.joinpath('index.html')
    index.write_text("""
<!DOCTYPE html>
<html>
<head>
  <title>{{page_config['appName'] | e}}</title>
</head>
<body>
    {# Copy so we do not modify the page_config with updates. #}
    {% set page_config_full = page_config.copy() %}

    {# Set a dummy variable - we just want the side effect of the update. #}
    {% set _ = page_config_full.update(baseUrl=base_url, wsUrl=ws_url) %}

      <script id="jupyter-config-data" type="application/json">
        {{ page_config_full | tojson }}
      </script>
  <script src="{{page_config['fullStaticUrl'] | e}}/bundle.js" main="index"></script>

  <script type="text/javascript">
    /* Remove token from URL. */
    (function () {
      var parsedUrl = new URL(window.location.href);
      if (parsedUrl.searchParams.get('token')) {
        parsedUrl.searchParams.delete('token');
        window.history.replaceState({ }, '', parsedUrl.href);
      }
    })();
  </script>
</body>
</html>
""")

    return _make_lab_app

@pytest.fixture
def labapp(serverapp, make_lab_app):
    app = make_lab_app()
    app.link_to_serverapp(serverapp)
    app.initialize()
    return app

@pytest.fixture
def fetch_long(http_server_client, auth_header, base_url):
    """fetch fixture that handles auth, base_url, and path"""
    def client_fetch(*parts, headers={}, params={}, **kwargs):
        # Handle URL strings
        path_url = url_escape(url_path_join(base_url, *parts), plus=False)
        params_url = urllib.parse.urlencode(params)
        url = path_url + "?" + params_url
        # Add auth keys to header
        headers.update(auth_header)
        # Make request.
        return http_server_client.fetch(
            url, headers=headers, request_timeout=150, **kwargs
        )
    return client_fetch
<|endoftext|>