<commit_before>import datetime
from decimal import Decimal

BIRTHDAY = datetime.date(2012, 6, 5)
def age():
    age = datetime.date.today() - BIRTHDAY
    return "%d days" % age.days

db = None # This global is wired in wireup. It's an instance of
          # gittip.postgres.PostgresManager.
AMOUNTS= [Decimal(a) for a in ('0.00', '0.08', '0.16', '0.32', '0.64', '1.28')]

__version__ = "~~VERSION~~"

def get_tip(tipper, tippee):
    """Given two user ids, return a Decimal.
    """
    TIP = """\

        SELECT amount
          FROM tips
         WHERE tipper=%s
           AND tippee=%s
      ORDER BY mtime DESC
         LIMIT 1

    """
    rec = db.fetchone(TIP, (tipper, tippee))
    if rec is None:
        tip = Decimal(0.00)
    else:
        tip = rec['amount']
    return tip

def get_backed_amount(participant_id):
    """Given a unicode, return a Decimal.
    """

    BACKED = """\

        SELECT sum(amount) AS backed
          FROM ( SELECT DISTINCT ON (tipper)
                        amount
                      , tipper
                   FROM tips
                   JOIN participants p ON p.id = tipper
                  WHERE tippee=%s
                    AND last_bill_result = ''
               ORDER BY tipper
                      , mtime DESC
                ) AS foo

    """
    rec = db.fetchone(BACKED, (participant_id,))
    if rec is None:
        amount = None
    else:
        amount = rec['backed']  # might be None

    if amount is None:
        amount = Decimal(0.00)

    return amount

def get_tipjar(participant_id, pronoun="their", claimed=False):
    """Given a participant id, return a unicode.
    """

    amount = get_backed_amount(participant_id)

    # Compute a unicode describing the amount.
    # ========================================
    # This is down here because we use it in multiple places in the app,
    # basically in the claimed participant page and the non-claimed GitHub page
    # (hopefully soon to be Facebook and Twitter as well).

    if pronoun not in ('your', 'their'):
        raise Exception("Unknown, um, pronoun: %s" % pronoun)

    if amount == 0:
        if pronoun == "your":
            tipjar = u"have no backed tips."
        elif pronoun == "their":
            tipjar = u"has no backed tips."
    else:
        if pronoun == "your":
            tipjar = u"have $%s in backed tips."
        elif pronoun == "their":
            tipjar = u"has $%s in backed tips."
        tipjar %= amount

    # We're opt-in.
    # =============
    # If the user hasn't claimed the tipjar then the tips are only pledges,
    # we're not going to actually collect money on their behalf.

    if not claimed:
        tipjar = tipjar.replace("backed", "pledged")

    return tipjar

def get_tips_and_total(tipper, for_payday=False):
    """Given a participant id and a date, return a list and a Decimal.

    This function is used to populate a participant's page for their own
    viewing pleasure, and also by the payday function. If for_payday is not
    False it must be a date object.

    """
    if for_payday:

        # For payday we want the oldest relationship to be paid first.
        order_by = "ctime ASC"

        # This is where it gets crash-proof.
        # ==================================
        # We need to account for the fact that we may have crashed during
        # Payday and we're re-running that function. We only want to select
        # tips that existed before Payday started, but haven't been processed
        # as part of this Payday yet.
        #
        # It's a bug if the paydays subselect returns > 1 rows.
        #
        # XXX If we crash during Payday and we rerun it after a timezone
        # change, will we get burned? How?

        ts_filter = """\

               AND mtime < %s
               AND ( SELECT id
                       FROM transfers
                      WHERE tipper=t.tipper
                        AND tippee=t.tippee
                        AND timestamp >= %s
                    ) IS NULL

        """
        args = (tipper, for_payday, for_payday)
    else:
        order_by = "amount DESC"
        ts_filter = ""
        args = (tipper,)

    TIPS = """\

        SELECT * FROM (
            SELECT DISTINCT ON (tippee)
                   amount
                 , tippee
                 , t.ctime
                 , p.claimed_time
              FROM tips t
              JOIN participants p ON p.id = t.tippee
             WHERE tipper = %%s
               %s
          ORDER BY tippee
                 , t.mtime DESC
        ) AS foo
        ORDER BY %s
               , tippee

    """ % (ts_filter, order_by)  # XXX, No injections here, right?!
    tips = list(db.fetchall(TIPS, args))

    # Compute the total.
    # ==================
    # For payday we only want to process payments to tippees who have
    # themselves opted into Gittip. For the tipper's profile page we want to
    # show the total amount they've pledged (so they're not surprised when
    # someone *does* start accepting tips and all of a sudden they're hit with
    # bigger charges.

    if for_payday:
        to_total = [t for t in tips if t['claimed_time'] is not None]
    else:
        to_total = tips
    total = sum([t['amount'] for t in to_total])

    if not total:  # XXX Why is this necessary?
        total = Decimal('0.00')

    return tips, total

# canonizer
# =========
# This is an Aspen hook to ensure that requests are served on a certain root
# URL, even if multiple domains point to the application.

class X: pass
canonical_scheme = None
canonical_host = None

def canonize(request):
    """Enforce a certain scheme and hostname. Store these on request as well.
    """
    scheme = request.headers.get('X-Forwarded-Proto', 'http') # per Heroku
    host = request.headers['Host']
    bad_scheme = scheme != canonical_scheme
    bad_host = bool(canonical_host) and (host != canonical_host)
                # '' and False => ''
    if bad_scheme or bad_host:
        url = '%s://%s/' % (canonical_scheme, canonical_host)
        request.redirect(url, permanent=True)
<commit_msg>Setting version to 2.1.8 in gittip/__init__.py.<commit_after>import datetime
from decimal import Decimal

BIRTHDAY = datetime.date(2012, 6, 5)
def age():
    age = datetime.date.today() - BIRTHDAY
    return "%d days" % age.days

db = None # This global is wired in wireup. It's an instance of
          # gittip.postgres.PostgresManager.
AMOUNTS= [Decimal(a) for a in ('0.00', '0.08', '0.16', '0.32', '0.64', '1.28')]

__version__ = "2.1.8"

def get_tip(tipper, tippee):
    """Given two user ids, return a Decimal.
    """
    TIP = """\

        SELECT amount
          FROM tips
         WHERE tipper=%s
           AND tippee=%s
      ORDER BY mtime DESC
         LIMIT 1

    """
    rec = db.fetchone(TIP, (tipper, tippee))
    if rec is None:
        tip = Decimal(0.00)
    else:
        tip = rec['amount']
    return tip

def get_backed_amount(participant_id):
    """Given a unicode, return a Decimal.
    """

    BACKED = """\

        SELECT sum(amount) AS backed
          FROM ( SELECT DISTINCT ON (tipper)
                        amount
                      , tipper
                   FROM tips
                   JOIN participants p ON p.id = tipper
                  WHERE tippee=%s
                    AND last_bill_result = ''
               ORDER BY tipper
                      , mtime DESC
                ) AS foo

    """
    rec = db.fetchone(BACKED, (participant_id,))
    if rec is None:
        amount = None
    else:
        amount = rec['backed']  # might be None

    if amount is None:
        amount = Decimal(0.00)

    return amount

def get_tipjar(participant_id, pronoun="their", claimed=False):
    """Given a participant id, return a unicode.
    """

    amount = get_backed_amount(participant_id)

    # Compute a unicode describing the amount.
    # ========================================
    # This is down here because we use it in multiple places in the app,
    # basically in the claimed participant page and the non-claimed GitHub page
    # (hopefully soon to be Facebook and Twitter as well).

    if pronoun not in ('your', 'their'):
        raise Exception("Unknown, um, pronoun: %s" % pronoun)

    if amount == 0:
        if pronoun == "your":
            tipjar = u"have no backed tips."
        elif pronoun == "their":
            tipjar = u"has no backed tips."
    else:
        if pronoun == "your":
            tipjar = u"have $%s in backed tips."
        elif pronoun == "their":
            tipjar = u"has $%s in backed tips."
        tipjar %= amount

    # We're opt-in.
    # =============
    # If the user hasn't claimed the tipjar then the tips are only pledges,
    # we're not going to actually collect money on their behalf.

    if not claimed:
        tipjar = tipjar.replace("backed", "pledged")

    return tipjar

def get_tips_and_total(tipper, for_payday=False):
    """Given a participant id and a date, return a list and a Decimal.

    This function is used to populate a participant's page for their own
    viewing pleasure, and also by the payday function. If for_payday is not
    False it must be a date object.

    """
    if for_payday:

        # For payday we want the oldest relationship to be paid first.
        order_by = "ctime ASC"

        # This is where it gets crash-proof.
        # ==================================
        # We need to account for the fact that we may have crashed during
        # Payday and we're re-running that function. We only want to select
        # tips that existed before Payday started, but haven't been processed
        # as part of this Payday yet.
        #
        # It's a bug if the paydays subselect returns > 1 rows.
        #
        # XXX If we crash during Payday and we rerun it after a timezone
        # change, will we get burned? How?

        ts_filter = """\

               AND mtime < %s
               AND ( SELECT id
                       FROM transfers
                      WHERE tipper=t.tipper
                        AND tippee=t.tippee
                        AND timestamp >= %s
                    ) IS NULL

        """
        args = (tipper, for_payday, for_payday)
    else:
        order_by = "amount DESC"
        ts_filter = ""
        args = (tipper,)

    TIPS = """\

        SELECT * FROM (
            SELECT DISTINCT ON (tippee)
                   amount
                 , tippee
                 , t.ctime
                 , p.claimed_time
              FROM tips t
              JOIN participants p ON p.id = t.tippee
             WHERE tipper = %%s
               %s
          ORDER BY tippee
                 , t.mtime DESC
        ) AS foo
        ORDER BY %s
               , tippee

    """ % (ts_filter, order_by)  # XXX, No injections here, right?!
    tips = list(db.fetchall(TIPS, args))

    # Compute the total.
    # ==================
    # For payday we only want to process payments to tippees who have
    # themselves opted into Gittip. For the tipper's profile page we want to
    # show the total amount they've pledged (so they're not surprised when
    # someone *does* start accepting tips and all of a sudden they're hit with
    # bigger charges.

    if for_payday:
        to_total = [t for t in tips if t['claimed_time'] is not None]
    else:
        to_total = tips
    total = sum([t['amount'] for t in to_total])

    if not total:  # XXX Why is this necessary?
        total = Decimal('0.00')

    return tips, total

# canonizer
# =========
# This is an Aspen hook to ensure that requests are served on a certain root
# URL, even if multiple domains point to the application.

class X: pass
canonical_scheme = None
canonical_host = None

def canonize(request):
    """Enforce a certain scheme and hostname. Store these on request as well.
    """
    scheme = request.headers.get('X-Forwarded-Proto', 'http') # per Heroku
    host = request.headers['Host']
    bad_scheme = scheme != canonical_scheme
    bad_host = bool(canonical_host) and (host != canonical_host)
                # '' and False => ''
    if bad_scheme or bad_host:
        url = '%s://%s/' % (canonical_scheme, canonical_host)
        request.redirect(url, permanent=True)
<|endoftext|>


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

"""
UDPConsole
==========

This is a sample application that is similar to the UDPMultiplexer.  It opens
a socket for unicast messages and (optionally) another for broadcast messages.

Run this application with a BACpypes IP address parameter.

    $ python UDPConsole.py <addr> [ --nobroadcast ]

The address can be one of the following forms:

    192.168.1.10             - unicast socket, no broadcast socket, port 47808
    192.168.1.10/24          - unicast socket, 192.168.1.255 broadcast socket, port 47808
    192.168.1.10:12345       - unicast socket, no broadcast socket, port 12345
    192.168.1.10/24:12345    - unicast socket, 192.168.1.255 broadcast socket, port 12345
    any                      - special tuple ('', 47808)
    any:12345                - special tuple ('', 12345)

Use the --nobroadcast option to prevent the application from opening the
broadcast socket when one would otherwise be opened.

To send a packet, enter in a string in the form <addr> <message> where <addr>
is a BACpyes IP address (which may include the socket) or '*' for a local
broadcast.

Linux/MacOS Test Cases
----------------------

Here are some test cases for Linux and MacOS.

Using Any
~~~~~~~~~

    $ python samples/UDPConsole.py any
    * hi
    received u'hi' from ('10.0.1.5', 47808)

In this case the application received its own broadcast, but did not recognize
it as a broadcast message and did not recognize that it came from itself.
Broadcast messages from other devices sent to 255.255.255.255 or 10.0.1.255
are received, but also not recognized as broadcast messages.

Using the Local Address
~~~~~~~~~~~~~~~~~~~~~~~

    $ python samples/UDPConsole.py 10.0.1.5
    * hi
    received u'hi' from self

In this case it received its own broadcast and it recognized that it came from
itself, but it did not recognize it as a broadcast message.  Broadcast messages
from other devices sent to 255.255.255.255 or 10.0.1.255 are not received.

Using the CIDR Address
~~~~~~~~~~~~~~~~~~~~~~

    $ python samples/UDPConsole.py 10.0.1.5/24
    * hi
    received broadcast u'hi' from self

In this case it received its own broadcast, recognized that it came from itself,
and also recognized it was sent as a broadcast message.  Broadcast messages
from other devices sent to 255.255.255.255 are not received, but those sent to
10.0.1.255 are received and recognized as broadcast messages.
"""

import sys

from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.udp import UDPDirector
from bacpypes.comm import Client, Server, bind
from bacpypes.pdu import Address, PDU
from bacpypes.core import run, stop

from bacpypes.consolelogging import ArgumentParser
from bacpypes.console import ConsoleClient

# some debugging
_debug = 0
_log = ModuleLogger(globals())

# globals
local_unicast_tuple = None
local_broadcast_tuple = None

#
#   MiddleMan
#

@bacpypes_debugging
class MiddleMan(Client, Server):

    def indication(self, pdu):
        if _debug: MiddleMan._debug('indication %r', pdu)

        if not pdu.pduData:
            stop()
            return

        # decode the line and trim off the eol
        line = pdu.pduData.decode('utf_8')[:-1]
        if _debug: MiddleMan._debug('    - line: %r', line)

        line_parts = line.split(' ', 1)
        if _debug: MiddleMan._debug('    - line_parts: %r', line_parts)
        if len(line_parts) != 2:
            sys.stderr.write("err: invalid line: %r\n" % (line,))
            return

        addr, msg = line_parts

        # check the address
        if addr == "*":
            dest = local_broadcast_tuple
        elif ':' in addr:
            addr, port = addr.split(':')
            if addr == "*":
                dest = (local_broadcast_tuple[0], int(port))
            else:
                dest = (addr, int(port))
        else:
            dest = (addr, local_unicast_tuple[1])
        if _debug: MiddleMan._debug('    - dest: %r', dest)

        # send it along
        try:
            self.request(PDU(msg.encode('utf_8'), destination=dest))
        except Exception as err:
            sys.stderr.write("err: %r\n" % (err,))
            return

    def confirmation(self, pdu):
        if _debug: MiddleMan._debug('confirmation %r', pdu)

        # decode the line
        line = pdu.pduData.decode('utf_8')
        if _debug: MiddleMan._debug('    - line: %r', line)

        if pdu.pduSource == local_unicast_tuple:
            sys.stdout.write("received %r from self\n" % (line,))
        else:
            sys.stdout.write("received %r from %s\n" % (
                line, pdu.pduSource,
                ))

#
#   BroadcastReceiver
#

@bacpypes_debugging
class BroadcastReceiver(Client):

    def confirmation(self, pdu):
        if _debug: BroadcastReceiver._debug('confirmation %r', pdu)

        # decode the line
        line = pdu.pduData.decode('utf_8')
        if _debug: MiddleMan._debug('    - line: %r', line)

        if pdu.pduSource == local_unicast_tuple:
            sys.stdout.write("received broadcast %r from self\n" % (line,))
        else:
            sys.stdout.write("received broadcast %r from %s\n" % (
                line, pdu.pduSource,
                ))

#
#   __main__
#

def main():
    # parse the command line arguments
    parser = ArgumentParser(description=__doc__)
    parser.add_argument("address",
        help="address of socket",
        )
    parser.add_argument("--nobroadcast",
        action="store_true",
        dest="noBroadcast",
        default=False,
        help="do not create a broadcast socket",
        )

    args = parser.parse_args()

    if _debug: _log.debug("initialization")
    if _debug: _log.debug("    - args: %r", args)

    if args.address == "any":
        local_unicast_tuple = ('', 47808)
        local_broadcast_tuple = ('255.255.255.255', 47808)

    elif args.address.startswith("any:"):
        port = int(args.address[4:])
        local_unicast_tuple = ('', port)
        local_broadcast_tuple = ('255.255.255.255', port)

    else:
        address = Address(args.address)
        if _debug: _log.debug("    - local_address: %r", address)

        local_unicast_tuple = address.addrTuple
        local_broadcast_tuple = address.addrBroadcastTuple

    if _debug: _log.debug("    - local_unicast_tuple: %r", local_unicast_tuple)
    if _debug: _log.debug("    - local_broadcast_tuple: %r", local_broadcast_tuple)

    console = ConsoleClient()
    middle_man = MiddleMan()
    unicast_director = UDPDirector(local_unicast_tuple)
    bind(console, middle_man, unicast_director)

    if args.noBroadcast:
        _log.debug("    - skipping broadcast")

    elif local_unicast_tuple == local_broadcast_tuple:
        _log.debug("    - identical unicast and broadcast tuples")

    elif local_broadcast_tuple[0] == '255.255.255.255':
        _log.debug("    - special broadcast address only for sending")

    else:
        broadcast_receiver = BroadcastReceiver()
        broadcast_director = UDPDirector(local_broadcast_tuple, reuse=True)
        bind(broadcast_receiver, broadcast_director)

    _log.debug("running")

    run()

    _log.debug("fini")

if __name__ == "__main__":
    main()
<commit_msg>switch from description to usage to prevent formatting, maybe someday use a custom formatter class<commit_after>#!/usr/bin/env python

"""
UDPConsole
==========

This is a sample application that is similar to the UDPMultiplexer.  It opens
a socket for unicast messages and (optionally) another for broadcast messages.

Run this application with a BACpypes IP address parameter.

    $ python UDPConsole.py <addr> [ --nobroadcast ]

The address can be one of the following forms:

    192.168.1.10             - unicast socket, no broadcast socket, port 47808
    192.168.1.10/24          - unicast socket, 192.168.1.255 broadcast socket, port 47808
    192.168.1.10:12345       - unicast socket, no broadcast socket, port 12345
    192.168.1.10/24:12345    - unicast socket, 192.168.1.255 broadcast socket, port 12345
    any                      - special tuple ('', 47808)
    any:12345                - special tuple ('', 12345)

Use the --nobroadcast option to prevent the application from opening the
broadcast socket when one would otherwise be opened.

To send a packet, enter in a string in the form <addr> <message> where <addr>
is a BACpyes IP address (which may include the socket) or '*' for a local
broadcast.

Linux/MacOS Test Cases
----------------------

Here are some test cases for Linux and MacOS.

Using Any
~~~~~~~~~

    $ python samples/UDPConsole.py any
    * hi
    received u'hi' from ('10.0.1.5', 47808)

In this case the application received its own broadcast, but did not recognize
it as a broadcast message and did not recognize that it came from itself.
Broadcast messages from other devices sent to 255.255.255.255 or 10.0.1.255
are received, but also not recognized as broadcast messages.

Using the Local Address
~~~~~~~~~~~~~~~~~~~~~~~

    $ python samples/UDPConsole.py 10.0.1.5
    * hi
    received u'hi' from self

In this case it received its own broadcast and it recognized that it came from
itself, but it did not recognize it as a broadcast message.  Broadcast messages
from other devices sent to 255.255.255.255 or 10.0.1.255 are not received.

Using the CIDR Address
~~~~~~~~~~~~~~~~~~~~~~

    $ python samples/UDPConsole.py 10.0.1.5/24
    * hi
    received broadcast u'hi' from self

In this case it received its own broadcast, recognized that it came from itself,
and also recognized it was sent as a broadcast message.  Broadcast messages
from other devices sent to 255.255.255.255 are not received, but those sent to
10.0.1.255 are received and recognized as broadcast messages.
"""

import sys

from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.udp import UDPDirector
from bacpypes.comm import Client, Server, bind
from bacpypes.pdu import Address, PDU
from bacpypes.core import run, stop

from bacpypes.consolelogging import ArgumentParser
from bacpypes.console import ConsoleClient

# some debugging
_debug = 0
_log = ModuleLogger(globals())

# globals
local_unicast_tuple = None
local_broadcast_tuple = None

#
#   MiddleMan
#

@bacpypes_debugging
class MiddleMan(Client, Server):

    def indication(self, pdu):
        if _debug: MiddleMan._debug('indication %r', pdu)

        if not pdu.pduData:
            stop()
            return

        # decode the line and trim off the eol
        line = pdu.pduData.decode('utf_8')[:-1]
        if _debug: MiddleMan._debug('    - line: %r', line)

        line_parts = line.split(' ', 1)
        if _debug: MiddleMan._debug('    - line_parts: %r', line_parts)
        if len(line_parts) != 2:
            sys.stderr.write("err: invalid line: %r\n" % (line,))
            return

        addr, msg = line_parts

        # check the address
        if addr == "*":
            dest = local_broadcast_tuple
        elif ':' in addr:
            addr, port = addr.split(':')
            if addr == "*":
                dest = (local_broadcast_tuple[0], int(port))
            else:
                dest = (addr, int(port))
        else:
            dest = (addr, local_unicast_tuple[1])
        if _debug: MiddleMan._debug('    - dest: %r', dest)

        # send it along
        try:
            self.request(PDU(msg.encode('utf_8'), destination=dest))
        except Exception as err:
            sys.stderr.write("err: %r\n" % (err,))
            return

    def confirmation(self, pdu):
        if _debug: MiddleMan._debug('confirmation %r', pdu)

        # decode the line
        line = pdu.pduData.decode('utf_8')
        if _debug: MiddleMan._debug('    - line: %r', line)

        if pdu.pduSource == local_unicast_tuple:
            sys.stdout.write("received %r from self\n" % (line,))
        else:
            sys.stdout.write("received %r from %s\n" % (
                line, pdu.pduSource,
                ))

#
#   BroadcastReceiver
#

@bacpypes_debugging
class BroadcastReceiver(Client):

    def confirmation(self, pdu):
        if _debug: BroadcastReceiver._debug('confirmation %r', pdu)

        # decode the line
        line = pdu.pduData.decode('utf_8')
        if _debug: MiddleMan._debug('    - line: %r', line)

        if pdu.pduSource == local_unicast_tuple:
            sys.stdout.write("received broadcast %r from self\n" % (line,))
        else:
            sys.stdout.write("received broadcast %r from %s\n" % (
                line, pdu.pduSource,
                ))

#
#   __main__
#

def main():
    # parse the command line arguments
    parser = ArgumentParser(usage=__doc__)
    parser.add_argument("address",
        help="address of socket",
        )
    parser.add_argument("--nobroadcast",
        action="store_true",
        dest="noBroadcast",
        default=False,
        help="do not create a broadcast socket",
        )

    args = parser.parse_args()

    if _debug: _log.debug("initialization")
    if _debug: _log.debug("    - args: %r", args)

    if args.address == "any":
        local_unicast_tuple = ('', 47808)
        local_broadcast_tuple = ('255.255.255.255', 47808)

    elif args.address.startswith("any:"):
        port = int(args.address[4:])
        local_unicast_tuple = ('', port)
        local_broadcast_tuple = ('255.255.255.255', port)

    else:
        address = Address(args.address)
        if _debug: _log.debug("    - local_address: %r", address)

        local_unicast_tuple = address.addrTuple
        local_broadcast_tuple = address.addrBroadcastTuple

    if _debug: _log.debug("    - local_unicast_tuple: %r", local_unicast_tuple)
    if _debug: _log.debug("    - local_broadcast_tuple: %r", local_broadcast_tuple)

    console = ConsoleClient()
    middle_man = MiddleMan()
    unicast_director = UDPDirector(local_unicast_tuple)
    bind(console, middle_man, unicast_director)

    if args.noBroadcast:
        _log.debug("    - skipping broadcast")

    elif local_unicast_tuple == local_broadcast_tuple:
        _log.debug("    - identical unicast and broadcast tuples")

    elif local_broadcast_tuple[0] == '255.255.255.255':
        _log.debug("    - special broadcast address only for sending")

    else:
        broadcast_receiver = BroadcastReceiver()
        broadcast_director = UDPDirector(local_broadcast_tuple, reuse=True)
        bind(broadcast_receiver, broadcast_director)

    _log.debug("running")

    run()

    _log.debug("fini")

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


<commit_before>import discord
from discord.ext import commands
from .utils import checks
from cogs.utils.dataIO import dataIO, fileIO
from __main__ import send_cmd_help
from selenium import webdriver

import json
import os
import asyncio
import aiohttp
import datetime
import random
import time

try: # check if BeautifulSoup4 is installed
	from bs4 import BeautifulSoup
	soupAvailable = True
except:
	soupAvailable = False

...

class APIError(Exception):
	pass

class ShinyAPIError(Exception):
	pass

class APIKeyError(Exception):
	pass

class Gw2:
	"""This cog finds tp prices"""

	def __init__(self, bot):
		self.bot = bot
		self.session = aiohttp.ClientSession(loop=self.bot.loop)

	@commands.command(pass_context=True)
	async def tpdata(self, ctx, *, tpitemname: str):
		"""This finds the current buy and sell prices of an item
		If multiple matches are found, displays the first"""
		user = ctx.message.author
		tpitemname = tpitemname.replace(" ", "%20")
		color = self.getColor(user)
		try:
			shiniesendpoint = tpitemname
			shiniesresults = await self.call_shiniesapi(shiniesendpoint)
			itemnameresult = shiniesresults[0]["name"]
			tpbuyid = shiniesresults[0]["item_id"]
			commerce = 'commerce/prices/'
			endpoint = commerce + tpbuyid
			results = await self.call_api(endpoint)
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except ShinyAPIError as e:
			await self.bot.say("{0.mention}, API has responded with the following error: "
							   "`{1}`".format(user, e))
			return
		except APIError as e:
			data = discord.Embed(description='I was unable to match that to an item on the TP , listing all - use !tpid (id) to select one', colour=color)
			#For each item returned, add to the data table
			counter = 0
			for name in shiniesresults:
				if counter < 10:
					data.add_field(name=name['name'], value=name['item_id'])
					counter += 1
			try:
				await self.bot.say(embed=data)
				if counter > 9:
					await self.bot.say("More than 10 entries, try to refine your search")
			except discord.HTTPException:
				await self.bot.say("Issue embedding data into discord - EC1")
			return
		buyprice = results["buys"]["unit_price"]
		sellprice = results ["sells"]["unit_price"]
		if buyprice != 0:
			buyprice = self.gold_to_coins(buyprice)
		if sellprice != 0:
			sellprice = self.gold_to_coins(sellprice)
		if buyprice == 0:
			buyprice = 'No buy orders'
		if sellprice == 0:
			sellprice = 'No sell orders'
		data = discord.Embed(title=itemnameresult, description='Not the item you wanted? Try !tplist (name) instead', colour=color)
		data.add_field(name="Buy price", value=buyprice)
		data.add_field(name="Sell price", value=sellprice)

		try:
			await self.bot.say(embed=data)
		except discord.HTTPException:
			await self.bot.say("Issue embedding data into discord - EC2")

	@commands.command(pass_context=True)
	async def tpid(self, ctx, *, tpdataid: str):
		"""This finds the current buy and sell prices of an item
		If multiple matches are found, displays the first"""
		user = ctx.message.author
		color = self.getColor(user)
		try:
			commerce = 'commerce/prices/'
			endpoint = commerce + tpdataid
			results = await self.call_api(endpoint)
			items = 'items/'
			endpoint = items + tpdataid
			itemsresult = await self.call_api(endpoint)
			itemnameresult = itemsresult["name"]
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except APIError as e:
			await self.bot.say("{0.mention}, This item isn't on the TP "
							   "`{1}`".format(user, e))
			return
		buyprice = results["buys"]["unit_price"]
		sellprice = results ["sells"]["unit_price"]
		if buyprice != 0:
			buyprice = self.gold_to_coins(buyprice)
		if sellprice != 0:
			sellprice = self.gold_to_coins(sellprice)
		if buyprice == 0:
			buyprice = 'No buy orders'
		if sellprice == 0:
			sellprice = 'No sell orders'
		data = discord.Embed(title=itemnameresult, colour=color)
		data.add_field(name="Buy price", value=buyprice)
		data.add_field(name="Sell price", value=sellprice)

		try:
			await self.bot.say(embed=data)
		except discord.HTTPException:
			await self.bot.say("Iss")

	@commands.command(pass_context=True)
	async def tplist(self, ctx, *, tpitemname: str):
		"""This lists the ids and names of all matching items to the entered name"""
		user = ctx.message.author
		color = self.getColor(user)
		tpitemname = tpitemname.replace(" ", "%20")
		try:
			shiniesendpoint = tpitemname
			shiniesresults = await self.call_shiniesapi(shiniesendpoint)
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except ShinyAPIError as e:
			await self.bot.say("{0.mention}, API has responded with the following error: "
							   "`{1}`".format(user, e))
			return
		data = discord.Embed(description='Matching IDs, use !tpid (id) to see prices for a specific item', colour=color)
		#For each item returned, add to the data table
		counter = 0
		for name in shiniesresults:
			if counter < 10:
				data.add_field(name=name['name'], value=name['item_id'])
				counter += 1
		try:
			await self.bot.say(embed=data)
			if counter > 9:
				await self.bot.say("More than 10 entries, try to refine your search")
		except discord.HTTPException:
			await self.bot.say("Issue embedding data into discord - EC3")

	@commands.command(pass_context=True)
	async def quaggan(self, ctx, *, quaggan_name : str = 'random'):
		"""This displays a quaggan"""
		user = ctx.message.author
		color = self.getColor(user)
		endpoint = 'quaggans'
		base_quaggan = 'https://static.staticwars.com/quaggans/'
		try:
			l_quaggans = await self.call_api(endpoint)
			if quaggan_name == 'random':
				quaggan_name = random.choice(l_quaggans)
				URL_quaggan = base_quaggan + quaggan_name + '.jpg'
				await self.bot.say(URL_quaggan)
			elif quaggan_name == 'list':
				data = discord.Embed(title='Available quaggans')
				data.add_field(name="List of quaggans", value=', '.join(l_quaggans))
				try:
					await self.bot.say(embed=data)
				except discord.HTTPException:
					await self.bot.say("Issue embedding data into discord - EC4")
			elif quaggan_name in l_quaggans:
				URL_quaggan = base_quaggan + quaggan_name + '.jpg'
				await self.bot.say(URL_quaggan)
			else:
				await self.bot.say("I couldn't find the requested quaggan. List of all available quaggans:")
				data = discord.Embed(title='Available quaggans')
				data.add_field(name="List of quaggans", value=', '.join(l_quaggans))
				try:
					await self.bot.say(embed=data)
				except discord.HTTPException:
					await self.bot.say("Issue embedding data into discord - EC5")
		except APIError as e:
			await self.bot.say("{0.mention}, API returned the following error:  "
							"`{1}`".format(user, e))
			return

	@commands.command(pass_context=True)
	async def baglevel(self, ctx):
		"""this displays the best level to open bags at"""
		user = ctx.message.author
		color = self.getColor(user)
		browser = webdriver.Firefox(executable_path='/home/ubuntu/geckodriver')
		url = "http://silverwastes.loltools.net/" #build the web address
		browser.get(url)
		time.sleep(1)
		html = browser.page_source
		soup = BeautifulSoup(html)
		bagprice = soup.find('div', attrs={'class':'col-md-8 text-center'})
		output = bagprice.text.strip()
		browser.quit()
		await self.bot.say(output)

	@commands.command(pass_context=True)
	async def gemprice(self, ctx, numberOfGems : int = 400):
		"""This lists current gold/gem prices"""
		user = ctx.message.author
		color = self.getColor(user)
		try:
			endpoint = "commerce/exchange/coins?quantity=10000000"
			gemsresult = await self.call_api(endpoint)
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except ShinyAPIError as e:
			await self.bot.say("{0.mention}, API has responded with the following error: "
							   "`{1}`".format(user, e))
			return

		gemCost = gemsresult['coins_per_gem']*numberOfGems

		# Display data
		data = discord.Embed(title="Gem / Gold price", colour=color)
		data.add_field(name=str(numberOfGems) + " Gems",value=self.gold_to_coins(gemCost))

		try:
			await self.bot.say(embed=data)
		except discord.HTTPException:
			await self.bot.say("Issue embedding data into discord - EC3")

	async def call_api(self, endpoint):
		apiserv = 'https://api.guildwars2.com/v2/'
		url = apiserv + endpoint
		async with self.session.get(url) as r:
			results = await r.json()
		if "error" in results:
			raise APIError("The API is dead!")
		if "text" in results:
			raise APIError(results["text"])
		return results
	async def call_shiniesapi(self, shiniesendpoint):
		shinyapiserv = 'https://www.gw2shinies.com/api/json/idbyname/'
		url = shinyapiserv + shiniesendpoint
		async with self.session.get(url) as r:
			shiniesresults = await r.json()
		if shiniesresults is None:
			raise ShinyAPIError("Could not find an item by that name")
		if "error" in shiniesresults:
			raise ShinyAPIError("The API is dead!")
		if "text" in shiniesresults:
			raise ShinyAPIError(shiniesresults["text"])
		return shiniesresults

	def gold_to_coins(self, money):
		gold, remainder = divmod(money, 10000)
		silver, copper = divmod(remainder, 100)
		if gold == 0:
			gold_string = ""
		else:
			gold_string = str(gold) + "g"
		if silver == 0:
			silver_string = ""
		else:
			silver_string = " " + str(silver) + "s"
		if copper == 0:
			copper_string = ""
		else:
			copper_string = " " + str(copper) + "c"
		return gold_string + silver_string + copper_string

	def getColor(self, user):
		try:
			color = user.colour
		except:
			color = discord.Embed.Empty
		return color

def check_folders():
	if not os.path.exists("data/guildwars2"):
		print("Creating data/guildwars2")
		os.makedirs("data/guildwars2")

def check_files():
	files = {
		"gamedata.json": {},
		"settings.json": {"ENABLED": False},
		"language.json": {},
		"keys.json": {},
		"build.json": {"id": None}  # Yay legacy support
	}

	for filename, value in files.items():
		if not os.path.isfile("data/guildwars2/{}".format(filename)):
			print("Creating empty {}".format(filename))
			dataIO.save_json("data/guildwars2/{}".format(filename), value)

def setup(bot):
	if soupAvailable:
		bot.add_cog(Gw2(bot))
	else:
		raise RuntimeError("You need to run `pip3 install beautifulsoup4`")
	check_folders()
	check_files()<commit_msg>readd virtual display<commit_after>import discord
from discord.ext import commands
from .utils import checks
from cogs.utils.dataIO import dataIO, fileIO
from __main__ import send_cmd_help
from pyvirtualdisplay import Display
from selenium import webdriver

import json
import os
import asyncio
import aiohttp
import datetime
import random
import time

try: # check if BeautifulSoup4 is installed
	from bs4 import BeautifulSoup
	soupAvailable = True
except:
	soupAvailable = False

...

class APIError(Exception):
	pass

class ShinyAPIError(Exception):
	pass

class APIKeyError(Exception):
	pass

class Gw2:
	"""This cog finds tp prices"""

	def __init__(self, bot):
		self.bot = bot
		self.session = aiohttp.ClientSession(loop=self.bot.loop)

	@commands.command(pass_context=True)
	async def tpdata(self, ctx, *, tpitemname: str):
		"""This finds the current buy and sell prices of an item
		If multiple matches are found, displays the first"""
		user = ctx.message.author
		tpitemname = tpitemname.replace(" ", "%20")
		color = self.getColor(user)
		try:
			shiniesendpoint = tpitemname
			shiniesresults = await self.call_shiniesapi(shiniesendpoint)
			itemnameresult = shiniesresults[0]["name"]
			tpbuyid = shiniesresults[0]["item_id"]
			commerce = 'commerce/prices/'
			endpoint = commerce + tpbuyid
			results = await self.call_api(endpoint)
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except ShinyAPIError as e:
			await self.bot.say("{0.mention}, API has responded with the following error: "
							   "`{1}`".format(user, e))
			return
		except APIError as e:
			data = discord.Embed(description='I was unable to match that to an item on the TP , listing all - use !tpid (id) to select one', colour=color)
			#For each item returned, add to the data table
			counter = 0
			for name in shiniesresults:
				if counter < 10:
					data.add_field(name=name['name'], value=name['item_id'])
					counter += 1
			try:
				await self.bot.say(embed=data)
				if counter > 9:
					await self.bot.say("More than 10 entries, try to refine your search")
			except discord.HTTPException:
				await self.bot.say("Issue embedding data into discord - EC1")
			return
		buyprice = results["buys"]["unit_price"]
		sellprice = results ["sells"]["unit_price"]
		if buyprice != 0:
			buyprice = self.gold_to_coins(buyprice)
		if sellprice != 0:
			sellprice = self.gold_to_coins(sellprice)
		if buyprice == 0:
			buyprice = 'No buy orders'
		if sellprice == 0:
			sellprice = 'No sell orders'
		data = discord.Embed(title=itemnameresult, description='Not the item you wanted? Try !tplist (name) instead', colour=color)
		data.add_field(name="Buy price", value=buyprice)
		data.add_field(name="Sell price", value=sellprice)

		try:
			await self.bot.say(embed=data)
		except discord.HTTPException:
			await self.bot.say("Issue embedding data into discord - EC2")

	@commands.command(pass_context=True)
	async def tpid(self, ctx, *, tpdataid: str):
		"""This finds the current buy and sell prices of an item
		If multiple matches are found, displays the first"""
		user = ctx.message.author
		color = self.getColor(user)
		try:
			commerce = 'commerce/prices/'
			endpoint = commerce + tpdataid
			results = await self.call_api(endpoint)
			items = 'items/'
			endpoint = items + tpdataid
			itemsresult = await self.call_api(endpoint)
			itemnameresult = itemsresult["name"]
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except APIError as e:
			await self.bot.say("{0.mention}, This item isn't on the TP "
							   "`{1}`".format(user, e))
			return
		buyprice = results["buys"]["unit_price"]
		sellprice = results ["sells"]["unit_price"]
		if buyprice != 0:
			buyprice = self.gold_to_coins(buyprice)
		if sellprice != 0:
			sellprice = self.gold_to_coins(sellprice)
		if buyprice == 0:
			buyprice = 'No buy orders'
		if sellprice == 0:
			sellprice = 'No sell orders'
		data = discord.Embed(title=itemnameresult, colour=color)
		data.add_field(name="Buy price", value=buyprice)
		data.add_field(name="Sell price", value=sellprice)

		try:
			await self.bot.say(embed=data)
		except discord.HTTPException:
			await self.bot.say("Iss")

	@commands.command(pass_context=True)
	async def tplist(self, ctx, *, tpitemname: str):
		"""This lists the ids and names of all matching items to the entered name"""
		user = ctx.message.author
		color = self.getColor(user)
		tpitemname = tpitemname.replace(" ", "%20")
		try:
			shiniesendpoint = tpitemname
			shiniesresults = await self.call_shiniesapi(shiniesendpoint)
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except ShinyAPIError as e:
			await self.bot.say("{0.mention}, API has responded with the following error: "
							   "`{1}`".format(user, e))
			return
		data = discord.Embed(description='Matching IDs, use !tpid (id) to see prices for a specific item', colour=color)
		#For each item returned, add to the data table
		counter = 0
		for name in shiniesresults:
			if counter < 10:
				data.add_field(name=name['name'], value=name['item_id'])
				counter += 1
		try:
			await self.bot.say(embed=data)
			if counter > 9:
				await self.bot.say("More than 10 entries, try to refine your search")
		except discord.HTTPException:
			await self.bot.say("Issue embedding data into discord - EC3")

	@commands.command(pass_context=True)
	async def quaggan(self, ctx, *, quaggan_name : str = 'random'):
		"""This displays a quaggan"""
		user = ctx.message.author
		color = self.getColor(user)
		endpoint = 'quaggans'
		base_quaggan = 'https://static.staticwars.com/quaggans/'
		try:
			l_quaggans = await self.call_api(endpoint)
			if quaggan_name == 'random':
				quaggan_name = random.choice(l_quaggans)
				URL_quaggan = base_quaggan + quaggan_name + '.jpg'
				await self.bot.say(URL_quaggan)
			elif quaggan_name == 'list':
				data = discord.Embed(title='Available quaggans')
				data.add_field(name="List of quaggans", value=', '.join(l_quaggans))
				try:
					await self.bot.say(embed=data)
				except discord.HTTPException:
					await self.bot.say("Issue embedding data into discord - EC4")
			elif quaggan_name in l_quaggans:
				URL_quaggan = base_quaggan + quaggan_name + '.jpg'
				await self.bot.say(URL_quaggan)
			else:
				await self.bot.say("I couldn't find the requested quaggan. List of all available quaggans:")
				data = discord.Embed(title='Available quaggans')
				data.add_field(name="List of quaggans", value=', '.join(l_quaggans))
				try:
					await self.bot.say(embed=data)
				except discord.HTTPException:
					await self.bot.say("Issue embedding data into discord - EC5")
		except APIError as e:
			await self.bot.say("{0.mention}, API returned the following error:  "
							"`{1}`".format(user, e))
			return

	@commands.command(pass_context=True)
	async def baglevel(self, ctx):
		"""this displays the best level to open bags at"""
		try :
			display = Display(visible=0, size=(800, 600))
			display.start()
			user = ctx.message.author
			color = self.getColor(user)
			browser = webdriver.Firefox(executable_path='/home/ubuntu/geckodriver')
			url = "http://silverwastes.loltools.net/" #build the web address
		except discord.HTTPException:
			await self.bot.say("EC7")
		try:
			browser.get(url)
			time.sleep(1)
			html = browser.page_source
			soup = BeautifulSoup(html)
			bagprice = soup.find('div', attrs={'class':'col-md-8 text-center'})
			output = bagprice.text.strip()
		except discord.HTTPException:
			await self.bot.say("EC8")
		browser.quit()
		display.stop()
		await self.bot.say(output)

	@commands.command(pass_context=True)
	async def gemprice(self, ctx, numberOfGems : int = 400):
		"""This lists current gold/gem prices"""
		user = ctx.message.author
		color = self.getColor(user)
		try:
			endpoint = "commerce/exchange/coins?quantity=10000000"
			gemsresult = await self.call_api(endpoint)
		except APIKeyError as e:
			await self.bot.say(e)
			return
		except ShinyAPIError as e:
			await self.bot.say("{0.mention}, API has responded with the following error: "
							   "`{1}`".format(user, e))
			return

		gemCost = gemsresult['coins_per_gem']*numberOfGems

		# Display data
		data = discord.Embed(title="Gem / Gold price", colour=color)
		data.add_field(name=str(numberOfGems) + " Gems",value=self.gold_to_coins(gemCost))

		try:
			await self.bot.say(embed=data)
		except discord.HTTPException:
			await self.bot.say("Issue embedding data into discord - EC3")

	async def call_api(self, endpoint):
		apiserv = 'https://api.guildwars2.com/v2/'
		url = apiserv + endpoint
		async with self.session.get(url) as r:
			results = await r.json()
		if "error" in results:
			raise APIError("The API is dead!")
		if "text" in results:
			raise APIError(results["text"])
		return results
	async def call_shiniesapi(self, shiniesendpoint):
		shinyapiserv = 'https://www.gw2shinies.com/api/json/idbyname/'
		url = shinyapiserv + shiniesendpoint
		async with self.session.get(url) as r:
			shiniesresults = await r.json()
		if shiniesresults is None:
			raise ShinyAPIError("Could not find an item by that name")
		if "error" in shiniesresults:
			raise ShinyAPIError("The API is dead!")
		if "text" in shiniesresults:
			raise ShinyAPIError(shiniesresults["text"])
		return shiniesresults

	def gold_to_coins(self, money):
		gold, remainder = divmod(money, 10000)
		silver, copper = divmod(remainder, 100)
		if gold == 0:
			gold_string = ""
		else:
			gold_string = str(gold) + "g"
		if silver == 0:
			silver_string = ""
		else:
			silver_string = " " + str(silver) + "s"
		if copper == 0:
			copper_string = ""
		else:
			copper_string = " " + str(copper) + "c"
		return gold_string + silver_string + copper_string

	def getColor(self, user):
		try:
			color = user.colour
		except:
			color = discord.Embed.Empty
		return color

def check_folders():
	if not os.path.exists("data/guildwars2"):
		print("Creating data/guildwars2")
		os.makedirs("data/guildwars2")

def check_files():
	files = {
		"gamedata.json": {},
		"settings.json": {"ENABLED": False},
		"language.json": {},
		"keys.json": {},
		"build.json": {"id": None}  # Yay legacy support
	}

	for filename, value in files.items():
		if not os.path.isfile("data/guildwars2/{}".format(filename)):
			print("Creating empty {}".format(filename))
			dataIO.save_json("data/guildwars2/{}".format(filename), value)

def setup(bot):
	if soupAvailable:
		bot.add_cog(Gw2(bot))
	else:
		raise RuntimeError("You need to run `pip3 install beautifulsoup4`")
	check_folders()
	check_files()<|endoftext|>


<commit_before>import sys

from behave import __version__
from behave.configuration import Configuration, ConfigError
from behave.formatter.ansi_escapes import escapes
from behave.i18n import languages
from behave.formatter import formatters
from behave.runner import Runner
from behave.parser import ParserError

TAG_HELP = """
Scenarios inherit tags declared on the Feature level. The simplest
TAG_EXPRESSION is simply a tag::

    --tags @dev

You may even leave off the "@" - behave doesn't mind.

When a tag in a tag expression starts with a ~, this represents boolean NOT::

    --tags ~@dev

A tag expression can have several tags separated by a comma, which represents
logical OR::

    --tags @dev,@wip

The --tags option can be specified several times, and this represents logical
AND, for instance this represents the boolean expression
"(@foo or not @bar) and @zap"::

    --tags @foo,~@bar --tags @zap.

Beware that if you want to use several negative tags to exclude several tags
you have to use logical AND::

    --tags ~@fixme --tags ~@buggy.
""".strip()

# TODO
# Positive tags can be given a threshold to limit the number of occurrences.
# Which can be practical if you are practicing Kanban or CONWIP. This will fail
# if there are more than 3 occurrences of the @qa tag:
#
# --tags @qa:3
# """.strip()

def main():
    config = Configuration()

    if config.version:
        print "behave " + __version__
        sys.exit(0)

    if config.tags_help:
        print TAG_HELP
        sys.exit(0)

    if config.lang_list:
        iso_codes = languages.keys()
        iso_codes.sort()
        print "Languages available:"
        for iso_code in iso_codes:
            native = languages[iso_code]['native'][0]
            name = languages[iso_code]['name'][0]
            print u'%s: %s / %s' % (iso_code, native, name)
        sys.exit(0)

    if config.lang_help:
        if config.lang_help not in languages:
            sys.exit('%s is not a recognised language: try --lang-list' %
                config.lang_help)
        trans = languages[config.lang_help]
        print u"Translations for %s / %s" % (trans['name'][0],
            trans['native'][0])
        for kw in trans:
            if kw in 'name native'.split():
                continue
            print u'%16s: %s' % (kw.title().replace('_', ' '),
                u', '.join(w for w in trans[kw] if w != '*'))
        sys.exit(0)

    if not config.format:
        config.format = ['pretty']
    elif 'help' in config.format:
        print "Available formatters:"
        formatters.list_formatters(sys.stdout)
        sys.exit(0)

    stream = config.output

    runner = Runner(config)
    try:
        failed = runner.run()
    except ParserError, e:
        sys.exit(str(e))
    except ConfigError, e:
        sys.exit(str(e))

    if config.show_snippets and runner.undefined:
        msg = "\nYou can implement step definitions for undefined steps with "
        msg += "these snippets:\n\n"
        printed = set()
        for step in set(runner.undefined):
            if step in printed:
                continue
            printed.add(step)

            msg += "@" + step.step_type + "(u'" + step.name + "')\n"
            msg += "def impl(context):\n"
            msg += "    assert False\n\n"

        sys.stderr.write(escapes['undefined'] + msg + escapes['reset'])
        sys.stderr.flush()

    if failed:
        sys.exit(1)

if __name__ == '__main__':
    main()
<commit_msg>Make all the snippets message bits unicode.<commit_after>import sys

from behave import __version__
from behave.configuration import Configuration, ConfigError
from behave.formatter.ansi_escapes import escapes
from behave.i18n import languages
from behave.formatter import formatters
from behave.runner import Runner
from behave.parser import ParserError

TAG_HELP = """
Scenarios inherit tags declared on the Feature level. The simplest
TAG_EXPRESSION is simply a tag::

    --tags @dev

You may even leave off the "@" - behave doesn't mind.

When a tag in a tag expression starts with a ~, this represents boolean NOT::

    --tags ~@dev

A tag expression can have several tags separated by a comma, which represents
logical OR::

    --tags @dev,@wip

The --tags option can be specified several times, and this represents logical
AND, for instance this represents the boolean expression
"(@foo or not @bar) and @zap"::

    --tags @foo,~@bar --tags @zap.

Beware that if you want to use several negative tags to exclude several tags
you have to use logical AND::

    --tags ~@fixme --tags ~@buggy.
""".strip()

# TODO
# Positive tags can be given a threshold to limit the number of occurrences.
# Which can be practical if you are practicing Kanban or CONWIP. This will fail
# if there are more than 3 occurrences of the @qa tag:
#
# --tags @qa:3
# """.strip()

def main():
    config = Configuration()

    if config.version:
        print "behave " + __version__
        sys.exit(0)

    if config.tags_help:
        print TAG_HELP
        sys.exit(0)

    if config.lang_list:
        iso_codes = languages.keys()
        iso_codes.sort()
        print "Languages available:"
        for iso_code in iso_codes:
            native = languages[iso_code]['native'][0]
            name = languages[iso_code]['name'][0]
            print u'%s: %s / %s' % (iso_code, native, name)
        sys.exit(0)

    if config.lang_help:
        if config.lang_help not in languages:
            sys.exit('%s is not a recognised language: try --lang-list' %
                config.lang_help)
        trans = languages[config.lang_help]
        print u"Translations for %s / %s" % (trans['name'][0],
            trans['native'][0])
        for kw in trans:
            if kw in 'name native'.split():
                continue
            print u'%16s: %s' % (kw.title().replace('_', ' '),
                u', '.join(w for w in trans[kw] if w != '*'))
        sys.exit(0)

    if not config.format:
        config.format = ['pretty']
    elif 'help' in config.format:
        print "Available formatters:"
        formatters.list_formatters(sys.stdout)
        sys.exit(0)

    stream = config.output

    runner = Runner(config)
    try:
        failed = runner.run()
    except ParserError, e:
        sys.exit(str(e))
    except ConfigError, e:
        sys.exit(str(e))

    if config.show_snippets and runner.undefined:
        msg = u"\nYou can implement step definitions for undefined steps with "
        msg += u"these snippets:\n\n"
        printed = set()
        for step in set(runner.undefined):
            if step in printed:
                continue
            printed.add(step)

            msg += u"@" + step.step_type + "(u'" + step.name + u"')\n"
            msg += u"def impl(context):\n"
            msg += u"    assert False\n\n"

        sys.stderr.write(escapes['undefined'] + msg + escapes['reset'])
        sys.stderr.flush()

    if failed:
        sys.exit(1)

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


<commit_before>#!/usr/bin/python

import sys, getopt
import os
import subprocess
import csv
import array
import random
from pyAudioAnalysis import audioSegmentation as aS
from itertools import groupby
from operator import itemgetter
from pydub import AudioSegment
from pydub.utils import get_array_type
from datetime import datetime
from time import gmtime, strftime

#-i --infile
#-o --outfile (csv) (if none, replace file extension with cab)
#-p --plot  / plot and print applause ranges to shell in hh:mm:ss format
#-n --name (default speaker for non-applause segments)

# Takes list of 0.2-second classifications
def class_list_to_time_rows(class_list,buffer_secs):
    try:
        prev_val=-1
        ranges=[]
        for i, x in enumerate(class_list):
            if x!=prev_val:
                ranges.append([i,int(x)])
            prev_val=x
        for i in range(len(ranges)):
            try: ranges[i].append(ranges[i+1][0])
            except: ranges[i].append(len(class_list))
        for triple in ranges:
            triple[0]=(triple[0]/5.0)+buffer_secs
            triple[2]=(triple[2]/5.0)-buffer_secs
        return ranges
    except:
        print "ERROR"

def diarize(inputfile,outputfile,to_csv,plot,numSpeakers,buffer_secs):
    try:
        wav_source=True
        if inputfile.lower()[-4:]!='.wav':     # Creates a temporary WAV
            wav_source=False                         # if input is MP3
            temp_filename=inputfile.split('/')[-1]+str(datetime.now()).replace(' ','__').replace(':','_')+'.wav'
            wav_path='/var/tmp/'+temp_filename   # Pathname for temp WAV
            subprocess.call(['ffmpeg', '-y', '-i', inputfile, wav_path]) # '-y' option overwrites existing file if present
        else:
            wav_path=inputfile
        output=aS.speakerDiarization(wav_path,numOfSpeakers=numSpeakers,PLOT=plot)
        output = list(output)
        class_rows=class_list_to_time_rows(output,buffer_secs)
        if wav_source==False:
            os.remove(wav_path)
        if to_csv==True:
            if outputfile=='':
                outputfile=inputfile[:-4]+'_diarized.csv'
            with open(outputfile, 'w') as csv_fo:
                csv_writer = csv.writer(csv_fo)
                csv_writer.writerows(class_rows)
                if len(class_rows)>0:
                    csv_fo.write('\n\n## Classifier run by '+str(os.getlogin()))
                    csv_fo.write('\n## '+strftime("%Y-%m-%d %H:%M:%S", gmtime())+' GMT')
    except:
        print "ERROR in DIARIZE function"

def main(argv):
    inputfile = ''
    outputfile = ''
    plot=False
    to_csv=False
    buffer_secs=1
    numSpeakers=0
    script_path=os.path.dirname(os.path.realpath(sys.argv[0]))
    try:
        opts, args = getopt.getopt(argv[1:],"hi:o:pn:cb",["ifile=","ofile="])
    except getopt.GetoptError:
        print "FindApplause.py -i <inputfile> -o <outputfile> -p'"
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print "FindApplause.py -i <inputfile> -o <outputfile> -p"
            sys.exit()
        elif opt in ("-i", "--ifile"):
            inputfile = arg.strip('"')
        elif opt in ("-o", "--ofile"):
            outputfile = arg
            to_csv=True
        elif opt in ("-n"):
            numSpeakers=arg
    if ("-p" in sys.argv[1:]):
        plot=True
    if ("-c" in sys.argv[1:])|("--csv" in sys.argv[1:]):
        to_csv=True
    if ("-b" in sys.argv[1:])|("--buffer" in sys.argv[1:]):
        buffer_secs=1
    if ('.mp3' in inputfile.lower())|('.wav' in inputfile.lower())|('.mp4' in inputfile.lower()):
        diarize(inputfile,outputfile,to_csv,plot,numSpeakers,buffer_secs)
    elif os.path.isdir(sys.argv[-1]):
        media_dir=sys.argv[-1]
        media_paths=[os.path.join(media_dir,item) for item in os.listdir(media_dir)]
        for pathname in media_paths:
            if pathname.lower()[-4:] in ('.wav','.mp3','.mp4'):
                diarize(pathname,outputfile,to_csv,plot,numSpeakers,buffer_secs)

if __name__ == "__main__":
   main(sys.argv)
<commit_msg>checkpoint<commit_after>#!/usr/bin/python

import sys, getopt
import os
import subprocess
import csv
import array
import random
from pyAudioAnalysis import audioSegmentation as aS
from itertools import groupby
from operator import itemgetter
from pydub import AudioSegment
from pydub.utils import get_array_type
from datetime import datetime
from time import gmtime, strftime

#-i --infile
#-o --outfile (csv) (if none, replace file extension with cab)
#-p --plot  / plot and print applause ranges to shell in hh:mm:ss format
#-n --name (default speaker for non-applause segments)

# Takes list of 0.2-second classifications
def class_list_to_time_rows(class_list,buffer_secs):
    try:
        prev_val=-1
        ranges=[]
        for i, x in enumerate(class_list):
            if x!=prev_val:
                ranges.append([i,int(x)])
            prev_val=x
        for i in range(len(ranges)):
            try: ranges[i].append(ranges[i+1][0])
            except: ranges[i].append(len(class_list))
        for triple in ranges:
            triple[0]=(triple[0]/5.0)+buffer_secs
            triple[2]=(triple[2]/5.0)-buffer_secs
        return ranges
    except:
        print "ERROR"

def diarize(inputfile,outputfile,to_csv,plot,numSpeakers,buffer_secs):
    try:
        wav_source=True
        if inputfile.lower()[-4:]!='.wav':     # Creates a temporary WAV
            wav_source=False                         # if input is MP3
            temp_filename=inputfile.split('/')[-1]+str(datetime.now()).replace(' ','__').replace(':','_')+'.wav'
            wav_path='/var/tmp/'+temp_filename   # Pathname for temp WAV
            subprocess.call(['ffmpeg', '-y', '-i', inputfile, wav_path]) # '-y' option overwrites existing file if present
        else:
            wav_path=inputfile
        output=aS.speakerDiarization(wav_path,numOfSpeakers=numSpeakers,PLOT=plot)
        output = list(output)
        class_rows=class_list_to_time_rows(output,buffer_secs)
        if wav_source==False:
            os.remove(wav_path)
        if to_csv==True:
            if outputfile=='':
                outputfile=inputfile[:-4]+'_diarized.csv'
            with open(outputfile, 'w') as csv_fo:
                csv_writer = csv.writer(csv_fo)
                csv_writer.writerows(class_rows)
                if len(class_rows)>0:
                    csv_fo.write('\n\n## Classifier run by '+str(os.getlogin()))
                    csv_fo.write('\n## '+strftime("%Y-%m-%d %H:%M:%S", gmtime())+' GMT')
    except:
        print "ERROR in DIARIZE function"

def main(argv):
    inputfile = ''
    outputfile = ''
    plot=False
    to_csv=False
    buffer_secs=1
    numSpeakers=0
    script_path=os.path.dirname(os.path.realpath(sys.argv[0]))
    try:
        opts, args = getopt.getopt(argv[1:],"hi:o:pn:cb",["ifile=","ofile="])
    except getopt.GetoptError:
        print "FindApplause.py -i <inputfile> -o <outputfile> -p'"
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print "FindApplause.py -i <inputfile> -o <outputfile> -p"
            sys.exit()
        elif opt in ("-i", "--ifile"):
            inputfile = arg.strip('"')
        elif opt in ("-o", "--ofile"):
            outputfile = arg
            to_csv=True
        elif opt in ("-n"):
            numSpeakers=arg
    if ("-p" in sys.argv[1:]):
        plot=True
    if ("-c" in sys.argv[1:])|("--csv" in sys.argv[1:]):
        to_csv=True
    if ("-b" in sys.argv[1:])|("--buffer" in sys.argv[1:]):
        buffer_secs=1
    if ('.mp3' in inputfile.lower())|('.wav' in inputfile.lower())|('.mp4' in inputfile.lower()):
        diarize(inputfile,outputfile,to_csv,plot,numSpeakers,buffer_secs)
    elif os.path.isdir(sys.argv[-1]):
        media_dir=sys.argv[-1]
        media_paths=[os.path.join(media_dir,item) for item in os.listdir(media_dir)]
        for pathname in media_paths:
            if pathname.lower()[-4:] in ('.wav','.mp3','.mp4'):
                diarize(pathname,outputfile,to_csv,plot,numSpeakers,buffer_secs)

if __name__ == "__main__":
   main(sys.argv)
<|endoftext|>


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

"""
__init__
---------

Contains testing helpers.
"""

import os
import shutil
import unittest
from cookiecutter import utils

class CookiecutterCleanSystemTestCase(unittest.TestCase):
    """
    Test case that simulates a clean system with no config/cloned cookiecutters.

    During setUp:

    * Back up the `~/.cookiecutterrc` config file to `~/.cookiecutterrc.backup`
    * Back up the `~/.cookiecutters/` dir to `~/.cookiecutters.backup/`
    * Starts off a test case with no pre-existing `~/.cookiecutterrc` or
      `~/.cookiecutters/`

    During tearDown:

    * Delete `~/.cookiecutters/` only if a backup is present at
      `~/.cookiecutters.backup/`
    * Restore the `~/.cookiecutterrc` config file from `~/.cookiecutterrc.backup`
    * Restore the `~/.cookiecutters/` dir from `~/.cookiecutters.backup/`

    """

    def setUp(self):
        # If ~/.cookiecutterrc is pre-existing, move it to a temp location
        self.user_config_path = os.path.expanduser('~/.cookiecutterrc')
        self.user_config_path_backup = os.path.expanduser(
            '~/.cookiecutterrc.backup'
        )
        if os.path.exists(self.user_config_path):
            self.user_config_found = True
            shutil.copy(self.user_config_path, self.user_config_path_backup)
            os.remove(self.user_config_path)
        else:
            self.user_config_found = False

        # If the default cookiecutters_dir is pre-existing, move it to a
        # temp location
        self.cookiecutters_dir = os.path.expanduser('~/.cookiecutters')
        self.cookiecutters_dir_backup = os.path.expanduser('~/.cookiecutters.backup')
        if os.path.isdir(self.cookiecutters_dir):
            self.cookiecutters_dir_found = True

            # Remove existing backups before backing up. If they exist, they're stale.
            if os.path.isdir(self.cookiecutters_dir_backup):
                utils.rmtree(self.cookiecutters_dir_backup)

            shutil.copytree(self.cookiecutters_dir, self.cookiecutters_dir_backup)
        else:
            self.cookiecutters_dir_found = False

    def tearDown(self):
        # If it existed, restore ~/.cookiecutterrc
        # We never write to ~/.cookiecutterrc, so this logic is simpler.
        if self.user_config_found and os.path.exists(self.user_config_path_backup):
            shutil.copy(self.user_config_path_backup, self.user_config_path)
            os.remove(self.user_config_path_backup)

        # Carefully delete the created ~/.cookiecutters dir only in certain
        # conditions.
        if self.cookiecutters_dir_found:
            # Delete the created ~/.cookiecutters dir as long as a backup exists
            if os.path.isdir(self.cookiecutters_dir) and os.path.isdir(self.cookiecutters_dir_backup):
                utils.rmtree(self.cookiecutters_dir)
        else:
            # Delete the created ~/.cookiecutters dir.
            # There's no backup because it never existed
            if os.path.isdir(self.cookiecutters_dir):
                utils.rmtree(self.cookiecutters_dir)

        # Restore the user's default cookiecutters_dir contents
        if os.path.isdir(self.cookiecutters_dir_backup):
            shutil.copytree(self.cookiecutters_dir_backup, self.cookiecutters_dir)
        if os.path.isdir(self.cookiecutters_dir):
            utils.rmtree(self.cookiecutters_dir_backup)
<commit_msg>Remove CookiecutterCleanSystemTestCase in favor of conftest fixture<commit_after><|endoftext|>


<commit_before>from collections import OrderedDict

from pglgen import xml

class Command(xml.BaseParser):
    '''Parse xml registry command tags'''

    def init_data(self):

        self.name = None
        self.rtnType = []
        self.params = []

        self.protoParam = []

        self.parent.commands.append(self)

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()
        if 'command/proto/name' in tagPath:
            self.name = data[0]
        elif 'command/proto' in tagPath:
            for i in data:
                if i not in self.rtnType and i is not '':
                    if '*' in i and len(i) > 1: # split pointer from type
                        info = i.split(' ')
                        self.rtnType.extend(info)
                    else:
                        self.rtnType.append(i)
        elif 'command/param/name' in tagPath:
            self.params.append([data[0].strip(), self.protoParam])
            self.protoParam = []
        elif 'command/param' in tagPath:
            for i in data:
                if i not in self.protoParam and i is not '':
                    if '*' in i and len(i) > 1: # split pointer from type
                        info = i.split(' ')
                        self.protoParam.extend(info)
                    else:
                        self.protoParam.append(i)

class Commands(xml.BaseParser):
    '''Integrate changes from the indivdual Command parsers.'''

    def init_data(self):

        self.commands = []

        self.register_parser('registry/commands/command', Command)

    def integrate(self):
        for cmd in self.commands:
            attr = {
                'parms': cmd.params,
                'return': cmd.rtnType,
            }
            self.root.commands[cmd.name] = attr

class Feature(xml.BaseParser):

    def init_data(self):

        self.name = None
        self.api = None
        self.version = None

        self.default = OrderedDict()
        self.profile_setup(self.default)

        self.profiles = OrderedDict()

        #self.parent.features.append(self)

    @staticmethod
    def profile_setup(profileDict):
        profileDict.update({
            'require': {
                'enum': [],
                'command': [],
            },
            'remove': {
                'enum': [],
                'command': [],
            }
        })

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()

        if ('feature/require/enum' in tagPath or
            'feature/require/command' in tagPath or
            'feature/remove/enum' in tagPath or
            'feature/remove/command' in tagPath):

            # The xml parser calls the parser when the full tag data is read.
            # So in order to get certain information before that happens a stack
            # traversal is needed. This is to set various information from the
            # feature tag that is needed in various tags contained within the tag.
            if self.name is None or self.version is None or self.api is None:
                ptag, pattrs, pdata = self.stack.peek(posRel=2)
                self.name = pattrs['name']
                self.version = pattrs['number']
                self.api = pattrs['api']

            featureStatus, pattrs, pdata = self.stack.peek(posRel=1)
            if 'profile' in pattrs.keys():
                profile = pattrs['profile']
                if profile not in self.profiles.keys():
                    self.profiles[profile] = {}
                    self.profile_setup(self.profiles[profile])

                self.profiles[profile][featureStatus][tag].append(attrs['name'])
            else:
                self.default[featureStatus][tag].append(attrs['name'])

    def integrate(self):

        info = {
            'api': self.api,
            'version': self.version,
            'name': self.name
        }

        features = {
            'info': info,
            'default': self.default,
        }

        # merge any profiles into parent master
        features.update(self.profiles)

        try:
            self.parent.features[self.api]
        except:
            od = OrderedDict()
            od[self.name] =  features
            self.parent.features[self.api] = od
        else:
            self.parent.features[self.api][self.name] = features

class Extensions(xml.BaseParser):

    def init_data(self):

        self.name = None
        self.api = None
        self.version = None

        self.extensions = OrderedDict()

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()

        if ('extension/require/enum' in tagPath or
            'extension/require/command' in tagPath):

            ptag, pattrs, pdata = self.stack.peek(posRel=2)
            self.name = pattrs['name']
            self.supported = pattrs['supported']
            try:
                self.extensions[self.name][tag].append(attrs['name'])
            except:
                self.extensions[self.name] = {'enum': [], 'command': []}
                self.extensions[self.name][tag].append(attrs['name'])

    def integrate(self):

        self.parent.extensions.update(self.extensions)

class Registry(xml.BaseParser):

    def init_data(self):

        self.enums = OrderedDict()
        self.commands = OrderedDict()

        # The features dictionary is laid out as follows:
        # features = {
        #     gl: {                        # api
        #         GL_VERSION_1_0: {        # name
        #             'info': {
        #                 'api': gl,
        #                 'version': 1.0,
        #                 'name': GL_VERSION_1_0,
        #             },
        #             'default': {  # Items in default are port of all profiles
        #                 'require': {
        #                     'enum': [],
        #                     'command': [],
        #                 },
        #                 'remove': {
        #                     'enum': [],
        #                     'command': [],
        #                 }
        #             }, # profiles will be after default (core / compatability)
        #         }
        #     }
        # }
        self.features = OrderedDict()

        self.extensions = OrderedDict()

        self.tag = 'registry'

        self.register_parser('registry/commands', Commands)
        self.register_parser('registry/feature', Feature)
        self.register_parser('registry/extensions', Extensions)

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()

        # No need for a full class to parse enums
        if 'registry/enums/enum' in tagPath:
            self.enums[attrs['name']] = attrs['value']

def parse_registry(xmlFile):
    reg = xml.parse_xml(Registry, xmlFile)
    return (reg.enums, reg.commands, reg.features, reg.extensions)

#  Higher level Tree-like View of parser classes.
#
#     - Registry
#       - Commands
#         - Command
#       - Feature
<commit_msg>Some registry parser style cleanups<commit_after>from collections import OrderedDict

from pglgen import xml

class Command(xml.BaseParser):
    '''Parse xml registry command tags'''

    def init_data(self):

        self.name = None
        self.rtnType = []
        self.params = []

        self.protoParam = []

        self.parent.commands.append(self)

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()
        if 'command/proto/name' in tagPath:
            self.name = data[0]
        elif 'command/proto' in tagPath:
            for i in data:
                if i not in self.rtnType and i is not '':
                    if '*' in i and len(i) > 1:  # split pointer from type
                        info = i.split(' ')
                        self.rtnType.extend(info)
                    else:
                        self.rtnType.append(i)
        elif 'command/param/name' in tagPath:
            self.params.append([data[0].strip(), self.protoParam])
            self.protoParam = []
        elif 'command/param' in tagPath:
            for i in data:
                if i not in self.protoParam and i is not '':
                    if '*' in i and len(i) > 1:  # split pointer from type
                        info = i.split(' ')
                        self.protoParam.extend(info)
                    else:
                        self.protoParam.append(i)

class Commands(xml.BaseParser):
    '''Integrate changes from the indivdual Command parsers.'''

    def init_data(self):

        self.commands = []

        self.register_parser('registry/commands/command', Command)

    def integrate(self):
        for cmd in self.commands:
            attr = {
                'parms': cmd.params,
                'return': cmd.rtnType,
            }
            self.root.commands[cmd.name] = attr

class Feature(xml.BaseParser):

    def init_data(self):

        self.name = None
        self.api = None
        self.version = None

        self.default = OrderedDict()
        self.profile_setup(self.default)

        self.profiles = OrderedDict()

        #self.parent.features.append(self)

    @staticmethod
    def profile_setup(profileDict):
        profileDict.update({
            'require': {
                'enum': [],
                'command': [],
            },
            'remove': {
                'enum': [],
                'command': [],
            }
        })

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()

        if ('feature/require/enum' in tagPath or
            'feature/require/command' in tagPath or
            'feature/remove/enum' in tagPath or
            'feature/remove/command' in tagPath):

            # The xml parser calls the parser when the full tag data is read.
            # So in order to get certain information before that happens a stack
            # traversal is needed. This is to set various information from the
            # feature tag that is needed in various tags contained within the tag.
            if self.name is None or self.version is None or self.api is None:
                ptag, pattrs, pdata = self.stack.peek(posRel=2)
                self.name = pattrs['name']
                self.version = pattrs['number']
                self.api = pattrs['api']

            featureStatus, pattrs, pdata = self.stack.peek(posRel=1)
            if 'profile' in pattrs.keys():
                profile = pattrs['profile']
                if profile not in self.profiles.keys():
                    self.profiles[profile] = {}
                    self.profile_setup(self.profiles[profile])

                self.profiles[profile][featureStatus][tag].append(attrs['name'])
            else:
                self.default[featureStatus][tag].append(attrs['name'])

    def integrate(self):

        info = {
            'api': self.api,
            'version': self.version,
            'name': self.name
        }

        features = {
            'info': info,
            'default': self.default,
        }

        # merge any profiles into parent master
        features.update(self.profiles)

        try:
            self.parent.features[self.api]
        except:
            od = OrderedDict()
            od[self.name] = features
            self.parent.features[self.api] = od
        else:
            self.parent.features[self.api][self.name] = features

class Extensions(xml.BaseParser):

    def init_data(self):

        self.name = None
        self.api = None
        self.version = None

        self.extensions = OrderedDict()

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()

        if ('extension/require/enum' in tagPath or
            'extension/require/command' in tagPath):

            ptag, pattrs, pdata = self.stack.peek(posRel=2)
            self.name = pattrs['name']
            self.supported = pattrs['supported']
            try:
                self.extensions[self.name][tag].append(attrs['name'])
            except KeyError:
                self.extensions[self.name] = {'enum': [], 'command': []}
                self.extensions[self.name][tag].append(attrs['name'])

    def integrate(self):
        self.parent.extensions.update(self.extensions)

class Registry(xml.BaseParser):

    def init_data(self):

        self.enums = OrderedDict()
        self.commands = OrderedDict()

        # The features dictionary is laid out as follows:
        # features = {
        #     gl: {                        # api
        #         GL_VERSION_1_0: {        # name
        #             'info': {
        #                 'api': gl,
        #                 'version': 1.0,
        #                 'name': GL_VERSION_1_0,
        #             },
        #             'default': {  # Items in default are port of all profiles
        #                 'require': {
        #                     'enum': [],
        #                     'command': [],
        #                 },
        #                 'remove': {
        #                     'enum': [],
        #                     'command': [],
        #                 }
        #             }, # profiles will be after default (core / compatability)
        #         }
        #     }
        # }
        self.features = OrderedDict()

        self.extensions = OrderedDict()

        self.tag = 'registry'

        self.register_parser('registry/commands', Commands)
        self.register_parser('registry/feature', Feature)
        self.register_parser('registry/extensions', Extensions)

    def parse(self):

        tagPath = self.stack.path()
        tag, attrs, data = self.stack.peek()

        # No need for a full class to parse enums
        if 'registry/enums/enum' in tagPath:
            self.enums[attrs['name']] = attrs['value']

def parse_registry(xmlFile):
    reg = xml.parse_xml(Registry, xmlFile)
    return (reg.enums, reg.commands, reg.features, reg.extensions)

#  Higher level Tree-like View of parser classes.
#
#     - Registry
#       - Commands
#         - Command
#       - Feature
<|endoftext|>


<commit_before>"""Pylons middleware initialization"""
from beaker.middleware import CacheMiddleware, SessionMiddleware
from paste.cascade import Cascade
from paste.registry import RegistryManager
from paste.urlparser import StaticURLParser
from paste.deploy.converters import asbool
from pylons import config
from pylons.middleware import ErrorHandler, StatusCodeRedirect
from pylons.wsgiapp import PylonsApp
from routes.middleware import RoutesMiddleware
from paste.debug.profile import make_profile_middleware

from adhocracy.lib.authentication import setup_auth
from adhocracy.lib.instance import setup_discriminator
from adhocracy.config.environment import load_environment

def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
    """Create a Pylons WSGI application and return it

    ``global_conf``
        The inherited configuration for this application. Normally from
        the [DEFAULT] section of the Paste ini file.

    ``full_stack``
        Whether this application provides a full WSGI stack (by default,
        meaning it handles its own exceptions and errors). Disable
        full_stack when this application is "managed" by another WSGI
        middleware.

    ``static_files``
        Whether this application serves its own static files; disable
        when another web server is responsible for serving them.

    ``app_conf``
        The application's local configuration. Normally specified in
        the [app:<name>] section of the Paste ini file (where <name>
        defaults to main).

    """
    # Configure the Pylons environment
    load_environment(global_conf, app_conf)

    # The Pylons WSGI app
    app = PylonsApp()

    # Routing/Session/Cache Middleware
    app = RoutesMiddleware(app, config['routes.map'])
    app = SessionMiddleware(app, config)
    app = CacheMiddleware(app, config)

    #app = make_profile_middleware(app, config)

    # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
    app = setup_auth(app, config)
    app = setup_discriminator(app, config)

    if asbool(full_stack):
        # Handle Python exceptions
        app = ErrorHandler(app, global_conf, **config['pylons.errorware'])

    # Display error documents for 401, 403, 404 status codes (and
    # 500 when debug is disabled)
    if asbool(config['debug']):
        app = StatusCodeRedirect(app)
    else:
        app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])

    # Establish the Registry for this application
    app = RegistryManager(app)

    if asbool(static_files):
        # Serve static files
        static_app = StaticURLParser(config['pylons.paths']['static_files'])
        app = Cascade([static_app, app])

    return app
<commit_msg>[svn r370] remove profiling<commit_after>"""Pylons middleware initialization"""
from beaker.middleware import CacheMiddleware, SessionMiddleware
from paste.cascade import Cascade
from paste.registry import RegistryManager
from paste.urlparser import StaticURLParser
from paste.deploy.converters import asbool
from pylons import config
from pylons.middleware import ErrorHandler, StatusCodeRedirect
from pylons.wsgiapp import PylonsApp
from routes.middleware import RoutesMiddleware
#from paste.debug.profile import make_profile_middleware

from adhocracy.lib.authentication import setup_auth
from adhocracy.lib.instance import setup_discriminator
from adhocracy.config.environment import load_environment

def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
    """Create a Pylons WSGI application and return it

    ``global_conf``
        The inherited configuration for this application. Normally from
        the [DEFAULT] section of the Paste ini file.

    ``full_stack``
        Whether this application provides a full WSGI stack (by default,
        meaning it handles its own exceptions and errors). Disable
        full_stack when this application is "managed" by another WSGI
        middleware.

    ``static_files``
        Whether this application serves its own static files; disable
        when another web server is responsible for serving them.

    ``app_conf``
        The application's local configuration. Normally specified in
        the [app:<name>] section of the Paste ini file (where <name>
        defaults to main).

    """
    # Configure the Pylons environment
    load_environment(global_conf, app_conf)

    # The Pylons WSGI app
    app = PylonsApp()

    # Routing/Session/Cache Middleware
    app = RoutesMiddleware(app, config['routes.map'])
    app = SessionMiddleware(app, config)
    app = CacheMiddleware(app, config)

    #app = make_profile_middleware(app, config)

    # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
    app = setup_auth(app, config)
    app = setup_discriminator(app, config)

    if asbool(full_stack):
        # Handle Python exceptions
        app = ErrorHandler(app, global_conf, **config['pylons.errorware'])

    # Display error documents for 401, 403, 404 status codes (and
    # 500 when debug is disabled)
    if asbool(config['debug']):
        app = StatusCodeRedirect(app)
    else:
        app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])

    # Establish the Registry for this application
    app = RegistryManager(app)

    if asbool(static_files):
        # Serve static files
        static_app = StaticURLParser(config['pylons.paths']['static_files'])
        app = Cascade([static_app, app])

    return app
<|endoftext|>


<commit_before>"""
birthday.py
Author: Daniel Wilson
Credit: <list sources used, if any>
Assignment:

Your program will ask the user the following questions, in this order:

1. Their name.
2. The name of the month they were born in (e.g. "September").
3. The year they were born in (e.g. "1962").
4. The day they were born on (e.g. "11").

If the user's birthday fell on October 31, then respond with:

  You were born on Halloween!

If the user's birthday fell on today's date, then respond with:

  Happy birthday!

Otherwise respond with a statement like this:

  Peter, you are a winter baby of the nineties.

Example Session

  Hello, what is your name? Eric
  Hi Eric, what was the name of the month you were born in? September
  And what year were you born in, Eric? 1972
  And the day? 11
  Eric, you are a fall baby of the stone age.
"""
from datetime import datetime
from calendar import month_name
todaymonth = datetime.today().month
todaydate = datetime.today().day

n = input("What is your name? ")
m = input("Hi " + n + ", what was the name of the month you were born in? ")
q = float(input("What year were you born in, " + n + "? "))
d = float(input("And the day? "))

if m in ["December", "January", "February"] :
    Season = ("winter")
elif m in ["March", "April", "May"]:
    Season = ("spring")
elif m in ["June", "July", "August"]:
    Season = ("summer")
elif m in ["September", "October", "November"]:
    Season = ("fall")

print(season)

    <commit_msg>Updated from Brython Server: 2/2/2016 2:45:47 PM<commit_after>"""
birthday.py
Author: Daniel Wilson
Credit: <list sources used, if any>
Assignment:

Your program will ask the user the following questions, in this order:

1. Their name.
2. The name of the month they were born in (e.g. "September").
3. The year they were born in (e.g. "1962").
4. The day they were born on (e.g. "11").

If the user's birthday fell on October 31, then respond with:

  You were born on Halloween!

If the user's birthday fell on today's date, then respond with:

  Happy birthday!

Otherwise respond with a statement like this:

  Peter, you are a winter baby of the nineties.

Example Session

  Hello, what is your name? Eric
  Hi Eric, what was the name of the month you were born in? September
  And what year were you born in, Eric? 1972
  And the day? 11
  Eric, you are a fall baby of the stone age.
"""
from datetime import datetime
from calendar import month_name
todaymonth = datetime.today().month
todaydate = datetime.today().day

n = input("What is your name? ")
m = input("Hi " + n + ", what was the name of the month you were born in? ")
q = float(input("What year were you born in, " + n + "? "))
d = float(input("And the day? "))

if m in ["December", "January", "February"] :
    Season = ("winter")
elif m in ["March", "April", "May"]:
    Season = ("spring")
elif m in ["June", "July", "August"]:
    Season = ("summer")
elif m in ["September", "October", "November"]:
    Season = ("fall")

print(Season)

    <|endoftext|>