<commit_before>'''
Killmail posting cog for antinub-gregbot project.

Monitors zKillboard's redisQ api and posts killmails relevant to your corp in
the given channel.
'''
from asyncio import CancelledError, sleep
from datetime import datetime
from socket import AF_INET
import logging
from traceback import format_exception

from aiohttp import ClientResponseError, ClientSession, TCPConnector
from discord import Colour
from discord.embeds import Embed

from config import KILLMAILS
from utils.messaging import notify_owner, paginate

class Killmails:
    '''A cog which monitors zKillboard's redisQ api and posts links to
    killmails which match the provided rule'''
    def __init__(self, bot, config):
        self.logger = logging.getLogger(__name__)
        self.bot = bot
        self.conf = config
        self.colours = {
            'green': Colour(0x007a00),
            'red': Colour(0x7a0000)
        }

        self.zkb_listener = None
        connector = TCPConnector(family=AF_INET if config['force_ipv4'] else 0)
        self.session = ClientSession(connector=connector)
        self.channel = self.bot.get_channel(self.conf['channel_id'])

        self.format_tracker = {'old': 0, 'new': 0}

        self.start_listening()

    def __unload(self):
        self.zkb_listener.cancel()

    def get_health(self):
        'Returns a string describing the status of this cog'
        if not self.zkb_listener.done():
            ret_string = '\n  \u2714 Listening {}% Old Format'
        else:
            ret_string = '\n  \u2716 Not listening {}% Old Format'
        old = self.format_tracker['old']
        total = old + self.format_tracker['new']
        percentage = 100 * old / max(total, 1)
        return ret_string.format(percentage)

    def start_listening(self, delay=0):
        'Start the listen loop and add the recovery callback'
        self.zkb_listener = self.bot.loop.create_task(
            self.retrieve_kills(delay))
        self.zkb_listener.add_done_callback(self.recover)

    async def retrieve_kills(self, delay):
        '''Loops to try to retrieve killmail packages'''
        await sleep(delay)
        try:
            while True:
                try:
                    package = await self.wait_for_package()
                except ClientResponseError:
                    self.logger.warning('Ignoring ClientResponseError')
                    continue

                if package:
                    self.bot.dispatch('killmail',
                                      await self.fetch_crest_info(package))
                else:
                    self.logger.debug('Got empty package')
        except CancelledError:
            await self.session.close()
            raise CancelledError

    def recover(self, fut):
        'The loop should not break unless cancelled so restart the loop'
        self.zkb_listener = None
        if not fut.cancelled():
            exc = fut.exception()
            exc_info = (type(exc), exc, exc.__traceback__)
            self.logger.error('An error occurred, restarting the loop',
                              exc_info=exc_info)
            self.bot.loop.create_task(self.error_to_admins(exc_info))
            self.start_listening(10)

    async def error_to_admins(self, exc_info):
        'Pass on the error which caused the loop to break to admins'
        message = 'Error in killmail retrieve loop:'
        traceback = paginate(''.join(format_exception(*exc_info)),
                             '```Python\n')
        await notify_owner(self.bot, [message, *traceback])

    async def wait_for_package(self):
        'Returns a dictionary containing the contents of the redisQ package'
        async with self.session.get(self.conf['redisQ_url']) as resp:
            if resp.status == 200:
                zkb_data = await resp.json()
                return zkb_data['package']
            elif resp.status == 502:
                self.logger.info('redisQ is taking too long to respond')
            else:
                self.logger.error('redisQ: %s error occurred', resp.status)

    async def on_killmail(self, package):
        'Test the killmail for relevancy and then send to discord or ignore'
        k_id = package['killID']
        try:
            if self.is_relevant(package):
                self.logger.info('Relaying killmail, ID: %s', k_id)
                embed = self.killmail_embed(package)
                msg = await self.bot.send_message(self.channel, embed=embed)
                if embed.colour == self.colours['red']:
                    await self.bot.add_reaction(msg, '\U0001F1EB')
            else:
                self.logger.debug('Ignoring killmail')
        except KeyError:
            self.logger.exception("Key Error")

    def is_relevant(self, package):
        'Returns True if a killmail should be relayed to discord'
        value = package['zkb']['totalValue'] / 1000000.0
        if value >= self.conf['others_value'] and self.conf['others_value']:
            return True

        try:
            self.format_tracker['new'] += 1
            old_format = False
            killmail = package['killmail']
        except KeyError:  # zkb pls
            self.format_tracker['old'] += 1
            old_format = True
            killmail = package

        if old_format:
            victim_corp = str(killmail['victim']['corporation']['id'])
        else:
            victim_corp = str(killmail['victim']['corporation_id'])
        if victim_corp in self.conf['corp_ids']:
            if value >= self.conf['corp_ids'][victim_corp]:
                return True

        for attacker in killmail['attackers']:
            if 'corporation' in attacker:
                if old_format:
                    attacker_corp = str(attacker['corporation']['id'])
                else:
                    attacker_corp = str(attacker['corporation_id'])
                if attacker_corp in self.conf['corp_ids']:
                    if value >= self.conf['corp_ids'][attacker_corp]:
                        return True

        return False

    async def fetch_crest_info(self, package):
        'Fills in potentially missing information from CREST api'
        zkb = package['zkb']  # The zkb specific part of the package
        url = 'https://crest-tq.eveonline.com/killmails/{}/{}/'.format(
            package['killID'],
            zkb['hash']
        )
        async with self.session.get(url) as resp:
            if resp.status == 200:
                crest_data = await resp.json()
                crest_data['zkb'] = zkb
                return crest_data
            elif resp.status == 502:
                self.logger.info('CREST is taking too long to respond')
            else:
                self.logger.error('CREST: %s error occurred', resp.status)

    def killmail_embed(self, package):
        'Generates the embed which the killmail will be posted in'
        victim = package['victim']
        if 'character' in victim:
            victim_str = '{} ({})'.format(
                victim['character']['name'],
                victim['corporation']['name'])
        else:
            victim_str = victim['corporation']['name']
        ship = victim['shipType']

        embed = Embed()
        embed.title = '{} | {} | {}'.format(
            package['solarSystem']['name'],
            ship['name'],
            victim['corporation']['name'])
        embed.description = ('{} lost their {} in {}\n'
                             'Total Value: {:,} ISK\n'
                             '\u200b').format(
                                 victim_str,
                                 ship['name'],
                                 package['solarSystem']['name'],
                                 package['zkb']['totalValue'])
        embed.url = 'https://zkillboard.com/kill/{}/'.format(package['killID'])
        embed.timestamp = datetime.strptime(package['killTime'],
                                            '%Y.%m.%d %H:%M:%S')
        if victim['corporation']['id_str'] in self.conf['corp_ids']:
            embed.colour = self.colours['red']
        else:
            embed.colour = self.colours['green']
        embed.set_thumbnail(url=('http://imageserver.eveonline.com/Type/'
                                 '{}_64.png').format(ship['id_str']))
        return embed

def setup(bot):
    'Adds the cog to the provided discord bot'
    bot.add_cog(Killmails(bot, KILLMAILS))
<commit_msg>Fix format tracker<commit_after>'''
Killmail posting cog for antinub-gregbot project.

Monitors zKillboard's redisQ api and posts killmails relevant to your corp in
the given channel.
'''
from asyncio import CancelledError, sleep
from datetime import datetime
from socket import AF_INET
import logging
from traceback import format_exception

from aiohttp import ClientResponseError, ClientSession, TCPConnector
from discord import Colour
from discord.embeds import Embed

from config import KILLMAILS
from utils.messaging import notify_owner, paginate

class Killmails:
    '''A cog which monitors zKillboard's redisQ api and posts links to
    killmails which match the provided rule'''
    def __init__(self, bot, config):
        self.logger = logging.getLogger(__name__)
        self.bot = bot
        self.conf = config
        self.colours = {
            'green': Colour(0x007a00),
            'red': Colour(0x7a0000)
        }

        self.zkb_listener = None
        connector = TCPConnector(family=AF_INET if config['force_ipv4'] else 0)
        self.session = ClientSession(connector=connector)
        self.channel = self.bot.get_channel(self.conf['channel_id'])

        self.format_tracker = {'old': 0, 'total': 0}

        self.start_listening()

    def __unload(self):
        self.zkb_listener.cancel()

    def get_health(self):
        'Returns a string describing the status of this cog'
        if not self.zkb_listener.done():
            ret_string = '\n  \u2714 Listening {}% Old Format'
        else:
            ret_string = '\n  \u2716 Not listening {}% Old Format'
        old = self.format_tracker['old']
        total = self.format_tracker['total']
        percentage = 100 * old / max(total, 1)
        return ret_string.format(percentage)

    def start_listening(self, delay=0):
        'Start the listen loop and add the recovery callback'
        self.zkb_listener = self.bot.loop.create_task(
            self.retrieve_kills(delay))
        self.zkb_listener.add_done_callback(self.recover)

    async def retrieve_kills(self, delay):
        '''Loops to try to retrieve killmail packages'''
        await sleep(delay)
        try:
            while True:
                try:
                    package = await self.wait_for_package()
                except ClientResponseError:
                    self.logger.warning('Ignoring ClientResponseError')
                    continue

                if package:
                    self.bot.dispatch('killmail',
                                      await self.fetch_crest_info(package))
                else:
                    self.logger.debug('Got empty package')
        except CancelledError:
            await self.session.close()
            raise CancelledError

    def recover(self, fut):
        'The loop should not break unless cancelled so restart the loop'
        self.zkb_listener = None
        if not fut.cancelled():
            exc = fut.exception()
            exc_info = (type(exc), exc, exc.__traceback__)
            self.logger.error('An error occurred, restarting the loop',
                              exc_info=exc_info)
            self.bot.loop.create_task(self.error_to_admins(exc_info))
            self.start_listening(10)

    async def error_to_admins(self, exc_info):
        'Pass on the error which caused the loop to break to admins'
        message = 'Error in killmail retrieve loop:'
        traceback = paginate(''.join(format_exception(*exc_info)),
                             '```Python\n')
        await notify_owner(self.bot, [message, *traceback])

    async def wait_for_package(self):
        'Returns a dictionary containing the contents of the redisQ package'
        async with self.session.get(self.conf['redisQ_url']) as resp:
            if resp.status == 200:
                zkb_data = await resp.json()
                return zkb_data['package']
            elif resp.status == 502:
                self.logger.info('redisQ is taking too long to respond')
            else:
                self.logger.error('redisQ: %s error occurred', resp.status)

    async def on_killmail(self, package):
        'Test the killmail for relevancy and then send to discord or ignore'
        k_id = package['killID']
        try:
            if self.is_relevant(package):
                self.logger.info('Relaying killmail, ID: %s', k_id)
                embed = self.killmail_embed(package)
                msg = await self.bot.send_message(self.channel, embed=embed)
                if embed.colour == self.colours['red']:
                    await self.bot.add_reaction(msg, '\U0001F1EB')
            else:
                self.logger.debug('Ignoring killmail')
        except KeyError:
            self.logger.exception("Key Error")

    def is_relevant(self, package):
        'Returns True if a killmail should be relayed to discord'
        value = package['zkb']['totalValue'] / 1000000.0
        if value >= self.conf['others_value'] and self.conf['others_value']:
            return True

        self.format_tracker['total'] += 1
        try:
            killmail = package['killmail']
            old_format = False
        except KeyError:  # zkb pls
            killmail = package
            old_format = True
            self.format_tracker['old'] += 1

        if old_format:
            victim_corp = str(killmail['victim']['corporation']['id'])
        else:
            victim_corp = str(killmail['victim']['corporation_id'])
        if victim_corp in self.conf['corp_ids']:
            if value >= self.conf['corp_ids'][victim_corp]:
                return True

        for attacker in killmail['attackers']:
            if 'corporation' in attacker:
                if old_format:
                    attacker_corp = str(attacker['corporation']['id'])
                else:
                    attacker_corp = str(attacker['corporation_id'])
                if attacker_corp in self.conf['corp_ids']:
                    if value >= self.conf['corp_ids'][attacker_corp]:
                        return True

        return False

    async def fetch_crest_info(self, package):
        'Fills in potentially missing information from CREST api'
        zkb = package['zkb']  # The zkb specific part of the package
        url = 'https://crest-tq.eveonline.com/killmails/{}/{}/'.format(
            package['killID'],
            zkb['hash']
        )
        async with self.session.get(url) as resp:
            if resp.status == 200:
                crest_data = await resp.json()
                crest_data['zkb'] = zkb
                return crest_data
            elif resp.status == 502:
                self.logger.info('CREST is taking too long to respond')
            else:
                self.logger.error('CREST: %s error occurred', resp.status)

    def killmail_embed(self, package):
        'Generates the embed which the killmail will be posted in'
        victim = package['victim']
        if 'character' in victim:
            victim_str = '{} ({})'.format(
                victim['character']['name'],
                victim['corporation']['name'])
        else:
            victim_str = victim['corporation']['name']
        ship = victim['shipType']

        embed = Embed()
        embed.title = '{} | {} | {}'.format(
            package['solarSystem']['name'],
            ship['name'],
            victim['corporation']['name'])
        embed.description = ('{} lost their {} in {}\n'
                             'Total Value: {:,} ISK\n'
                             '\u200b').format(
                                 victim_str,
                                 ship['name'],
                                 package['solarSystem']['name'],
                                 package['zkb']['totalValue'])
        embed.url = 'https://zkillboard.com/kill/{}/'.format(package['killID'])
        embed.timestamp = datetime.strptime(package['killTime'],
                                            '%Y.%m.%d %H:%M:%S')
        if victim['corporation']['id_str'] in self.conf['corp_ids']:
            embed.colour = self.colours['red']
        else:
            embed.colour = self.colours['green']
        embed.set_thumbnail(url=('http://imageserver.eveonline.com/Type/'
                                 '{}_64.png').format(ship['id_str']))
        return embed

def setup(bot):
    'Adds the cog to the provided discord bot'
    bot.add_cog(Killmails(bot, KILLMAILS))
<|endoftext|>


<commit_before># Copyright 2016, 2017 John J. Rofrano. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Pet Store Service

Paths:
------
GET /pets - Returns a list all of the Pets
GET /pets/{id} - Returns the Pet with a given id number
POST /pets - creates a new Pet record in the database
PUT /pets/{id} - updates a Pet record in the database
DELETE /pets/{id} - deletes a Pet record in the database
"""

import os
import sys
import logging
from flask import Flask, jsonify, request, url_for, make_response, abort
from flask_api import status    # HTTP Status Codes
from werkzeug.exceptions import NotFound

# For this example we'll use SQLAlchemy, a popular ORM that supports a
# variety of backends including SQLite, MySQL, and PostgreSQL
from flask_sqlalchemy import SQLAlchemy

from models import Pet, DataValidationError

# Create Flask application
app = Flask(__name__)

# We'll just use SQLite here so we don't need an external database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db/development.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'please, tell nobody... Shhhh'
app.config['LOGGING_LEVEL'] = logging.INFO

# Initialize SQLAlchemy
#db = SQLAlchemy(app)

# Pull options from environment
DEBUG = (os.getenv('DEBUG', 'False') == 'True')
PORT = os.getenv('PORT', '5000')

######################################################################
# Error Handlers
######################################################################
@app.errorhandler(DataValidationError)
def request_validation_error(error):
    """ Handles Value Errors from bad data """
    return bad_request(error)

@app.errorhandler(400)
def bad_request(error):
    """ Handles bad reuests with 400_BAD_REQUEST """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=400, error='Bad Request', message=message), 400

@app.errorhandler(404)
def not_found(error):
    """ Handles resources not found with 404_NOT_FOUND """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=404, error='Not Found', message=message), 404

@app.errorhandler(405)
def method_not_supported(error):
    """ Handles unsuppoted HTTP methods with 405_METHOD_NOT_SUPPORTED """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=405, error='Method not Allowed', message=message), 405

@app.errorhandler(415)
def mediatype_not_supported(error):
    """ Handles unsuppoted media requests with 415_UNSUPPORTED_MEDIA_TYPE """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=415, error='Unsupported media type', message=message), 415

@app.errorhandler(500)
def internal_server_error(error):
    """ Handles unexpected server error with 500_SERVER_ERROR """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=500, error='Internal Server Error', message=message), 500

######################################################################
# GET INDEX
######################################################################
@app.route('/')
def index():
    """ Root URL response """
    return jsonify(name='Pet Demo REST API Service',
                   version='1.0',
                   paths=url_for('list_pets', _external=True)
                  ), status.HTTP_200_OK

######################################################################
# LIST ALL PETS
######################################################################
@app.route('/pets', methods=['GET'])
def list_pets():
    """ Returns all of the Pets """
    pets = []
    category = request.args.get('category')
    name = request.args.get('name')
    if category:
        pets = Pet.find_by_category(category)
    elif name:
        pets = Pet.find_by_name(name)
    else:
        pets = Pet.all()

    results = [pet.serialize() for pet in pets]
    return make_response(jsonify(results), status.HTTP_200_OK)

######################################################################
# RETRIEVE A PET
######################################################################
@app.route('/pets/<int:pet_id>', methods=['GET'])
def get_pets(pet_id):
    """
    Retrieve a single Pet

    This endpoint will return a Pet based on it's id
    """
    pet = Pet.find(pet_id)
    if not pet:
        raise NotFound("Pet with id '{}' was not found.".format(pet_id))
    return make_response(jsonify(pet.serialize()), status.HTTP_200_OK)

######################################################################
# ADD A NEW PET
######################################################################
@app.route('/pets', methods=['POST'])
def create_pets():
    """
    Creates a Pet
    This endpoint will create a Pet based the data in the body that is posted
    """
    check_content_type('application/json')
    pet = Pet()
    pet.deserialize(request.get_json())
    pet.save()
    message = pet.serialize()
    location_url = url_for('get_pets', pet_id=pet.id, _external=True)
    return make_response(jsonify(message), status.HTTP_201_CREATED,
                         {
                             'Location': location_url
                         })

######################################################################
# UPDATE AN EXISTING PET
######################################################################
@app.route('/pets/<int:pet_id>', methods=['PUT'])
def update_pets(pet_id):
    """
    Update a Pet

    This endpoint will update a Pet based the body that is posted
    """
    check_content_type('application/json')
    pet = Pet.find(pet_id)
    if not pet:
        raise NotFound("Pet with id '{}' was not found.".format(pet_id))
    pet.deserialize(request.get_json())
    pet.id = pet_id
    pet.save()
    return make_response(jsonify(pet.serialize()), status.HTTP_200_OK)

######################################################################
# DELETE A PET
######################################################################
@app.route('/pets/<int:pet_id>', methods=['DELETE'])
def delete_pets(pet_id):
    """
    Delete a Pet

    This endpoint will delete a Pet based the id specified in the path
    """
    pet = Pet.find(pet_id)
    if pet:
        pet.delete()
    return make_response('', status.HTTP_204_NO_CONTENT)

######################################################################
#  U T I L I T Y   F U N C T I O N S
######################################################################

def init_db():
    """ Initialies the SQLAlchemy app """
    global app
    Pet.init_db(app)

def check_content_type(content_type):
    """ Checks that the media type is correct """
    if request.headers['Content-Type'] == content_type:
        return
    app.logger.error('Invalid Content-Type: %s', request.headers['Content-Type'])
    abort(415, 'Content-Type must be {}'.format(content_type))

def initialize_logging(log_level=logging.INFO):
    """ Initialized the default logging to STDOUT """
    if not app.debug:
        print 'Setting up logging...'
        # Set up default logging for submodules to use STDOUT
        # datefmt='%m/%d/%Y %I:%M:%S %p'
        fmt = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
        logging.basicConfig(stream=sys.stdout, level=log_level, format=fmt)
        # Make a new log handler that uses STDOUT
        handler = logging.StreamHandler(sys.stdout)
        handler.setFormatter(logging.Formatter(fmt))
        handler.setLevel(log_level)
        # Remove the Flask default handlers and use our own
        handler_list = list(app.logger.handlers)
        for log_handler in handler_list:
            app.logger.removeHandler(log_handler)
        app.logger.addHandler(handler)
        app.logger.setLevel(log_level)
        app.logger.info('Logging handler established')

######################################################################
#   M A I N
######################################################################
if __name__ == "__main__":
    print "========================================="
    print " P E T   S E R V I C E   S T A R T I N G"
    print "========================================="
    initialize_logging(logging.INFO)
    db.create_all()  # make our sqlalchemy tables
    app.run(host='0.0.0.0', port=int(PORT), debug=DEBUG)
<commit_msg>forgot to call init_db()<commit_after># Copyright 2016, 2017 John J. Rofrano. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Pet Store Service

Paths:
------
GET /pets - Returns a list all of the Pets
GET /pets/{id} - Returns the Pet with a given id number
POST /pets - creates a new Pet record in the database
PUT /pets/{id} - updates a Pet record in the database
DELETE /pets/{id} - deletes a Pet record in the database
"""

import os
import sys
import logging
from flask import Flask, jsonify, request, url_for, make_response, abort
from flask_api import status    # HTTP Status Codes
from werkzeug.exceptions import NotFound

# For this example we'll use SQLAlchemy, a popular ORM that supports a
# variety of backends including SQLite, MySQL, and PostgreSQL
from flask_sqlalchemy import SQLAlchemy

from models import Pet, DataValidationError

# Create Flask application
app = Flask(__name__)

# We'll just use SQLite here so we don't need an external database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db/development.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'please, tell nobody... Shhhh'
app.config['LOGGING_LEVEL'] = logging.INFO

# Initialize SQLAlchemy
#db = SQLAlchemy(app)

# Pull options from environment
DEBUG = (os.getenv('DEBUG', 'False') == 'True')
PORT = os.getenv('PORT', '5000')

######################################################################
# Error Handlers
######################################################################
@app.errorhandler(DataValidationError)
def request_validation_error(error):
    """ Handles Value Errors from bad data """
    return bad_request(error)

@app.errorhandler(400)
def bad_request(error):
    """ Handles bad reuests with 400_BAD_REQUEST """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=400, error='Bad Request', message=message), 400

@app.errorhandler(404)
def not_found(error):
    """ Handles resources not found with 404_NOT_FOUND """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=404, error='Not Found', message=message), 404

@app.errorhandler(405)
def method_not_supported(error):
    """ Handles unsuppoted HTTP methods with 405_METHOD_NOT_SUPPORTED """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=405, error='Method not Allowed', message=message), 405

@app.errorhandler(415)
def mediatype_not_supported(error):
    """ Handles unsuppoted media requests with 415_UNSUPPORTED_MEDIA_TYPE """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=415, error='Unsupported media type', message=message), 415

@app.errorhandler(500)
def internal_server_error(error):
    """ Handles unexpected server error with 500_SERVER_ERROR """
    message = error.message or str(error)
    app.logger.info(message)
    return jsonify(status=500, error='Internal Server Error', message=message), 500

######################################################################
# GET INDEX
######################################################################
@app.route('/')
def index():
    """ Root URL response """
    return jsonify(name='Pet Demo REST API Service',
                   version='1.0',
                   paths=url_for('list_pets', _external=True)
                  ), status.HTTP_200_OK

######################################################################
# LIST ALL PETS
######################################################################
@app.route('/pets', methods=['GET'])
def list_pets():
    """ Returns all of the Pets """
    pets = []
    category = request.args.get('category')
    name = request.args.get('name')
    if category:
        pets = Pet.find_by_category(category)
    elif name:
        pets = Pet.find_by_name(name)
    else:
        pets = Pet.all()

    results = [pet.serialize() for pet in pets]
    return make_response(jsonify(results), status.HTTP_200_OK)

######################################################################
# RETRIEVE A PET
######################################################################
@app.route('/pets/<int:pet_id>', methods=['GET'])
def get_pets(pet_id):
    """
    Retrieve a single Pet

    This endpoint will return a Pet based on it's id
    """
    pet = Pet.find(pet_id)
    if not pet:
        raise NotFound("Pet with id '{}' was not found.".format(pet_id))
    return make_response(jsonify(pet.serialize()), status.HTTP_200_OK)

######################################################################
# ADD A NEW PET
######################################################################
@app.route('/pets', methods=['POST'])
def create_pets():
    """
    Creates a Pet
    This endpoint will create a Pet based the data in the body that is posted
    """
    check_content_type('application/json')
    pet = Pet()
    pet.deserialize(request.get_json())
    pet.save()
    message = pet.serialize()
    location_url = url_for('get_pets', pet_id=pet.id, _external=True)
    return make_response(jsonify(message), status.HTTP_201_CREATED,
                         {
                             'Location': location_url
                         })

######################################################################
# UPDATE AN EXISTING PET
######################################################################
@app.route('/pets/<int:pet_id>', methods=['PUT'])
def update_pets(pet_id):
    """
    Update a Pet

    This endpoint will update a Pet based the body that is posted
    """
    check_content_type('application/json')
    pet = Pet.find(pet_id)
    if not pet:
        raise NotFound("Pet with id '{}' was not found.".format(pet_id))
    pet.deserialize(request.get_json())
    pet.id = pet_id
    pet.save()
    return make_response(jsonify(pet.serialize()), status.HTTP_200_OK)

######################################################################
# DELETE A PET
######################################################################
@app.route('/pets/<int:pet_id>', methods=['DELETE'])
def delete_pets(pet_id):
    """
    Delete a Pet

    This endpoint will delete a Pet based the id specified in the path
    """
    pet = Pet.find(pet_id)
    if pet:
        pet.delete()
    return make_response('', status.HTTP_204_NO_CONTENT)

######################################################################
#  U T I L I T Y   F U N C T I O N S
######################################################################

def init_db():
    """ Initialies the SQLAlchemy app """
    global app
    Pet.init_db(app)

def check_content_type(content_type):
    """ Checks that the media type is correct """
    if request.headers['Content-Type'] == content_type:
        return
    app.logger.error('Invalid Content-Type: %s', request.headers['Content-Type'])
    abort(415, 'Content-Type must be {}'.format(content_type))

def initialize_logging(log_level=logging.INFO):
    """ Initialized the default logging to STDOUT """
    if not app.debug:
        print 'Setting up logging...'
        # Set up default logging for submodules to use STDOUT
        # datefmt='%m/%d/%Y %I:%M:%S %p'
        fmt = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
        logging.basicConfig(stream=sys.stdout, level=log_level, format=fmt)
        # Make a new log handler that uses STDOUT
        handler = logging.StreamHandler(sys.stdout)
        handler.setFormatter(logging.Formatter(fmt))
        handler.setLevel(log_level)
        # Remove the Flask default handlers and use our own
        handler_list = list(app.logger.handlers)
        for log_handler in handler_list:
            app.logger.removeHandler(log_handler)
        app.logger.addHandler(handler)
        app.logger.setLevel(log_level)
        app.logger.info('Logging handler established')

######################################################################
#   M A I N
######################################################################
if __name__ == "__main__":
    print "========================================="
    print " P E T   S E R V I C E   S T A R T I N G"
    print "========================================="
    initialize_logging(logging.INFO)
    init_db()  # make our sqlalchemy tables
    app.run(host='0.0.0.0', port=int(PORT), debug=DEBUG)
<|endoftext|>


<commit_before>import metalink

def test_should_parse_meta4_file():
    m4 = metalink.Metalink4()
    m4.parsefile("tests/resources/5.15.2-0-202011130602qtxmlpatterns-Windows-Windows_7-Mingw-Windows-Windows_7-X86.7z.meta4")<commit_msg>Fix formatting<commit_after>import metalink

def test_should_parse_meta4_file():
    m4 = metalink.Metalink4()
    m4.parsefile(
        "tests/resources/5.15.2-0-202011130602qtxmlpatterns-Windows-Windows_7-Mingw-Windows-Windows_7-X86.7z.meta4"
    )
<|endoftext|>


<commit_before>from django.shortcuts import render, get_object_or_404
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.views.generic import View
from models import Stream, StreamItem, StreamConnection
from forms import StreamForm
from broker.models import Connection
from broker.utils import twitter_client
from open_facebook import OpenFacebook

def expand_tweet_urls(tweet):
    text = tweet.text
    if tweet.entities['urls']:
        for entity in tweet.entities['urls']:
            url = entity['url']
            expanded = entity['expanded_url']
            text = text.replace(url, expanded)
    return text

def ingest_tweet(tweet, streamconnection):
    tweet_text = expand_tweet_urls(tweet)
    item, created = StreamItem.objects.get_or_create(stream=streamconnection.stream,
                                                     connection=streamconnection.connection,
                                                     connection_system_id=tweet.id, date=tweet.created_at)
    if created:
        item.title = tweet.id
        item.body = tweet_text
        item.linked_url = ''
        item.picture = ''
        item.type = 'tweet'
        item.permalink = u'https://twitter.com/{}/status/{}'.format(streamconnection.connection.username, tweet.id)
        if tweet.user.protected:
            item.is_published = False
        item.save()

def update_twitter(streamconnection):
    api = twitter_client(streamconnection.connection)
    tweets = api.user_timeline(exclude_replies=True, include_rts=False, count=30)
    for tweet in tweets:
        ingest_tweet(tweet, streamconnection)
    streamconnection.save()

def update_facebook(streamconnection):
    facebook = OpenFacebook(streamconnection.connection.token)
    statuses = facebook.get('me/feed')['data']
    for status in statuses:
        ingest_fb(status, streamconnection)

def ingest_fb(post, streamconnection):
    try:
        if post['name']:  # eliminate shared stories to stick with explicit shares
            item, created = StreamItem.objects.get_or_create(stream=streamconnection.stream,
                                                             connection=streamconnection.connection,
                                                             connection_system_id=post['id'], date=post['created_time'])
            if created:
                item.title = post['name']
                item.body = post['message']
                item.linked_url = post['link']
                item.picture = post['picture']
                item.type = post['type']
                item.permalink = u'https://facebook.com/{}/posts/{}'.format(streamconnection.connection.username,
                                                                            post['id'].split('_')[1])
                item.save()

    except KeyError:
        pass

class ActivityStream(View):

    def get(self, request):
        stream, created = Stream.objects.get_or_create(user=User.objects.get(id=1))

        if not stream.streamconnection_set.all():
            return HttpResponseRedirect(reverse('activity_stream_settings'))
        else:
            for streamconnection in stream.streamconnection_set.all():
                if streamconnection.connection.provider == 'twitter':
                    _tweets = StreamItem.objects.filter(stream__user=stream.user, is_published=True,
                                                        connection__provider='twitter')
                    if not _tweets:
                        update_twitter(streamconnection)

                    if streamconnection.needs_refresh():
                        update_twitter(streamconnection)

                elif streamconnection.connection.provider == 'facebook':
                    statuses = StreamItem.objects.filter(stream__user=stream.user, is_published=True,
                                                         connection__provider='facebook')
                    if not statuses:
                        facebook = OpenFacebook(streamconnection.connection.token)
                        statuses = facebook.get('me/feed')['data']
                        for status in statuses:
                            # eliminate shared stories to stick with explicit link shares (for now)
                            try:
                                if status['name']:
                                    ingest_fb(status, streamconnection)
                            except KeyError:
                                break

                    if streamconnection.needs_refresh():
                        update_facebook(streamconnection)

                else:
                    pass  # in case the broker adds clients before activity_stream

        posts = stream.streamitem_set.all().order_by('-date')

        context = dict(stream=stream, request=request, posts=posts)
        return render(request, 'activity_stream/list.html', context)

class ActivityStreamSettings(View):

    success = False

    def post(self, request):
        stream = get_object_or_404(Stream, user=request.user)
        stream_connections = stream.streamconnection_set.all().order_by('-id')
        form = StreamForm(request.POST, instance=stream)
        if form.is_valid():
            form.save()

            # manage StreamConnection preferences
            form_connections = form.cleaned_data['streamconnections']
            for connection in stream_connections:
                if connection in form_connections:
                    if not connection.is_published:
                        connection.is_published = True
                        connection.save()
                else:
                    if connection.is_published is True:
                        connection.is_published = False
                        connection.save()

            return HttpResponseRedirect('.?success=true')
        else:
            context = dict(connections=stream_connections, stream=stream, form=form, success=self.success)
            return render(request, 'activity_stream/settings.html', context)

    def get(self, request):
        streamconnections = StreamConnection.objects.filter(stream__user=request.user).order_by('-id')
        connections = Connection.objects.filter(user=request.user).order_by('-id')
        stream = get_object_or_404(Stream, user=request.user)
        form = StreamForm(instance=stream)
        form.fields['streamconnections'].queryset = streamconnections
        form.fields['streamconnections'].initial = streamconnections.filter(is_published=True)

        if 'success' in request.GET:
            if request.GET['success'] == 'true':
                self.success = True
        context = dict(connections=connections, stream=stream, form=form, success=self.success, request=request)
        return render(request, 'activity_stream/settings.html', context)
<commit_msg>Fix timezone for tweets. Save raw data for later processing<commit_after>from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.utils import timezone
from django.views.generic import View
from models import Stream, StreamItem, StreamConnection
from forms import StreamForm
from broker.models import Connection
from broker.utils import twitter_client
from open_facebook import OpenFacebook

def expand_tweet_urls(tweet):
    text = tweet.text
    if tweet.entities['urls']:
        for entity in tweet.entities['urls']:
            url = entity['url']
            expanded = entity['expanded_url']
            text = text.replace(url, expanded)
    return text

def ingest_tweet(tweet, streamconnection):
    tweet_text = expand_tweet_urls(tweet)
    item, created = StreamItem.objects.get_or_create(stream=streamconnection.stream,
                                                     connection=streamconnection.connection,
                                                     connection_system_id=tweet.id,
                                                     date=tweet.created_at.replace(tzinfo=timezone.utc))
    if created:
        item.title = tweet.id
        item.body = tweet_text
        item.linked_url = ''
        item.picture = ''
        item.type = 'tweet'
        item.permalink = u'https://twitter.com/{}/status/{}'.format(streamconnection.connection.username, tweet.id)
        item.raw_data = tweet
        if tweet.user.protected:
            item.is_published = False
        item.save()

def update_twitter(streamconnection):
    api = twitter_client(streamconnection.connection)
    tweets = api.user_timeline(exclude_replies=True, include_rts=False, count=30)
    for tweet in tweets:
        ingest_tweet(tweet, streamconnection)
    streamconnection.save()

def update_facebook(streamconnection):
    facebook = OpenFacebook(streamconnection.connection.token)
    statuses = facebook.get('me/feed')['data']
    for status in statuses:
        ingest_fb(status, streamconnection)

def ingest_fb(post, streamconnection):
    try:
        item, created = StreamItem.objects.get_or_create(stream=streamconnection.stream,
                                                         connection=streamconnection.connection,
                                                         connection_system_id=post['id'], date=post['created_time'])
        if created:
            if 'name' in post:  # eliminate shared stories to stick with explicit shares
                item.title = post['name']
                item.body = post['message']
                item.linked_url = post['link']
                item.picture = post['picture']
                item.type = post['type']
            else:
                item.is_published = False

            item.permalink = u'https://facebook.com/{}/posts/{}'.format(streamconnection.connection.username,
                                                                        post['id'].split('_')[1])
            item.raw_data = post
            item.save()

    except KeyError:
        pass

class ActivityStream(View):

    def get(self, request):
        stream, created = Stream.objects.get_or_create(user=User.objects.get(id=1))

        if not stream.streamconnection_set.all():
            return HttpResponseRedirect(reverse('activity_stream_settings'))
        else:
            for streamconnection in stream.streamconnection_set.all():
                if streamconnection.connection.provider == 'twitter':
                    _tweets = StreamItem.objects.filter(stream__user=stream.user, is_published=True,
                                                        connection__provider='twitter')
                    if not _tweets:
                        update_twitter(streamconnection)

                    if streamconnection.needs_refresh():
                        update_twitter(streamconnection)

                elif streamconnection.connection.provider == 'facebook':
                    statuses = StreamItem.objects.filter(stream__user=stream.user, is_published=True,
                                                         connection__provider='facebook')
                    if not statuses:
                        facebook = OpenFacebook(streamconnection.connection.token)
                        statuses = facebook.get('me/feed')['data']
                        for status in statuses:
                            # eliminate shared stories to stick with explicit link shares (for now)
                            try:
                                if status['name']:
                                    ingest_fb(status, streamconnection)
                            except KeyError:
                                break

                    if streamconnection.needs_refresh():
                        update_facebook(streamconnection)

                else:
                    pass  # in case the broker adds clients before activity_stream

        posts = stream.streamitem_set.all().order_by('-date')

        context = dict(stream=stream, request=request, posts=posts)
        return render(request, 'activity_stream/list.html', context)

class ActivityStreamSettings(View):

    success = False

    def post(self, request):
        stream = get_object_or_404(Stream, user=request.user)
        stream_connections = stream.streamconnection_set.all().order_by('-id')
        form = StreamForm(request.POST, instance=stream)
        if form.is_valid():
            form.save()

            # manage StreamConnection preferences
            form_connections = form.cleaned_data['streamconnections']
            for connection in stream_connections:
                if connection in form_connections:
                    if not connection.is_published:
                        connection.is_published = True
                        connection.save()
                else:
                    if connection.is_published is True:
                        connection.is_published = False
                        connection.save()

            return HttpResponseRedirect('.?success=true')
        else:
            context = dict(connections=stream_connections, stream=stream, form=form, success=self.success)
            return render(request, 'activity_stream/settings.html', context)

    def get(self, request):
        streamconnections = StreamConnection.objects.filter(stream__user=request.user).order_by('-id')
        connections = Connection.objects.filter(user=request.user).order_by('-id')
        stream = get_object_or_404(Stream, user=request.user)
        form = StreamForm(instance=stream)
        form.fields['streamconnections'].queryset = streamconnections
        form.fields['streamconnections'].initial = streamconnections.filter(is_published=True)

        if 'success' in request.GET:
            if request.GET['success'] == 'true':
                self.success = True
        context = dict(connections=connections, stream=stream, form=form, success=self.success, request=request)
        return render(request, 'activity_stream/settings.html', context)
<|endoftext|>


<commit_before>import contextlib

from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC

class Util(object):
    def __init__(self, driver):
        self.driver = driver
        self.timeouts = [2]

    @property
    def timeout(self):
        return self.timeouts[0]

    @contextlib.contextmanager
    def local_timeout(self, value):
        self.push_timeout(value)
        try:
            yield
        finally:
            self.pop_timeout()

    def push_timeout(self, new):
        self.timeouts[0:0] = [new]

    def pop_timeout(self):
        return self.timeouts.pop(0)

    def find_element(self, locator):
        return WebDriverWait(self.driver, self.timeout).until(
            EC.presence_of_element_located(locator))

    def find_elements(self, locator):
        return WebDriverWait(self.driver, self.timeout).until(
            EC.presence_of_all_elements_located(locator))

    def find_clickable_element(self, locator):
        return WebDriverWait(self.driver, self.timeout).until(
            EC.element_to_be_clickable(locator))

    def get_text_excluding_children(self, element):
        return self.driver.execute_script("""
        return jQuery(arguments[0]).contents().filter(function() {
            return this.nodeType == Node.TEXT_NODE;
        }).text();
        """, element)

    def element_screen_position(self, element):
        return self.driver.execute_script("""
        var offset = jQuery(arguments[0]).offset();
        offset.top -= document.body.scrollTop;
        offset.left -= document.body.scrollLeft;
        return offset;
        """,
        element)

    def get_selection_text(self):
        """
        Gets the text of the current selection.

        .. node:: This function requires that ``rangy`` be installed.

        :returns: The text.
        :rtype: class:`basestring`
        """
        return self.driver.execute_script("""
        return rangy.getSelection(window).toString()
        """)

    def wait(self, condition):
        return WebDriverWait(self.driver, self.timeout).until(condition)

def locations_within(a, b, tolerance):
    """
    Verifies whether two positions are the same. A tolerance value
    determines how close the two positions must be to be considered
    "same".

    The two locations must be dictionaries that have the same keys. If
    a key is pesent in one but not in the other, this is an error. The
    values must be integers or anything that can be converted to an
    integer through ``int``. (If somehow you need floating point
    precision, this is not the function for you.)

    Do not rely on this function to determine whether two object have
    the same keys. If the function returns ``True``, then the two
    objects have the same keys. If the function returns ``False``,
    then you cannot infer anything regarding the keys because the
    function will return ``False`` as soon as it knows that the two
    locations are **not** within tolerance.

    :param a: First position.
    :type a: :class:`dict`
    :param b: Second position.
    :type b: :class:`dict`
    :param tolerance: The tolerance within which the two positions
                      must be.
    :return: An empty string if the comparison is
             successful. Otherwise, the string contains a description
             of the differences.
    :rtype: :class:`str`
    :raises ValueError: When a key is present in one object but not
                        the other.
    """
    ret = ''
    # Clone b so that we can destroy it.
    b = dict(b)

    for (key, value) in a.items():
        if key not in b:
            raise ValueError("b does not have the key: " + key)
        if abs(int(value) - int(b[key])) > tolerance:
            ret += 'key {0} differs: {1} {2}'.format(key, int(value),
                                                     int(b[key]))
        del b[key]

    if b:
        raise ValueError("keys in b not seen in a: " + ", ".join(b.keys()))

    return ret
<commit_msg>Added methods for scrolling + some documentation.<commit_after>import contextlib

from selenium.webdriver.support.ui import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC

class Util(object):
    def __init__(self, driver):
        self.driver = driver
        self.timeouts = [2]

    @property
    def timeout(self):
        return self.timeouts[0]

    @contextlib.contextmanager
    def local_timeout(self, value):
        self.push_timeout(value)
        try:
            yield
        finally:
            self.pop_timeout()

    def push_timeout(self, new):
        self.timeouts[0:0] = [new]

    def pop_timeout(self):
        return self.timeouts.pop(0)

    def find_element(self, locator):
        return WebDriverWait(self.driver, self.timeout).until(
            EC.presence_of_element_located(locator))

    def find_elements(self, locator):
        return WebDriverWait(self.driver, self.timeout).until(
            EC.presence_of_all_elements_located(locator))

    def find_clickable_element(self, locator):
        return WebDriverWait(self.driver, self.timeout).until(
            EC.element_to_be_clickable(locator))

    def get_text_excluding_children(self, element):
        return self.driver.execute_script("""
        return jQuery(arguments[0]).contents().filter(function() {
            return this.nodeType == Node.TEXT_NODE;
        }).text();
        """, element)

    def element_screen_position(self, element):
        return self.driver.execute_script("""
        var offset = jQuery(arguments[0]).offset();
        offset.top -= document.body.scrollTop;
        offset.left -= document.body.scrollLeft;
        return offset;
        """,
        element)

    def get_selection_text(self):
        """
        Gets the text of the current selection.

        .. node:: This function requires that ``rangy`` be installed.

        :returns: The text.
        :rtype: class:`basestring`
        """
        return self.driver.execute_script("""
        return rangy.getSelection(window).toString()
        """)

    def scroll_top(self, element):
        """
        Gets the top of the scrolling area of the element.

        :param element: An element on the page.
        :type element: :class:`selenium.webdriver.remote.webelement.WebElement`
        :returns: The top of the scrolling area.
        """
        return self.driver.execute_script("""
        return arguments[0].scrollTop;
        """, element)

    def window_scroll_top(self):
        """
        Gets the top of the scrolling area for ``window``.

        :returns: The top of the scrolling area.
        """
        return self.driver.execute_script("""
        return window.scrollY;
        """)

    def window_scroll_left(self):
        """
        Gets the left of the scrolling area for ``window``.

        :returns: The left of the scrolling area.
        """
        return self.driver.execute_script("""
        return window.scrollX;
        """)

    def wait(self, condition):
        """
        Waits for a condition to be true.

        :param condition: Should be a callable that operates in the
                          same way ``WebDriverWait.until`` expects.
        :returns: Whatever ``WebDriverWait.until`` returns.
        """
        return WebDriverWait(self.driver, self.timeout).until(condition)

    def wait_until_not(self, condition):
        """
        Waits for a condition to be false.

        :param condition: Should be a callable that operates in the
                          same way ``WebDriverWait.until_not`` expects.
        :returns: Whatever ``WebDriverWait.until_not`` returns.
        """
        return WebDriverWait(self.driver, self.timeout).until_not(condition)

def locations_within(a, b, tolerance):
    """
    Verifies whether two positions are the same. A tolerance value
    determines how close the two positions must be to be considered
    "same".

    The two locations must be dictionaries that have the same keys. If
    a key is pesent in one but not in the other, this is an error. The
    values must be integers or anything that can be converted to an
    integer through ``int``. (If somehow you need floating point
    precision, this is not the function for you.)

    Do not rely on this function to determine whether two object have
    the same keys. If the function returns ``True``, then the two
    objects have the same keys. If the function returns ``False``,
    then you cannot infer anything regarding the keys because the
    function will return ``False`` as soon as it knows that the two
    locations are **not** within tolerance.

    :param a: First position.
    :type a: :class:`dict`
    :param b: Second position.
    :type b: :class:`dict`
    :param tolerance: The tolerance within which the two positions
                      must be.
    :return: An empty string if the comparison is
             successful. Otherwise, the string contains a description
             of the differences.
    :rtype: :class:`str`
    :raises ValueError: When a key is present in one object but not
                        the other.
    """
    ret = ''
    # Clone b so that we can destroy it.
    b = dict(b)

    for (key, value) in a.items():
        if key not in b:
            raise ValueError("b does not have the key: " + key)
        if abs(int(value) - int(b[key])) > tolerance:
            ret += 'key {0} differs: {1} {2}'.format(key, int(value),
                                                     int(b[key]))
        del b[key]

    if b:
        raise ValueError("keys in b not seen in a: " + ", ".join(b.keys()))

    return ret
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from openerp import api, models, fields, _
from openerp.exceptions import except_orm
from datetime import date, timedelta
from openerp.exceptions import Warning

def _all_taxes(x):
    return True

def _all_except_vat(x):
    return x.tax_code_id.parent_id.name != 'IVA'

class account_invoice_line(models.Model):
    """
    Line of an invoice. Compute pirces with and without vat,
    for unit or line quantity.
    """
    _name = "account.invoice.line"
    _inherit = "account.invoice.line"

    @api.one
    @api.depends('quantity', 'discount', 'price_unit', 'invoice_line_tax_id',
                 'product_id', 'invoice_id.partner_id',
                 'invoice_id.currency_id')
    def compute_price(self, context=None):
        self.price_unit_vat_included = self.price_calc(use_vat=True, quantity=1)
        self.price_subtotal_vat_included = self.price_calc(use_vat=True)
        self.price_unit_not_vat_included = self.price_calc(use_vat=False,
                                                           quantity=1)
        self.price_subtotal_not_vat_included = self.price_calc(use_vat=False)

    price_unit_vat_included = fields.Float(compute='compute_price')
    price_subtotal_vat_included = fields.Float(compute='compute_price')
    price_unit_not_vat_included = fields.Float(compute='compute_price')
    price_subtotal_not_vat_included = fields.Float(compute='compute_price')

    @api.v8
    def price_calc(self, use_vat=True, tax_filter=None, quantity=None,
                   discount=None, context=None):
        assert len(self) == 1, "Use price_calc with one instance"
        _tax_filter = tax_filter or (use_vat and _all_taxes) or _all_except_vat
        _quantity = quantity if quantity is not None else self.quantity
        _discount = discount if discount is not None else self.discount
        _price = self.price_unit * (1-(_discount or 0.0)/100.0)

        taxes = self.invoice_line_tax_id.filtered(_tax_filter).compute_all(
            _price, _quantity,
            product=self.product_id,
            partner=self.invoice_id.partner_id
        )
        return self.invoice_id.currency_id.round(taxes['total_included']) \
            if self.invoice_id else taxes['total_included']

    @api.v8
    def compute_all(self, tax_filter=lambda tax: True, context=None):
        res = {}
        for line in self:
            _quantity = line.quantity
            _discount = line.discount
            _price = line.price_unit * (1-(_discount or 0.0)/100.0)
            taxes = line.invoice_line_tax_id.filtered(tax_filter).compute_all(
                _price, _quantity,
                product=line.product_id,
                partner=line.invoice_id.partner_id)

            if line.invoice_id:
                def _round(x):
                    return line.invoice_id.currency_id.round(x)
            else:
                def _round(x):
                    return x

            res[line.id] = {
                'amount_untaxed': _round(taxes['total']),
                'amount_tax': _round(taxes['total_included']) -
                _round(taxes['total']),
                'amount_total': _round(taxes['total_included']),
                'taxes': taxes['taxes'],
            }
        return res.get(len(self) == 1 and res.keys()[0], res)

account_invoice_line()

def _calc_concept(product_types):
    if product_types == set(['consu']):
        concept = '1'
    elif product_types == set(['service']):
        concept = '2'
    elif product_types == set(['consu', 'service']):
        concept = '3'
    else:
        raise Warning(
            _('Cant compute AFIP concept from product types %s.') %
            product_types
        )
    return concept

class account_invoice(models.Model):
    """
    Argentine invoice functions.
    """
    _name = "account.invoice"
    _inherit = "account.invoice"

    @api.depends('invoice_line.product_id.type')
    def _get_concept(self):
        """
        Compute concept type from selected products in invoice.
        """
        concept_obj = self.env['afip.concept_type']

        for inv in self:
            product_types = set([
                line.product_id.type for line in inv.invoice_line
            ])
            if False in product_types:
                raise Warning("Products %s has not defined type" % ','.join(
                    line.product_id.name for line in inv.invoice_line
                    if line.product_id.type is False
                ))
            inv.afip_concept = concept_obj.get_code(product_types)

    def _get_service_begin_date(self):
        today = date.today()
        first = date(day=1, month=today.month, year=today.year)
        prev_last_day = first - timedelta(days=1)
        period = self.period_id.find(prev_last_day)
        return period and period.date_start or False

    def _get_service_end_date(self):
        today = date.today()
        first = date(day=1, month=today.month, year=today.year)
        prev_last_day = first - timedelta(days=1)
        period = self.period_id.find(prev_last_day)
        return period and prev_last_day or False

    afip_concept = fields.Selection(
        [('1', 'Consumible'), ('2', 'Service'), ('3', 'Mixted')],
        compute="_get_concept",
        store=False,
        help="AFIP invoice concept.")
    afip_service_start = fields.Date(
        'Service Start Date', default=_get_service_begin_date)
    afip_service_end = fields.Date(
        'Service End Date', default=_get_service_end_date)

    def afip_validation(self):
        """
        Check basic AFIP request to generate invoices.
        """
        for invoice in self:
            # If parter is not in Argentina, ignore it.
            if invoice.company_id.partner_id.country_id.name != 'Argentina':
                continue

            # Check if you choose the right journal.
            if invoice.type == 'out_invoice' and \
                    invoice.journal_id.journal_class_id.afip_code not in\
                    [1, 6, 11, 51, 19, 2, 7, 12, 52, 20]:
                raise except_orm(
                    _('Wrong Journal'),
                    _('Out invoice journal must have a valid journal class.'))
            if invoice.type == 'out_refund' and \
                    invoice.journal_id.journal_class_id.afip_code not in\
                    [3, 8, 13, 53, 21]:
                raise except_orm(
                    _('Wrong Journal'),
                    _('Out invoice journal must have a valid journal class.'))

            # Partner responsability ?
            partner = invoice.partner_id
            if not partner.responsability_id:
                raise except_orm(
                    _('No responsability'),
                    _('Your partner have not afip responsability assigned.'
                      ' Assign one please.'))

            # Take responsability classes for this journal
            invoice_class = \
                invoice.journal_id.journal_class_id.document_class_id
            company = invoice.journal_id.company_id.partner_id
            resp_class = \
                self.env['afip.responsability_relation'].search(
                    [('document_class_id', '=', invoice_class.id),
                     ('issuer_id.code', '=', company.responsability_id.code)])

            # You can emmit this document?
            if not resp_class:
                raise except_orm(
                    _('Invalid emisor'),
                    _('Your responsability with AFIP dont let you generate'
                      ' this kind of document.'))

            # Partner can receive this document?
            resp_class = \
                self.env['afip.responsability_relation'].search([
                    ('document_class_id', '=', invoice_class.id),
                    ('receptor_id.code', '=', partner.responsability_id.code)
                ])
            if not resp_class:
                raise Warning(
                    _('Invalid receptor\n'
                      'Your partner (%s) can\'t receive this document (%s).'
                      ' Check AFIP responsability of the partner,'
                      ' or Journal Account of the invoice.') %
                    (partner.responsability_id.name, invoice_class.name))

            # If Final Consumer have pay more than 1000$,
            # you need more information to generate document.
            if partner.responsability_id.code == 'CF' \
                    and invoice.amount_total > 1000 and \
                    (partner.document_type_id.code in [None, 'Sigd']
                     or invoice.partner_id.document_number is None):
                raise except_orm(_('Partner without Identification for total'
                                   ' invoices > $1000.-'),
                                 _('You must define valid document type and'
                                   ' number for this Final Consumer.'))
        return True

    def compute_all(self, cr, uid, ids, line_filter=lambda line: True,
                    tax_filter=lambda tax: True, context=None):
        res = {}
        for inv in self.browse(cr, uid, ids, context=context):
            amounts = []
            for line in inv.invoice_line:
                if line_filter(line):
                    amounts.append(line.compute_all(tax_filter=tax_filter,
                                                    context=context))

            s = {
                'amount_total': 0,
                'amount_tax': 0,
                'amount_untaxed': 0,
                'taxes': []
            }
            for amount in amounts:
                for key, value in amount.items():
                    s[key] = s.get(key, 0) + value

            res[inv.id] = s

        return res.get(len(ids) == 1 and ids[0], res)

    @api.multi
    @api.onchange('partner_id', 'company_id')
    def _onchange_partner_id(self):
        # Set list of valid journals by partner responsability
        # partner_obj = self.pool.get('res.partner')
        partner = self.partner_id
        company = self.company_id
        responsability = partner.responsability_id
        result = {}

        if not responsability:
            msg = {
                'title': _('The partner has not set any fiscal responsability'),
                'message': _('Please, set partner fiscal responsability in the'
                             ' partner form before continuing.')
            }
            return {'warning', msg}

        if responsability.issuer_relation_ids is None:
            return {}

        if not company.partner_id.responsability_id.id:
            msg = {
                'title': _('Your company has not set any fiscal'
                           ' responsability'),
                'message': _('Please, set your company responsability in the'
                             ' company form before continuing.')
            }
            return {'warning', msg}

        accepted_journal_ids = self.partner_id.prefered_journals(
            self.company_id.id, self.type)

        if accepted_journal_ids:
            result['domain'].update({
                'journal_id': [('id', 'in', accepted_journal_ids)],
            })
            self.journal_id = accepted_journal_ids[0]
        else:
            result['domain'].update({
                'journal_id': [('id', 'in', [])],
            })
            self.journal_id = False

        return result

account_invoice()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>Fixing issue product type<commit_after># -*- coding: utf-8 -*-
from openerp import api, models, fields, _
from openerp.exceptions import except_orm
from datetime import date, timedelta
from openerp.exceptions import Warning

def _all_taxes(x):
    return True

def _all_except_vat(x):
    return x.tax_code_id.parent_id.name != 'IVA'

class account_invoice_line(models.Model):
    """
    Line of an invoice. Compute pirces with and without vat,
    for unit or line quantity.
    """
    _name = "account.invoice.line"
    _inherit = "account.invoice.line"

    @api.one
    @api.depends('quantity', 'discount', 'price_unit', 'invoice_line_tax_id',
                 'product_id', 'invoice_id.partner_id',
                 'invoice_id.currency_id')
    def compute_price(self, context=None):
        self.price_unit_vat_included = self.price_calc(use_vat=True, quantity=1)
        self.price_subtotal_vat_included = self.price_calc(use_vat=True)
        self.price_unit_not_vat_included = self.price_calc(use_vat=False,
                                                           quantity=1)
        self.price_subtotal_not_vat_included = self.price_calc(use_vat=False)

    price_unit_vat_included = fields.Float(compute='compute_price')
    price_subtotal_vat_included = fields.Float(compute='compute_price')
    price_unit_not_vat_included = fields.Float(compute='compute_price')
    price_subtotal_not_vat_included = fields.Float(compute='compute_price')

    @api.v8
    def price_calc(self, use_vat=True, tax_filter=None, quantity=None,
                   discount=None, context=None):
        assert len(self) == 1, "Use price_calc with one instance"
        _tax_filter = tax_filter or (use_vat and _all_taxes) or _all_except_vat
        _quantity = quantity if quantity is not None else self.quantity
        _discount = discount if discount is not None else self.discount
        _price = self.price_unit * (1-(_discount or 0.0)/100.0)

        taxes = self.invoice_line_tax_id.filtered(_tax_filter).compute_all(
            _price, _quantity,
            product=self.product_id,
            partner=self.invoice_id.partner_id
        )
        return self.invoice_id.currency_id.round(taxes['total_included']) \
            if self.invoice_id else taxes['total_included']

    @api.v8
    def compute_all(self, tax_filter=lambda tax: True, context=None):
        res = {}
        for line in self:
            _quantity = line.quantity
            _discount = line.discount
            _price = line.price_unit * (1-(_discount or 0.0)/100.0)
            taxes = line.invoice_line_tax_id.filtered(tax_filter).compute_all(
                _price, _quantity,
                product=line.product_id,
                partner=line.invoice_id.partner_id)

            if line.invoice_id:
                def _round(x):
                    return line.invoice_id.currency_id.round(x)
            else:
                def _round(x):
                    return x

            res[line.id] = {
                'amount_untaxed': _round(taxes['total']),
                'amount_tax': _round(taxes['total_included']) -
                _round(taxes['total']),
                'amount_total': _round(taxes['total_included']),
                'taxes': taxes['taxes'],
            }
        return res.get(len(self) == 1 and res.keys()[0], res)

account_invoice_line()

def _calc_concept(product_types):
    if product_types == set(['consu']):
        concept = '1'
    elif product_types == set(['service']):
        concept = '2'
    elif product_types == set(['consu', 'service']):
        concept = '3'
    else:
        raise Warning(
            _('Cant compute AFIP concept from product types %s.') %
            product_types
        )
    return concept

class account_invoice(models.Model):
    """
    Argentine invoice functions.
    """
    _name = "account.invoice"
    _inherit = "account.invoice"

    @api.depends('invoice_line.product_id.type')
    def _get_concept(self):
        """
        Compute concept type from selected products in invoice.
        """
        concept_obj = self.env['afip.concept_type']

        for inv in self:
            product_types = set([
                line.product_id.type for line in inv.invoice_line
            ])
            if False in product_types:
                raise Warning("Products %s has not defined type" % ','.join(
                    '%s [%s]' % (line.product_id.name or 'No name',
                                 line.invoice_id.name)
                    for line in inv.invoice_line
                    if line.product_id.type is False
                ))
            inv.afip_concept = concept_obj.get_code(product_types)

    def _get_service_begin_date(self):
        today = date.today()
        first = date(day=1, month=today.month, year=today.year)
        prev_last_day = first - timedelta(days=1)
        period = self.period_id.find(prev_last_day)
        return period and period.date_start or False

    def _get_service_end_date(self):
        today = date.today()
        first = date(day=1, month=today.month, year=today.year)
        prev_last_day = first - timedelta(days=1)
        period = self.period_id.find(prev_last_day)
        return period and prev_last_day or False

    afip_concept = fields.Selection(
        [('1', 'Consumible'), ('2', 'Service'), ('3', 'Mixted')],
        compute="_get_concept",
        store=False,
        help="AFIP invoice concept.")
    afip_service_start = fields.Date(
        'Service Start Date', default=_get_service_begin_date)
    afip_service_end = fields.Date(
        'Service End Date', default=_get_service_end_date)

    def afip_validation(self):
        """
        Check basic AFIP request to generate invoices.
        """
        for invoice in self:
            # If parter is not in Argentina, ignore it.
            if invoice.company_id.partner_id.country_id.name != 'Argentina':
                continue

            # Check if you choose the right journal.
            if invoice.type == 'out_invoice' and \
                    invoice.journal_id.journal_class_id.afip_code not in\
                    [1, 6, 11, 51, 19, 2, 7, 12, 52, 20]:
                raise except_orm(
                    _('Wrong Journal'),
                    _('Out invoice journal must have a valid journal class.'))
            if invoice.type == 'out_refund' and \
                    invoice.journal_id.journal_class_id.afip_code not in\
                    [3, 8, 13, 53, 21]:
                raise except_orm(
                    _('Wrong Journal'),
                    _('Out invoice journal must have a valid journal class.'))

            # Partner responsability ?
            partner = invoice.partner_id
            if not partner.responsability_id:
                raise except_orm(
                    _('No responsability'),
                    _('Your partner have not afip responsability assigned.'
                      ' Assign one please.'))

            # Take responsability classes for this journal
            invoice_class = \
                invoice.journal_id.journal_class_id.document_class_id
            company = invoice.journal_id.company_id.partner_id
            resp_class = \
                self.env['afip.responsability_relation'].search(
                    [('document_class_id', '=', invoice_class.id),
                     ('issuer_id.code', '=', company.responsability_id.code)])

            # You can emmit this document?
            if not resp_class:
                raise except_orm(
                    _('Invalid emisor'),
                    _('Your responsability with AFIP dont let you generate'
                      ' this kind of document.'))

            # Partner can receive this document?
            resp_class = \
                self.env['afip.responsability_relation'].search([
                    ('document_class_id', '=', invoice_class.id),
                    ('receptor_id.code', '=', partner.responsability_id.code)
                ])
            if not resp_class:
                raise Warning(
                    _('Invalid receptor\n'
                      'Your partner (%s) can\'t receive this document (%s).'
                      ' Check AFIP responsability of the partner,'
                      ' or Journal Account of the invoice.') %
                    (partner.responsability_id.name, invoice_class.name))

            # If Final Consumer have pay more than 1000$,
            # you need more information to generate document.
            if partner.responsability_id.code == 'CF' \
                    and invoice.amount_total > 1000 and \
                    (partner.document_type_id.code in [None, 'Sigd']
                     or invoice.partner_id.document_number is None):
                raise except_orm(_('Partner without Identification for total'
                                   ' invoices > $1000.-'),
                                 _('You must define valid document type and'
                                   ' number for this Final Consumer.'))
        return True

    def compute_all(self, cr, uid, ids, line_filter=lambda line: True,
                    tax_filter=lambda tax: True, context=None):
        res = {}
        for inv in self.browse(cr, uid, ids, context=context):
            amounts = []
            for line in inv.invoice_line:
                if line_filter(line):
                    amounts.append(line.compute_all(tax_filter=tax_filter,
                                                    context=context))

            s = {
                'amount_total': 0,
                'amount_tax': 0,
                'amount_untaxed': 0,
                'taxes': []
            }
            for amount in amounts:
                for key, value in amount.items():
                    s[key] = s.get(key, 0) + value

            res[inv.id] = s

        return res.get(len(ids) == 1 and ids[0], res)

    @api.multi
    @api.onchange('partner_id', 'company_id')
    def _onchange_partner_id(self):
        # Set list of valid journals by partner responsability
        # partner_obj = self.pool.get('res.partner')
        partner = self.partner_id
        company = self.company_id
        responsability = partner.responsability_id
        result = {}

        if not responsability:
            msg = {
                'title': _('The partner has not set any fiscal responsability'),
                'message': _('Please, set partner fiscal responsability in the'
                             ' partner form before continuing.')
            }
            return {'warning', msg}

        if responsability.issuer_relation_ids is None:
            return {}

        if not company.partner_id.responsability_id.id:
            msg = {
                'title': _('Your company has not set any fiscal'
                           ' responsability'),
                'message': _('Please, set your company responsability in the'
                             ' company form before continuing.')
            }
            return {'warning', msg}

        accepted_journal_ids = self.partner_id.prefered_journals(
            self.company_id.id, self.type)

        if accepted_journal_ids:
            result['domain'].update({
                'journal_id': [('id', 'in', accepted_journal_ids)],
            })
            self.journal_id = accepted_journal_ids[0]
        else:
            result['domain'].update({
                'journal_id': [('id', 'in', [])],
            })
            self.journal_id = False

        return result

account_invoice()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before># No shebang line, this module is meant to be imported
#
# Copyright 2013 Oliver Palmer
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Information about the operating system including type, filesystem information,
and other relevant information.  This module may also contain os specific
information such as the Linux distribution, Windows version, bitness, etc.
"""

import os
import time
import tempfile

import psutil
from pyfarm.ext.config.enum import OperatingSystem as OperatingSystemEnum

class OperatingSystemInfo(object):
    """
    .. note::
        This class has already been instanced onto
        `pyfarm.system.operating_system`

    Namespace class which returns information about
    the current operating system such as case-sensitivity, type, etc.

    :attr OS:
        Integer containing the os type, this is a mapping to a value
        on :class:`OperatingSystem`

    :attr IS_LINUX:
        set to True if running linux

    :attr IS_WINDOWS:
        set to True if running windows

    :attr IS_MAC:
        set to True if running mac os

    :attr IS_OTHER:
        set to True if running something we could not determine a mapping for

    :attr IS_POSIX:
        set to True if running a posix platform (such as linux or mac)

    :attr CASE_SENSITIVE:
        set to True if the filesystem is case sensitive
    """
    _enum = OperatingSystemEnum()
    OS = _enum.get()
    IS_LINUX = OS == _enum.LINUX
    IS_WINDOWS = OS == _enum.WINDOWS
    IS_MAC = OS == _enum.MAC
    IS_OTHER = OS == _enum.OTHER
    IS_POSIX = OS in (_enum.LINUX, _enum.MAC)
    CASE_SENSITIVE = None

    def __init__(self):
        if self.__class__.CASE_SENSITIVE is None:
            fid, path = tempfile.mkstemp()
            exists = map(os.path.isfile, [path, path.lower(), path.upper()])
            if not any(exists):
                raise ValueError(
                    "failed to determine if path was case sensitive")
            elif all(exists):
                self.__class__.CASE_SENSITIVE = False

            elif exists.count(True) == 1:
                self.__class__.CASE_SENSITIVE = True

            try:
                os.remove(path)
            except:
                pass

    def uptime(self):
        """
        Returns the amount of time the system has been running in
        seconds
        """
        return time.time() - psutil.BOOT_TIME<commit_msg>fixing underlying logic<commit_after># No shebang line, this module is meant to be imported
#
# Copyright 2013 Oliver Palmer
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Information about the operating system including type, filesystem information,
and other relevant information.  This module may also contain os specific
information such as the Linux distribution, Windows version, bitness, etc.
"""

import os
import time
import tempfile

import psutil
from pyfarm.core.enums import OS, OperatingSystem

class OperatingSystemInfo(object):
    """
    .. note::
        This class has already been instanced onto
        `pyfarm.system.operating_system`

    Namespace class which returns information about
    the current operating system such as case-sensitivity, type, etc.

    :attr OS:
        Integer containing the os type, this is a mapping to a value
        on :class:`OperatingSystem`

    :attr IS_LINUX:
        set to True if running linux

    :attr IS_WINDOWS:
        set to True if running windows

    :attr IS_MAC:
        set to True if running mac os

    :attr IS_OTHER:
        set to True if running something we could not determine a mapping for

    :attr IS_POSIX:
        set to True if running a posix platform (such as linux or mac)

    :attr CASE_SENSITIVE:
        set to True if the filesystem is case sensitive
    """
    OS = OS
    IS_LINUX = OS == OperatingSystem.LINUX
    IS_WINDOWS = OS == OperatingSystem.WINDOWS
    IS_MAC = OS == OperatingSystem.MAC
    IS_OTHER = OS == OperatingSystem.OTHER
    IS_POSIX = OS in (OperatingSystem.LINUX, OperatingSystem.MAC)
    CASE_SENSITIVE = None

    def __init__(self):
        if self.__class__.CASE_SENSITIVE is None:
            fid, path = tempfile.mkstemp()
            exists = map(os.path.isfile, [path, path.lower(), path.upper()])
            if not any(exists):
                raise ValueError(
                    "failed to determine if path was case sensitive")
            elif all(exists):
                self.__class__.CASE_SENSITIVE = False

            elif exists.count(True) == 1:
                self.__class__.CASE_SENSITIVE = True

            try:
                os.remove(path)
            except:
                pass

    def uptime(self):
        """
        Returns the amount of time the system has been running in
        seconds
        """
        return time.time() - psutil.BOOT_TIME<|endoftext|>


<commit_before>from flask import *
from sh import media
from os import urandom
from conf import *
from time import sleep

app = Flask(__name__)
app.secret_key = urandom(255)

media_codes = [0,2,4,12,13]

@app.route('/')
def main():
	return redirect(url_for('controls'))

@app.route('/controls', methods=['GET', 'POST'])
@app.route('/controls/<control>', methods=['GET', 'POST'])
def controls(control=None):
	if request.method == 'GET':
		if control:
			media(control)
			sleep(1)
			return redirect(url_for('controls'))
		else:
			return render_template('controls.html', now_playing=nowPlaying())
	elif request.method == 'POST':
		cont = request.form['control']
		return redirect(url_for('controls', control=cont))

def nowPlaying():
	isPlaying = str(media('isPlaying', _ok_code=media_codes))[0]
	isPaused = str(media('isPaused', _ok_code=media_codes))[0]
	artist = str(media('artist', _ok_code=media_codes))
	track = str(media('title', _ok_code=media_codes))
	if track == '(null)' and artist == '(null)':
		stopped = True
	if isPlaying == '1':
		playing = track +'- '+ artist
	elif isPaused == '1' and not stopped:
		playing = Markup(track +'- '+ artist + '[paused]')
	else:
		playing = 'No music playing!'
	return playing

app.run(debug=DEBUG, host=HOST)
<commit_msg>fixed variable assigment<commit_after>from flask import *
from sh import media
from os import urandom
from conf import *
from time import sleep

app = Flask(__name__)
app.secret_key = urandom(255)

media_codes = [0,2,4,12,13]

@app.route('/')
def main():
	return redirect(url_for('controls'))

@app.route('/controls', methods=['GET', 'POST'])
@app.route('/controls/<control>', methods=['GET', 'POST'])
def controls(control=None):
	if request.method == 'GET':
		if control:
			media(control)
			sleep(1)
			return redirect(url_for('controls'))
		else:
			return render_template('controls.html', now_playing=nowPlaying())
	elif request.method == 'POST':
		cont = request.form['control']
		return redirect(url_for('controls', control=cont))

def nowPlaying():
	isPlaying = str(media('isPlaying', _ok_code=media_codes))[0]
	isPaused = str(media('isPaused', _ok_code=media_codes))[0]
	artist = str(media('artist', _ok_code=media_codes))
	track = str(media('title', _ok_code=media_codes))
	stopped = False
	if track == '(null)' and artist == '(null)':
		stopped = True
	if isPlaying == '1':
		playing = track +'- '+ artist
	elif isPaused == '1' and not stopped:
		playing = Markup(track +'- '+ artist + '[paused]')
	else:
		playing = 'No music playing!'
	return playing

app.run(debug=DEBUG, host=HOST)
<|endoftext|>


<commit_before>from django.contrib.sites.models import Site
from django.template import loader, RequestContext
from django.http import HttpResponse
from django.core.urlresolvers import reverse, NoReverseMatch
from django.conf import settings

from robots.models import Rule

CRAWL_DELAY = getattr(settings, 'ROBOTS_CRAWL_DELAY', False)
USE_SITEMAP = getattr(settings, 'ROBOTS_USE_SITEMAP', True)

def rules_list(request, template_name='robots/rule_list.html',
        mimetype='text/plain', status_code=200):
    """
    Returns a generated robots.txt file with correct mimetype (text/plain),
    status code (200 or 404), sitemap url (automatically) and crawl delay
    (if settings.ROBOTS_CRAWL_DELAY is given).
    """
    scheme = request.is_secure() and 'https' or 'http'
    current_site = Site.objects.get_current()
    try:
        sitemap_url = reverse('django.contrib.sitemaps.views.index')
    except NoReverseMatch:
        try:
            sitemap_url = reverse('django.contrib.sitemaps.views.sitemap')
        except NoReverseMatch:
            sitemap_url = None
    if sitemap_url is not None and USE_SITEMAP:
        sitemap_url = "%s://%s%s" % (scheme, current_site.domain, sitemap_url)
    rules = Rule.objects.filter(sites=current_site)
    if not rules.count():
        status_code = 404
    t = loader.get_template(template_name)
    c = RequestContext(request, {
        'rules': rules,
        'sitemap_url': sitemap_url,
        'crawl_delay': CRAWL_DELAY,
    })
    return HttpResponse(t.render(c), status=status_code, mimetype=mimetype)
<commit_msg>removes legacy crawl delay support that is now superceeded by the rule crawldelay<commit_after>from django.contrib.sites.models import Site
from django.template import loader, RequestContext
from django.http import HttpResponse
from django.core.urlresolvers import reverse, NoReverseMatch
from django.conf import settings

from robots.models import Rule

USE_SITEMAP = getattr(settings, 'ROBOTS_USE_SITEMAP', True)

def rules_list(request, template_name='robots/rule_list.html',
        mimetype='text/plain', status_code=200):
    """
    Returns a generated robots.txt file with correct mimetype (text/plain),
    status code (200 or 404), sitemap url (automatically).
    """
    scheme = request.is_secure() and 'https' or 'http'
    current_site = Site.objects.get_current()
    try:
        sitemap_url = reverse('django.contrib.sitemaps.views.index')
    except NoReverseMatch:
        try:
            sitemap_url = reverse('django.contrib.sitemaps.views.sitemap')
        except NoReverseMatch:
            sitemap_url = None
    if sitemap_url is not None and USE_SITEMAP:
        sitemap_url = "%s://%s%s" % (scheme, current_site.domain, sitemap_url)
    rules = Rule.objects.filter(sites=current_site)
    if not rules.count():
        status_code = 404
    t = loader.get_template(template_name)
    c = RequestContext(request, {
        'rules': rules,
        'sitemap_url': sitemap_url,
    })
    return HttpResponse(t.render(c), status=status_code, mimetype=mimetype)
<|endoftext|>


<commit_before>from __future__ import print_function, unicode_literals

import json
import os
import os.path as path
import shutil
import subprocess
import sys
import tarfile
from time import time
import urllib

from mach.registrar import Registrar
from mach.decorators import (
    CommandArgument,
    CommandProvider,
    Command,
)

from servo.command_base import CommandBase, cd

@CommandProvider
class MachCommands(CommandBase):
    @Command('build',
             description='Build Servo',
             category='build')
    @CommandArgument('--target', '-t',
                     default=None,
                     help='Cross compile for given target platform')
    @CommandArgument('--release', '-r',
                     action='store_true',
                     help='Build in release mode')
    @CommandArgument('--jobs', '-j',
                     default=None,
                     help='Number of jobs to run in parallel')
    def build(self, target, release=False, jobs=None):
        self.ensure_bootstrapped()

        opts = []
        if release:
            opts += ["--release"]
        if target:
            opts += ["--target", target]
        if jobs is not None:
            opts += ["-j", jobs]

        build_start = time()
        subprocess.check_call(["cargo", "build"] + opts, env=self.build_env())
        elapsed = time() - build_start

        print("Build completed in %0.2fs" % elapsed)

    @Command('build-cef',
             description='Build the Chromium Embedding Framework library',
             category='build')
    @CommandArgument('--jobs', '-j',
                     default=None,
                     help='Number of jobs to run in parallel')
    def build_cef(self, jobs=None):
        self.ensure_bootstrapped()

        ret = None
        opts = []
        if jobs is not None:
            opts += ["-j", jobs]

        build_start = time()
        with cd(path.join("ports", "cef")):
            ret = subprocess.call(["cargo", "build"], env=self.build_env())
        elapsed = time() - build_start

        print("CEF build completed in %0.2fs" % elapsed)

        return ret

    @Command('build-tests',
             description='Build the Servo test suites',
             category='build')
    @CommandArgument('--jobs', '-j',
                     default=None,
                     help='Number of jobs to run in parallel')
    def build_tests(self, jobs=None):
        self.ensure_bootstrapped()
        opts = []
        if jobs is not None:
            opts += ["-j", jobs]
        subprocess.check_call(["cargo", "test", "--no-run"], env=self.build_env())
<commit_msg>Add -v or --verbose to mach build<commit_after>from __future__ import print_function, unicode_literals

import json
import os
import os.path as path
import shutil
import subprocess
import sys
import tarfile
from time import time
import urllib

from mach.registrar import Registrar
from mach.decorators import (
    CommandArgument,
    CommandProvider,
    Command,
)

from servo.command_base import CommandBase, cd

@CommandProvider
class MachCommands(CommandBase):
    @Command('build',
             description='Build Servo',
             category='build')
    @CommandArgument('--target', '-t',
                     default=None,
                     help='Cross compile for given target platform')
    @CommandArgument('--release', '-r',
                     action='store_true',
                     help='Build in release mode')
    @CommandArgument('--jobs', '-j',
                     default=None,
                     help='Number of jobs to run in parallel')
    @CommandArgument('--verbose', '-v',
                     action='store_true',
                     help='Print verbose output')
    def build(self, target, release=False, jobs=None, verbose=False):
        self.ensure_bootstrapped()

        opts = []
        if release:
            opts += ["--release"]
        if target:
            opts += ["--target", target]
        if jobs is not None:
            opts += ["-j", jobs]
        if verbose:
            opts += ["-v"]

        build_start = time()
        subprocess.check_call(["cargo", "build"] + opts, env=self.build_env())
        elapsed = time() - build_start

        print("Build completed in %0.2fs" % elapsed)

    @Command('build-cef',
             description='Build the Chromium Embedding Framework library',
             category='build')
    @CommandArgument('--jobs', '-j',
                     default=None,
                     help='Number of jobs to run in parallel')
    def build_cef(self, jobs=None):
        self.ensure_bootstrapped()

        ret = None
        opts = []
        if jobs is not None:
            opts += ["-j", jobs]

        build_start = time()
        with cd(path.join("ports", "cef")):
            ret = subprocess.call(["cargo", "build"], env=self.build_env())
        elapsed = time() - build_start

        print("CEF build completed in %0.2fs" % elapsed)

        return ret

    @Command('build-tests',
             description='Build the Servo test suites',
             category='build')
    @CommandArgument('--jobs', '-j',
                     default=None,
                     help='Number of jobs to run in parallel')
    def build_tests(self, jobs=None):
        self.ensure_bootstrapped()
        opts = []
        if jobs is not None:
            opts += ["-j", jobs]
        subprocess.check_call(["cargo", "test", "--no-run"], env=self.build_env())
<|endoftext|>