<commit_before>##############################################################################
#
#    Copyright 2013 Camptocamp
#    Copyright 2009-2013 Akretion,
#    Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau,
#            Benoît Guillot, Joel Grand-Guillaume
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models, _, exceptions, api
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
import time

#TODO: revisar este wizard al migrar crm_claim_rma_custom
class ClaimMakePicking(models.TransientModel):

    _name = "claim_make_picking.wizard"
    _description = 'Wizard to create pickings from claim lines'

    # Get default destination location
    @api.model
    def _get_dest_loc(self):
        """Return the location_id to use as destination.
        If it's an outoing shippment: take the customer stock property
        If it's an incoming shippment take the location_dest_id common to all
        lines, or if different, return None."""
        context = self.env.context
        loc_id = False
        if context.get('picking_type') == 'out':
            partner = self.env['res.partner'].browse(context.get('partner_id'))
            if context.get('type') == 'supplier':
                loc_id = partner.property_stock_supplier[0]
            elif context.get('type') == 'customer':
                loc_id = partner.property_stock_customer[0]
        elif context.get('picking_type') == 'in':
            # Add the case of return to supplier !
            line_ids = self._get_claim_lines()
            loc_id = self._get_common_dest_location_from_line(line_ids)
        return loc_id

    @api.model
    def _get_claim_lines(self):
        # TODO use custom states to show buttons of this wizard or not instead
        # of raise an error
        context = self.env.context
        line_obj = self.env['claim.line']
        if context.get('picking_type') == 'out':
            move_field = 'move_out_customer_id'
        else:
            move_field = 'move_in_customer_id'
        good_lines = []
        line_ids = line_obj.search([('claim_id', '=', context['active_id'])])
        for line in line_ids:
            if not line[move_field] or line[move_field].state == 'cancel':
                good_lines.append(line.id)
        if not good_lines:
            raise exceptions.UserError(
                _('A picking has already been created for this claim.'))
        return good_lines

    # Get default source location
    def _get_source_loc(self):
        loc_id = False
        context = self.env.context
        if context.get('picking_type') == 'out':
            warehouse = self.env['stock.warehouse'].browse(context.get('warehouse_id'))
            if context.get('type') == 'supplier':
                loc_id = warehouse.lot_breakdown_id[0]
            if context.get('type') == 'customer':
                loc_id = warehouse.lot_rma_id[0]

        elif context.get('picking_type') == 'in':
            partner = self.env['res.partner'].browse(context.get('partner_id'))
            if context.get('type') == 'supplier':
                loc_id = partner.property_stock_supplier[0]

            if context.get('type') == 'customer':
                loc_id = partner.property_stock_customer[0]
        return loc_id

    claim_line_source_location = fields.Many2one(
            'stock.location',
            string='Source Location',
            help="Location where the returned products are from.",
            required=True, default=_get_source_loc)
    claim_line_dest_location = fields.Many2one(
            'stock.location',
            string='Dest. Location',
            help="Location where the system will stock the returned products.",
            required=True, default=_get_dest_loc)
    claim_line_ids = fields.Many2many(
            'claim.line',
            'claim_line_picking',
            'claim_picking_id',
            'claim_line_id',
            string='Claim lines', default=_get_claim_lines)

    def _get_common_dest_location_from_line(self, line_ids):
        """Return the ID of the common location between all lines. If no common
        destination was  found, return False"""
        loc_id = False
        line_obj = self.env['claim.line']
        line_location = []
        for line in line_obj.browse(line_ids):
            if line.location_dest_id.id not in line_location:
                line_location.append(line.location_dest_id.id)
        if len(line_location) == 1:
            loc_id = line_location[0]
        return loc_id

    def _get_common_partner_from_line(self, line_ids):
        """Return the ID of the common partner between all lines. If no common
        partner was found, return False"""
        partner_id = False
        line_obj = self.env['claim.line']
        line_partner = []
        for line in line_obj.browse(line_ids):
            if (line.warranty_return_partner
                    and line.warranty_return_partner.id
                    not in line_partner):
                line_partner.append(line.warranty_return_partner.id)
        if len(line_partner) == 1:
            partner_id = line_partner[0]
        return partner_id

    @api.model
    def action_cancel(self):
        return {'type': 'ir.actions.act_window_close'}

    @api.multi
    def create_move(self, claim_line, p_type, picking_id, claim, note, write_field):
        reserv_obj = self.env['stock.reservation']
        type_ids = self.env['stock.picking.type'].search([('code', '=', p_type)])
        partner_id = claim.delivery_address_id
        move_obj = self.env['stock.move']
        product = claim_line.product_id
        if self.env.context.get('picking_type', 'in') == u'out' and \
                claim_line.equivalent_product_id:
            product = claim_line.equivalent_product_id
        qty = claim_line.product_returned_quantity

        move_id = move_obj.create(
            {'name': claim_line.product_id.name,
             'priority': '0',
             'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
             'date_expected': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
             'product_id': product.id,
             'picking_type_id': type_ids and type_ids[0].id,
             'product_uom_qty': claim_line.product_returned_quantity,
             'product_uom': claim_line.product_id.uom_id.id,
             'partner_id': partner_id.id,
             'picking_id': picking_id.id,
             'state': 'draft',
             'price_unit': claim_line.unit_sale_price,
             'company_id': claim.company_id.id,
             'location_id': self.claim_line_source_location.id,
             'location_dest_id': self.claim_line_dest_location.id,
             'note': note,
             'claim_line_id': claim_line.id
             })
        if p_type == 'outgoing' and claim_line.product_id.type == 'product':
            reserv_vals = {
                'product_id': product.id,
                'product_uom': claim_line.product_id.uom_id.id,
                'product_uom_qty': claim_line.product_returned_quantity,
                'date_validity': False,
                'name': u"{} ({})".format(claim_line.claim_id.number, claim_line.product_id.name_template),
                'location_id': self.claim_line_source_location.id,
                'location_dest_id': self.claim_line_dest_location.id,
                'move_id': move_id,
                'claim_id': claim_line.claim_id.id,
            }
            reserve = reserv_obj.create(reserv_vals)
            reserv_obj.reserve([reserve])
        claim_line.write({write_field: move_id.id})

    # If "Create" button pressed
    def action_create_picking(self):
        picking_obj = self.env['stock.picking']
        claim_obj = self.env['crm.claim']
        view_obj = self.env['ir.ui.view']
        name = 'RMA picking out'
        context = self.env.context
        if context.get('picking_type') == 'out':
            p_type = 'outgoing'
            write_field = 'move_out_customer_id'
            note = 'RMA picking out'
            view_xml_id = 'stock_picking_form'
        else:
            p_type = 'incoming'
            write_field = 'move_in_customer_id'
            if context.get('picking_type'):
                note = 'RMA picking ' + str(context.get('picking_type'))
                name = note
        model = 'stock.picking'
        view_id = view_obj.search([('model', '=', model),
                                   ('type', '=', 'form'),
                                   ])[0]
        claim = claim_obj.browse(context['active_id'])
        rma_cost = claim.rma_cost
        partner_id = claim.delivery_address_id
        line_ids = [x.id for x in self.claim_line_ids]
        # In case of product return, we don't allow one picking for various
        # product if location are different
        # or if partner address is different
        if context.get('product_return'):
            common_dest_loc_id = self._get_common_dest_location_from_line(line_ids)
            self.env['claim.line'].browse(line_ids).auto_set_warranty()
            common_dest_partner_id = self._get_common_partner_from_line(line_ids)
        # create picking
        type_ids = self.env['stock.picking.type'].search([('code', '=', p_type)])
        picking_id = picking_obj.create(
            {'origin': claim.number,
             'picking_type_id': type_ids and type_ids[0].id,
             'move_type': 'one',  # direct
             'state': 'draft',
             'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
             'partner_id': partner_id.id,
             'invoice_state': "none",
             'company_id': claim.company_id.id,
             'location_id': self.claim_line_source_location.id,
             'location_dest_id': self.claim_line_dest_location.id,
             'note': note,
             'claim_id': claim.id,
             })
        # Create picking lines
        for wizard_claim_line in self.claim_line_ids:
            self.create_move(wizard_claim_line, p_type, picking_id, claim, note, write_field)

        #TODO: Migrar
        # ~ wf_service = netsvc.LocalService("workflow")
        # ~ if picking_id:
            # ~ wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
            #picking_obj.action_assign(cr, uid, [picking_id])
        if picking_id:
            domain = ("[('picking_type_code', '=', '%s'), \
                       ('partner_id', '=', %s)]" %
                      (p_type, partner_id.id))

            return {
                'name': '%s' % name,
                'view_type': 'form',
                'view_mode': 'form',
                'view_id': view_id.id,
                'domain': domain,
                'res_model': model,
                'res_id': picking_id.id,
                'type': 'ir.actions.act_window',
            }
        else:
            return {'type': 'ir.actions.act_window_close'}
<commit_msg>[FIX]'crm_claim_rma': eliminada selección innecesaria<commit_after>##############################################################################
#
#    Copyright 2013 Camptocamp
#    Copyright 2009-2013 Akretion,
#    Author: Emmanuel Samyn, Raphaël Valyi, Sébastien Beau,
#            Benoît Guillot, Joel Grand-Guillaume
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models, _, exceptions, api
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
import time

#TODO: revisar este wizard al migrar crm_claim_rma_custom
class ClaimMakePicking(models.TransientModel):

    _name = "claim_make_picking.wizard"
    _description = 'Wizard to create pickings from claim lines'

    # Get default destination location
    @api.model
    def _get_dest_loc(self):
        """Return the location_id to use as destination.
        If it's an outoing shippment: take the customer stock property
        If it's an incoming shippment take the location_dest_id common to all
        lines, or if different, return None."""
        context = self.env.context
        loc_id = False
        if context.get('picking_type') == 'out':
            partner = self.env['res.partner'].browse(context.get('partner_id'))
            if context.get('type') == 'supplier':
                loc_id = partner.property_stock_supplier
            elif context.get('type') == 'customer':
                loc_id = partner.property_stock_customer
        elif context.get('picking_type') == 'in':
            # Add the case of return to supplier !
            line_ids = self._get_claim_lines()
            loc_id = self._get_common_dest_location_from_line(line_ids)
        return loc_id

    @api.model
    def _get_claim_lines(self):
        # TODO use custom states to show buttons of this wizard or not instead
        # of raise an error
        context = self.env.context
        line_obj = self.env['claim.line']
        if context.get('picking_type') == 'out':
            move_field = 'move_out_customer_id'
        else:
            move_field = 'move_in_customer_id'
        good_lines = []
        line_ids = line_obj.search([('claim_id', '=', context['active_id'])])
        for line in line_ids:
            if not line[move_field] or line[move_field].state == 'cancel':
                good_lines.append(line.id)
        if not good_lines:
            raise exceptions.UserError(
                _('A picking has already been created for this claim.'))
        return good_lines

    # Get default source location
    def _get_source_loc(self):
        loc_id = False
        context = self.env.context
        if context.get('picking_type') == 'out':
            warehouse = self.env['stock.warehouse'].browse(context.get('warehouse_id'))
            if context.get('type') == 'supplier':
                loc_id = warehouse.lot_breakdown_id
            if context.get('type') == 'customer':
                loc_id = warehouse.lot_rma_id

        elif context.get('picking_type') == 'in':
            partner = self.env['res.partner'].browse(context.get('partner_id'))
            if context.get('type') == 'supplier':
                loc_id = partner.property_stock_supplier

            if context.get('type') == 'customer':
                loc_id = partner.property_stock_customer
        return loc_id

    claim_line_source_location = fields.Many2one(
            'stock.location',
            string='Source Location',
            help="Location where the returned products are from.",
            required=True, default=_get_source_loc)
    claim_line_dest_location = fields.Many2one(
            'stock.location',
            string='Dest. Location',
            help="Location where the system will stock the returned products.",
            required=True, default=_get_dest_loc)
    claim_line_ids = fields.Many2many(
            'claim.line',
            'claim_line_picking',
            'claim_picking_id',
            'claim_line_id',
            string='Claim lines', default=_get_claim_lines)

    def _get_common_dest_location_from_line(self, line_ids):
        """Return the ID of the common location between all lines. If no common
        destination was  found, return False"""
        loc_id = False
        line_obj = self.env['claim.line']
        line_location = []
        for line in line_obj.browse(line_ids):
            if line.location_dest_id.id not in line_location:
                line_location.append(line.location_dest_id.id)
        if len(line_location) == 1:
            loc_id = line_location
        return loc_id

    def _get_common_partner_from_line(self, line_ids):
        """Return the ID of the common partner between all lines. If no common
        partner was found, return False"""
        partner_id = False
        line_obj = self.env['claim.line']
        line_partner = []
        for line in line_obj.browse(line_ids):
            if (line.warranty_return_partner
                    and line.warranty_return_partner.id
                    not in line_partner):
                line_partner.append(line.warranty_return_partner.id)
        if len(line_partner) == 1:
            partner_id = line_partner[0]
        return partner_id

    @api.model
    def action_cancel(self):
        return {'type': 'ir.actions.act_window_close'}

    @api.multi
    def create_move(self, claim_line, p_type, picking_id, claim, note, write_field):
        reserv_obj = self.env['stock.reservation']
        type_ids = self.env['stock.picking.type'].search([('code', '=', p_type)])
        partner_id = claim.delivery_address_id
        move_obj = self.env['stock.move']
        product = claim_line.product_id
        if self.env.context.get('picking_type', 'in') == u'out' and \
                claim_line.equivalent_product_id:
            product = claim_line.equivalent_product_id
        qty = claim_line.product_returned_quantity

        move_id = move_obj.create(
            {'name': claim_line.product_id.name,
             'priority': '0',
             'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
             'date_expected': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
             'product_id': product.id,
             'picking_type_id': type_ids and type_ids[0].id,
             'product_uom_qty': claim_line.product_returned_quantity,
             'product_uom': claim_line.product_id.uom_id.id,
             'partner_id': partner_id.id,
             'picking_id': picking_id.id,
             'state': 'draft',
             'price_unit': claim_line.unit_sale_price,
             'company_id': claim.company_id.id,
             'location_id': self.claim_line_source_location.id,
             'location_dest_id': self.claim_line_dest_location.id,
             'note': note,
             'claim_line_id': claim_line.id
             })
        if p_type == 'outgoing' and claim_line.product_id.type == 'product':
            reserv_vals = {
                'product_id': product.id,
                'product_uom': claim_line.product_id.uom_id.id,
                'product_uom_qty': claim_line.product_returned_quantity,
                'date_validity': False,
                'name': u"{} ({})".format(claim_line.claim_id.number, claim_line.product_id.name_template),
                'location_id': self.claim_line_source_location.id,
                'location_dest_id': self.claim_line_dest_location.id,
                'move_id': move_id,
                'claim_id': claim_line.claim_id.id,
            }
            reserve = reserv_obj.create(reserv_vals)
            reserv_obj.reserve([reserve])
        claim_line.write({write_field: move_id.id})

    # If "Create" button pressed
    def action_create_picking(self):
        picking_obj = self.env['stock.picking']
        claim_obj = self.env['crm.claim']
        view_obj = self.env['ir.ui.view']
        name = 'RMA picking out'
        context = self.env.context
        if context.get('picking_type') == 'out':
            p_type = 'outgoing'
            write_field = 'move_out_customer_id'
            note = 'RMA picking out'
            view_xml_id = 'stock_picking_form'
        else:
            p_type = 'incoming'
            write_field = 'move_in_customer_id'
            if context.get('picking_type'):
                note = 'RMA picking ' + str(context.get('picking_type'))
                name = note
        model = 'stock.picking'
        view_id = view_obj.search([('model', '=', model),
                                   ('type', '=', 'form'),
                                   ])[0]
        claim = claim_obj.browse(context['active_id'])
        rma_cost = claim.rma_cost
        partner_id = claim.delivery_address_id
        line_ids = [x.id for x in self.claim_line_ids]
        # In case of product return, we don't allow one picking for various
        # product if location are different
        # or if partner address is different
        if context.get('product_return'):
            common_dest_loc_id = self._get_common_dest_location_from_line(line_ids)
            self.env['claim.line'].browse(line_ids).auto_set_warranty()
            common_dest_partner_id = self._get_common_partner_from_line(line_ids)
        # create picking
        type_ids = self.env['stock.picking.type'].search([('code', '=', p_type)])
        picking_id = picking_obj.create(
            {'origin': claim.number,
             'picking_type_id': type_ids and type_ids[0].id,
             'move_type': 'one',  # direct
             'state': 'draft',
             'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
             'partner_id': partner_id.id,
             'invoice_state': "none",
             'company_id': claim.company_id.id,
             'location_id': self.claim_line_source_location.id,
             'location_dest_id': self.claim_line_dest_location.id,
             'note': note,
             'claim_id': claim.id,
             })
        # Create picking lines
        for wizard_claim_line in self.claim_line_ids:
            self.create_move(wizard_claim_line, p_type, picking_id, claim, note, write_field)

        #TODO: Migrar
        # ~ wf_service = netsvc.LocalService("workflow")
        # ~ if picking_id:
            # ~ wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
            #picking_obj.action_assign(cr, uid, [picking_id])
        if picking_id:
            domain = ("[('picking_type_code', '=', '%s'), \
                       ('partner_id', '=', %s)]" %
                      (p_type, partner_id.id))

            return {
                'name': '%s' % name,
                'view_type': 'form',
                'view_mode': 'form',
                'view_id': view_id.id,
                'domain': domain,
                'res_model': model,
                'res_id': picking_id.id,
                'type': 'ir.actions.act_window',
            }
        else:
            return {'type': 'ir.actions.act_window_close'}
<|endoftext|>


<commit_before>import socket
import messages
import struct
import logging
import binascii

log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

def chunks(s, size=1):
    for i in range(0, len(s), size):
        yield s[i:i + size]

def hex_print(s, size=1):
    return b':'.join(binascii.hexlify(c).upper() for c in chunks(s, size))

class Connection(object):
    """Represents a connection to a icecream scheduler."""
    CHUNK_SIZE = 2048

    def __init__(self, host, port=8765):
        self.socket = None
        self.server_host = host
        self.server_port = port
        self.input_buf = b''
        self.connect()

    def connect(self):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect((self.server_host, self.server_port))
        log.debug("Sending protocol version 22")
        self.socket.send(b'\x22\x00\x00\x00')
        log.debug("Receiving protocol version")
        assert(self.socket.recv(4) == b'\x22\x00\x00\x00')
        log.debug("Sending protocol version 22")
        self.socket.send(b'\x22\x00\x00\x00')
        log.debug("Receiving protocol version")
        assert(self.socket.recv(4) == b'\x22\x00\x00\x00')

    def send(self, s):
        log.debug("Sending:\n{0}".format(hex_print(s)))
        totalsent = 0
        while totalsent < len(s):
            sent = self.socket.send(s[totalsent:])
            if sent == 0:
                return
            totalsent += sent

    def send_message(self, msg):
        msg_string = msg.pack()
        self.send(struct.pack("!LL", len(msg_string), msg.msg_type) +
                  msg_string)

    def recv_chunk(self):
        msg = self.socket.recv(self.CHUNK_SIZE)
        self.input_buf += msg
        return len(msg)

    def receive(self, n):
        while len(self.input_buf) < n:
            self.recv_chunk()
        s, self.input_buf = self.input_buf[:n], self.input_buf[n:]
        log.debug("Received:\n{0}".format(hex_print(s)))
        return s

    def receive_until_null(self):
        i = 0
        while True:
            if i < len(self.input_buf) and self.input_buf[i] == '\x00':
                break

            i += 1
            if i >= len(self.input_buf):
                amount_read = 0
                while amount_read == 0:
                    amount_read = self.recv_chunk()
                    log.info("Read {0} bytes.".format(amount_read))

        s, self.input_buf = self.input_buf[:i+1], self.input_buf[i+1:]
        return s

    def get_message(self):
        length = struct.unpack("!L", self.receive(4))[0]

        log.debug("Receiving message of length {0}".format(length))

        msg = self.receive(length)

        return messages.unpack(msg)
<commit_msg>Add docstrings to connection.  Remove unused method.<commit_after>import socket
import messages
import struct
import logging
import binascii

log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

def chunks(s, size=1):
    for i in range(0, len(s), size):
        yield s[i:i + size]

def hex_print(s, size=1):
    return b':'.join(binascii.hexlify(c).upper() for c in chunks(s, size))

class Connection(object):
    """Represents a connection to a icecream scheduler."""

    CHUNK_SIZE = 2048

    def __init__(self, host, port=8765):
        self.socket = None
        self.server_host = host
        self.server_port = port
        self.input_buf = b''
        self.connect()

    def connect(self):
        """
        Open a connection to the scheduler.

        Also handles the initial procotol negociation. Currently badly.
        """
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect((self.server_host, self.server_port))
        log.debug("Sending protocol version 22")
        self.socket.send(b'\x22\x00\x00\x00')
        log.debug("Receiving protocol version")
        assert(self.socket.recv(4) == b'\x22\x00\x00\x00')
        log.debug("Sending protocol version 22")
        self.socket.send(b'\x22\x00\x00\x00')
        log.debug("Receiving protocol version")
        assert(self.socket.recv(4) == b'\x22\x00\x00\x00')

    def send(self, s):
        """Reliably sends the string s to the scheduler."""
        log.debug("Sending:\n{0}".format(hex_print(s)))
        totalsent = 0
        while totalsent < len(s):
            sent = self.socket.send(s[totalsent:])
            if sent == 0:
                return
            totalsent += sent

    def send_message(self, msg):
        """Packs and sends the given Message to the scheduler."""
        msg_string = msg.pack()
        self.send(struct.pack("!LL", len(msg_string), msg.msg_type) +
                  msg_string)

    def recv_chunk(self):
        """Receives self.CHUNK_SIZE bytes from the wire and buffers them."""
        msg = self.socket.recv(self.CHUNK_SIZE)
        self.input_buf += msg
        return len(msg)

    def receive(self, n):
        """Reliably receives n bytes from the wire."""
        while len(self.input_buf) < n:
            self.recv_chunk()
        s, self.input_buf = self.input_buf[:n], self.input_buf[n:]
        log.debug("Received:\n{0}".format(hex_print(s)))
        return s

    def get_message(self):
        """Receive the next full Message from the wire."""
        length = struct.unpack("!L", self.receive(4))[0]

        log.debug("Receiving message of length {0}".format(length))

        msg = self.receive(length)

        return messages.unpack(msg)
<|endoftext|>


<commit_before>import os
import os.path
import shutil
import subprocess
import sys

from glob import glob

from pocs.utils import current_time
from pocs.utils.logger import get_root_logger

from . import load_config

class Webcam(object):

    """ Simple module to take a picture with the webcams

    This class will capture images from any webcam entry in the config file.
    The capturing is done on a loop, with defaults of 255 stacked images and
    a minute cadence.

    Note:
            All parameters are optional.

    Note:
            This is a port of Olivier's `SKYCAM_start_webcamloop` function
            in skycam.c

    Note:
            TODO: The images then have their flux measured and the gain and brightness
            adjusted accordingly. Images analysis is stored in the (mongo) database

    Args:
            webcam (dict):      Config options for the camera, required.
            frames (int):       Number of frames to capture per image. Default 255
            resolution (str):   Resolution for images. Default "1600x1200"
            brightness (str):   Initial camera brightness. Default "50%"
            gain (str):         Initial camera gain. Default "50%"
            delay (int):        Time to wait between captures. Default 60 (seconds)
    """

    def __init__(self, webcam_config, frames=255, resolution="1600x1200", brightness="50%", gain="50%"):

        self.config = load_config()
        self.logger = get_root_logger()

        self.webcam_dir = self.config['directories'].get('webcam', '/var/panoptes/webcams/')
        assert os.path.exists(self.webcam_dir), self.logger.warning(
            "Webcam directory must exist: {}".format(self.webcam_dir))

        self.logger.info("Creating webcams")

        # Lookup the webcams
        if webcam_config is None:
            err_msg = "No webcams to connect. Please check config.yaml and all appropriate ports"
            self.logger.warning(err_msg)

        self.webcam_config = webcam_config
        self.name = self.webcam_config.get('name', 'GenericWebCam')

        self.port_name = self.webcam_config.get('port').split('/')[-1]

        # Command for taking pics
        self.cmd = shutil.which('fswebcam')

        # Defaults
        self._timestamp = "%Y-%m-%d %H:%M:%S"
        self._thumbnail_resolution = '240x120'

        # Create the string for the params
        self.base_params = "-F {} -r {} --set brightness={} --set gain={} --jpeg 100 --timestamp \"{}\" ".format(
            frames, resolution, brightness, gain, self._timestamp)

        self.logger.info("{} created".format(self.name))

    def capture(self):
        """ Capture an image from a webcam

        Given a webcam, this attempts to capture an image using the subprocess
        command. Also creates a thumbnail of the image

        Args:
            webcam (dict): Entry for the webcam. Example::
                {
                    'name': 'Pier West',
                    'port': '/dev/video0',
                    'params': {
                        'rotate': 270
                    },
                }

            The values for the `params` key will be passed directly to fswebcam
        """
        webcam = self.webcam_config

        assert isinstance(webcam, dict)
        self.logger.debug("Capturing image for {}...".format(webcam.get('name')))

        camera_name = self.port_name

        # Create the directory for storing images
        timestamp = current_time(flatten=True)
        date_dir = timestamp.split('T')[0]

        try:
            os.makedirs("{}/{}".format(self.webcam_dir, date_dir), exist_ok=True)
        except OSError as err:
            self.logger.warning("Cannot create new dir: {} \t {}".format(date_dir, err))

        # Output file names
        out_file = '{}/{}/{}_{}.jpeg'.format(self.webcam_dir, date_dir, camera_name, timestamp)

        # We also create a thumbnail and always link it to the same image
        # name so that it is always current.
        thumbnail_file = '{}/tn_{}.jpeg'.format(self.webcam_dir, camera_name)

        options = self.base_params
        if 'params' in webcam:
            for opt, val in webcam.get('params').items():
                options += "--{}={}".format(opt, val)

        # Assemble all the parameters
        params = " -d {} --title \"{}\" {} --save {} --scale {} {}".format(
            webcam.get('port'),
            webcam.get('name'),
            options,
            out_file,
            self._thumbnail_resolution,
            thumbnail_file
        )

        static_out_file = ''

        # Actually call the command.
        # NOTE: This is a blocking call (within this process). See `start_capturing`
        try:
            self.logger.debug("Webcam subproccess command: {} {}".format(self.cmd, params))

            with open(os.devnull, 'w') as devnull:
                retcode = subprocess.call(self.cmd + params, shell=True, stdout=devnull, stderr=devnull)

            if retcode < 0:
                self.logger.warning(
                    "Image captured terminated for {}. Return code: {} \t Error: {}".format(
                        webcam.get('name'),
                        retcode,
                        sys.stderr
                    )
                )
            else:
                self.logger.debug("Image captured for {}".format(webcam.get('name')))

                # Static files (always points to most recent)
                static_out_file = '{}/{}.jpeg'.format(self.webcam_dir, camera_name)

                # Symlink the latest image
                if os.path.lexists(static_out_file):
                    os.remove(static_out_file)

                os.symlink(out_file, static_out_file)

                return retcode
        except OSError as e:
            self.logger.warning("Execution failed:".format(e, file=sys.stderr))

        return {'out_fn': static_out_file}

    def create_timelapse(self, directory, fps=12, remove_after=False):
        """ Create a timelapse movie for the given directory """
        assert os.path.exists(directory), self.logger.warning("Directory does not exist: {}".format(directory))
        ffmpeg_cmd = shutil.which('ffmpeg')

        # Try for various video devices
        out_file = '{}/{}.mp4'.format(directory, self.port_name)

        cmd = [ffmpeg_cmd, '-f', 'image2', '-r', str(fps), '-pattern_type', 'glob',
               '-i', '{}{}*.jpeg'.format(directory, self.port_name), '-c:v', 'libx264', '-pix_fmt', 'yuv420p', out_file]

        self.logger.debug("Timelapse command: {}".format(cmd))
        try:
            subprocess.run(cmd)
        except subprocess.CalledProcessError as err:
            self.logger.warning("Problem making timelapse: {}".format(err))

        if remove_after:
            self.logger.debug("Removing all images files")
            for f in glob('{}{}*.jpeg'.format(directory, self.port_name)):
                os.remove(f)
<commit_msg>* Auto timelapse for webcams<commit_after>import os
import os.path
import shutil
import subprocess
import sys

from glob import glob

from pocs.utils import current_time
from pocs.utils.logger import get_root_logger

from . import load_config

class Webcam(object):

    """ Simple module to take a picture with the webcams

    This class will capture images from any webcam entry in the config file.
    The capturing is done on a loop, with defaults of 255 stacked images and
    a minute cadence.

    Note:
            All parameters are optional.

    Note:
            This is a port of Olivier's `SKYCAM_start_webcamloop` function
            in skycam.c

    Note:
            TODO: The images then have their flux measured and the gain and brightness
            adjusted accordingly. Images analysis is stored in the (mongo) database

    Args:
            webcam (dict):      Config options for the camera, required.
            frames (int):       Number of frames to capture per image. Default 255
            resolution (str):   Resolution for images. Default "1600x1200"
            brightness (str):   Initial camera brightness. Default "50%"
            gain (str):         Initial camera gain. Default "50%"
            delay (int):        Time to wait between captures. Default 60 (seconds)
    """

    def __init__(self, webcam_config, frames=255, resolution="1600x1200", brightness="50%", gain="50%"):

        self.config = load_config()
        self.logger = get_root_logger()

        self._today_dir = None

        self.webcam_dir = self.config['directories'].get('webcam', '/var/panoptes/webcams/')
        assert os.path.exists(self.webcam_dir), self.logger.warning(
            "Webcam directory must exist: {}".format(self.webcam_dir))

        self.logger.info("Creating webcams")

        # Lookup the webcams
        if webcam_config is None:
            err_msg = "No webcams to connect. Please check config.yaml and all appropriate ports"
            self.logger.warning(err_msg)

        self.webcam_config = webcam_config
        self.name = self.webcam_config.get('name', 'GenericWebCam')

        self.port_name = self.webcam_config.get('port').split('/')[-1]

        # Command for taking pics
        self.cmd = shutil.which('fswebcam')

        # Defaults
        self._timestamp = "%Y-%m-%d %H:%M:%S"
        self._thumbnail_resolution = '240x120'

        # Create the string for the params
        self.base_params = "-F {} -r {} --set brightness={} --set gain={} --jpeg 100 --timestamp \"{}\" ".format(
            frames, resolution, brightness, gain, self._timestamp)

        self.logger.info("{} created".format(self.name))

    def capture(self):
        """ Capture an image from a webcam

        Given a webcam, this attempts to capture an image using the subprocess
        command. Also creates a thumbnail of the image

        Args:
            webcam (dict): Entry for the webcam. Example::
                {
                    'name': 'Pier West',
                    'port': '/dev/video0',
                    'params': {
                        'rotate': 270
                    },
                }

            The values for the `params` key will be passed directly to fswebcam
        """
        webcam = self.webcam_config

        assert isinstance(webcam, dict)

        self.logger.debug("Capturing image for {}...".format(webcam.get('name')))

        camera_name = self.port_name

        # Create the directory for storing images
        timestamp = current_time(flatten=True)
        today_dir = timestamp.split('T')[0]
        today_path = "{}/{}".format(self.webcam_dir, today_dir)

        try:

            if today_path != self._today_dir:
                # If yesterday is not None, archive it
                if self._today_dir is not None:
                    self.logger.debug("Making timelapse for webcam")
                    self.create_timelapse(
                        self._today_dir, out_file="{}/{}.mp4".format(self.webcam_dir, today_dir), remove_after=True)

                # If today doesn't exist, make it
                if not os.path.exists(today_path):
                    self.logger.debug("Making directory for day's webcam")
                    os.makedirs(today_path, exist_ok=True)
                    self._today_dir = today_path

        except OSError as err:
            self.logger.warning("Cannot create new dir: {} \t {}".format(today_path, err))

        # Output file names
        out_file = '{}/{}_{}.jpeg'.format(today_path, camera_name, timestamp)

        # We also create a thumbnail and always link it to the same image
        # name so that it is always current.
        thumbnail_file = '{}/tn_{}.jpeg'.format(self.webcam_dir, camera_name)

        options = self.base_params
        if 'params' in webcam:
            for opt, val in webcam.get('params').items():
                options += "--{}={}".format(opt, val)

        # Assemble all the parameters
        params = " -d {} --title \"{}\" {} --save {} --scale {} {}".format(
            webcam.get('port'),
            webcam.get('name'),
            options,
            out_file,
            self._thumbnail_resolution,
            thumbnail_file
        )

        static_out_file = ''

        # Actually call the command.
        # NOTE: This is a blocking call (within this process). See `start_capturing`
        try:
            self.logger.debug("Webcam subproccess command: {} {}".format(self.cmd, params))

            with open(os.devnull, 'w') as devnull:
                retcode = subprocess.call(self.cmd + params, shell=True, stdout=devnull, stderr=devnull)

            if retcode < 0:
                self.logger.warning(
                    "Image captured terminated for {}. Return code: {} \t Error: {}".format(
                        webcam.get('name'),
                        retcode,
                        sys.stderr
                    )
                )
            else:
                self.logger.debug("Image captured for {}".format(webcam.get('name')))

                # Static files (always points to most recent)
                static_out_file = '{}/{}.jpeg'.format(self.webcam_dir, camera_name)

                # Symlink the latest image
                if os.path.lexists(static_out_file):
                    os.remove(static_out_file)

                os.symlink(out_file, static_out_file)

                return retcode
        except OSError as e:
            self.logger.warning("Execution failed:".format(e, file=sys.stderr))

        return {'out_fn': static_out_file}

    def create_timelapse(self, directory, fps=12, out_file=None, remove_after=False):
        """ Create a timelapse movie for the given directory """
        assert os.path.exists(directory), self.logger.warning("Directory does not exist: {}".format(directory))
        ffmpeg_cmd = shutil.which('ffmpeg')

        if out_file is None:
            out_file = self.port_name
            out_file = '{}/{}.mp4'.format(directory, out_file)

        cmd = [ffmpeg_cmd, '-f', 'image2', '-r', str(fps), '-pattern_type', 'glob',
               '-i', '{}{}*.jpeg'.format(directory, self.port_name), '-c:v', 'libx264', '-pix_fmt', 'yuv420p', out_file]

        self.logger.debug("Timelapse command: {}".format(cmd))
        try:
            subprocess.run(cmd)
        except subprocess.CalledProcessError as err:
            self.logger.warning("Problem making timelapse: {}".format(err))

        if remove_after:
            self.logger.debug("Removing all images files")
            for f in glob('{}{}*.jpeg'.format(directory, self.port_name)):
                os.remove(f)
<|endoftext|>


<commit_before>from settings import *
from stream import Stream
import socket
from util import *
from pyHPACK import HPACK
from pyHPACK.tables import Table
from frame import *

class Connection(object):
    def __init__(self, sock, addr, enable_tls, debug, is_client = False):
        self.setSocket(sock, enable_tls)
        self.addr = addr
        self.table = Table()
        self.streams = {}
        self.enablePush = SETTINGS.INIT_VALUE["enable_push"]
        self.maxConcurrentStreams = SETTINGS.INIT_VALUE["concurrent_streams"]
        self.maxFrameSize = SETTINGS.INIT_VALUE["frame_size"]
        self.maxHeaderListSize = SETTINGS.INIT_VALUE["header_list_size"]
        self.initialWindowSize = SETTINGS.INIT_VALUE["window_size"]
        self.peerSettingACK = False
        self.lastStreamID = 0
        self.addStream(0)
        self.preface = is_client
        self.is_goaway = False
        # temporaly using
        self.wireLenLimit = 24
        self.debug = debug

    def setSocket(self, sock, enable_tls):
        self.sock = sock
        if enable_tls:
            self._send = sock.write
            self._recv = sock.read
        else:
            self._send = sock.send
            self._recv = sock.recv

    def _send(self):
        pass

    def _recv(self):
        pass

    def send(self, frameType, flag = FLAG.NO, streamId = 0, **kwargs):
        frame = self.streams[streamId].makeFrame(frameType, flag, **kwargs)
        self._send(frame)
        # here?
        while len(self.streams[streamId].getWire()):
            if len(self.streams[streamId].getWire()) > self.wireLenLimit:
                frame = self.streams[streamId].makeFrame(TYPE.CONTINUATION, FLAG.NO)
            else:
                frame = self.streams[streamId].makeFrame(TYPE.CONTINUATION, FLAG.END_HEADERS)
            self._send(frame)

    def sendFrame(self, frame):
        frame.sendEval(self) #TODO: makeWire and send if this returns true
        state = self.getStreamState(frame.streamID)
        if frame.flags&FLAG.END_STREAM == FLAG.END_STREAM:
            if state == STATE.OPEN:
                self.setStreamState(frame.streamID, STATE.HCLOSED_L)
            elif state == STATE.HCLOSED_R:
                self.setStreamState(frame.streamID, STATE.CLOSED)
        frame.makeWire()
        print "%s\n\t%s" % (sendC.apply("SEND"), frame.string())
        self._send(frame.getWire())

    def setStreamState(self, ID, state):
        self.streams[ID].setState(state)

    def getStreamState(self, ID):
        return self.streams[ID].getState()

    def initFlagment(self, ID):
        self.streams[ID].initFlagment()

    def appendFlagment(self, ID, flagment):
        self.streams[ID].appendFlagment(flagment)

    def validateData(self):
        if self.preface:
            headerOctet = self._recv(9)
            if len(headerOctet) == 0:
                # when connection closed from client
                self.preface = False
                return False
            info = Http2Header.getHeaderInfo(headerOctet)
            if not self.is_goaway or self.is_goaway and (info.type == TYPE.HEADERS or
                                                         info.type == TYPE.PRIORITY or
                                                         info.type == TYPE.CONTINUATION):
                stream = self.streams.get(info.streamID, '')
                if not stream:
                    self.addStream(info.streamID)
                    stream = self.streams[info.streamID]
                if (stream.getState() == STATE.CLOSED and
                    info.type != TYPE.PRIORITY and
                    info.type != TYPE.RST_STREAM):
                    self.sendFrame(Rst_Stream(info.streamID, err=ERR_CODE.STREAM_CLOSED))
                frameFunc = getFrameFunc(info.type)
                frame = frameFunc(info, self._recv(info.length))
                if info.flags&FLAG.END_HEADERS == FLAG.END_HEADERS:
                    frame.headers = HPACK.decode(
                        stream.headerFlagment+frame.headerFlagment, self.table)
                    stream.initFlagment()
                print "%s\n\t%s" % (recvC.apply("RECV"), frame.string())
                if stream.continuing and info.type != TYPE.CONTINUATION:
                    self.sendFrame(Goaway(self.lastStreamID, err=ERR_CODE.PROTOCOL_ERROR))
                frame.recvEval(self)
            else:
                self._recv(info.length)
        else:
            data = self._recv(24)
            if data == CONNECTION_PREFACE:
                self.preface = True
        return True

    def addStream(self, ID, state = STATE.IDLE):
        self.streams[ID] = Stream(ID, self.initialWindowSize, state)

    def setHeaderTableSize(self, size):
        self.table.setMaxHeaderTableSize(size)

    def useWindow(self, ID, size):
        self.streams[0].useWindow(size)
        self.streams[ID].useWindow(size)

    def recoverWindow(self, ID, size):
        self.streams[ID].recoverWindow(size)

    def setInitialWindowSize(self, size):
        for ID in self.streams:
            if self.stream[ID].state != STATE.IDLE:
                self.stream[ID].setInitialWindowSize(size)
<commit_msg>improve code (use stream)<commit_after>from settings import *
from stream import Stream
import socket
from util import *
from pyHPACK import HPACK
from pyHPACK.tables import Table
from frame import *

class Connection(object):
    def __init__(self, sock, addr, enable_tls, debug, is_client = False):
        self.setSocket(sock, enable_tls)
        self.addr = addr
        self.table = Table()
        self.streams = {}
        self.enablePush = SETTINGS.INIT_VALUE["enable_push"]
        self.maxConcurrentStreams = SETTINGS.INIT_VALUE["concurrent_streams"]
        self.maxFrameSize = SETTINGS.INIT_VALUE["frame_size"]
        self.maxHeaderListSize = SETTINGS.INIT_VALUE["header_list_size"]
        self.initialWindowSize = SETTINGS.INIT_VALUE["window_size"]
        self.peerSettingACK = False
        self.lastStreamID = 0
        self.addStream(0)
        self.preface = is_client
        self.is_goaway = False
        # temporaly using
        self.wireLenLimit = 24
        self.debug = debug

    def setSocket(self, sock, enable_tls):
        self.sock = sock
        if enable_tls:
            self._send = sock.write
            self._recv = sock.read
        else:
            self._send = sock.send
            self._recv = sock.recv

    def _send(self):
        pass

    def _recv(self):
        pass

    def send(self, frameType, flag = FLAG.NO, streamId = 0, **kwargs):
        frame = self.streams[streamId].makeFrame(frameType, flag, **kwargs)
        self._send(frame)
        # here?
        while len(self.streams[streamId].getWire()):
            if len(self.streams[streamId].getWire()) > self.wireLenLimit:
                frame = self.streams[streamId].makeFrame(TYPE.CONTINUATION, FLAG.NO)
            else:
                frame = self.streams[streamId].makeFrame(TYPE.CONTINUATION, FLAG.END_HEADERS)
            self._send(frame)

    def sendFrame(self, frame):
        frame.sendEval(self) #TODO: makeWire and send if this returns true
        if frame.flags&FLAG.END_STREAM == FLAG.END_STREAM:
            stream = self.streams.get(frame.streamID, None)
            state = stream.getState()
            if state == STATE.OPEN:
                stream.setState(STATE.HCLOSED_L)
            elif state == STATE.HCLOSED_R:
                stream.setState(STATE.CLOSED)
        frame.makeWire()
        print "%s\n\t%s" % (sendC.apply("SEND"), frame.string())
        self._send(frame.getWire())

    def setStreamState(self, ID, state):
        self.streams[ID].setState(state)

    def getStreamState(self, ID):
        return self.streams[ID].getState()

    def initFlagment(self, ID):
        self.streams[ID].initFlagment()

    def appendFlagment(self, ID, flagment):
        self.streams[ID].appendFlagment(flagment)

    def validateData(self):
        if self.preface:
            headerOctet = self._recv(9)
            if len(headerOctet) == 0:
                # when connection closed from client
                self.preface = False
                return False
            info = Http2Header.getHeaderInfo(headerOctet)
            if not self.is_goaway or self.is_goaway and (info.type == TYPE.HEADERS or
                                                         info.type == TYPE.PRIORITY or
                                                         info.type == TYPE.CONTINUATION):
                stream = self.streams.get(info.streamID, '')
                if not stream:
                    self.addStream(info.streamID)
                    stream = self.streams[info.streamID]
                if (stream.getState() == STATE.CLOSED and
                    info.type != TYPE.PRIORITY and
                    info.type != TYPE.RST_STREAM):
                    self.sendFrame(Rst_Stream(info.streamID, err=ERR_CODE.STREAM_CLOSED))
                frameFunc = getFrameFunc(info.type)
                frame = frameFunc(info, self._recv(info.length))
                if info.flags&FLAG.END_HEADERS == FLAG.END_HEADERS:
                    frame.headers = HPACK.decode(
                        stream.headerFlagment+frame.headerFlagment, self.table)
                    stream.initFlagment()
                print "%s\n\t%s" % (recvC.apply("RECV"), frame.string())
                if stream.continuing and info.type != TYPE.CONTINUATION:
                    self.sendFrame(Goaway(self.lastStreamID, err=ERR_CODE.PROTOCOL_ERROR))
                frame.recvEval(self)
            else:
                self._recv(info.length)
        else:
            data = self._recv(24)
            if data == CONNECTION_PREFACE:
                self.preface = True
        return True

    def addStream(self, ID, state = STATE.IDLE):
        self.streams[ID] = Stream(ID, self.initialWindowSize, state)

    def setHeaderTableSize(self, size):
        self.table.setMaxHeaderTableSize(size)

    def useWindow(self, ID, size):
        self.streams[0].useWindow(size)
        self.streams[ID].useWindow(size)

    def recoverWindow(self, ID, size):
        self.streams[ID].recoverWindow(size)

    def setInitialWindowSize(self, size):
        for ID in self.streams:
            if self.stream[ID].state != STATE.IDLE:
                self.stream[ID].setInitialWindowSize(size)
<|endoftext|>


<commit_before>import sys
from inspect   import getmembers
from webob.exc import HTTPFound

from util      import iscontroller, _cfg
from routing   import lookup_controller

__all__ = ['PecanHook', 'TransactionHook', 'HookController', 'RequestViewerHook']

def walk_controller(root_class, controller, hooks):
    if not isinstance(controller, (int, dict)):
        for name, value in getmembers(controller):
            if name == 'controller': continue
            if name.startswith('__') and name.endswith('__'): continue

            if iscontroller(value):
                for hook in hooks:
                    value._pecan.setdefault('hooks', []).append(hook)
            elif hasattr(value, '__class__'):
                if name.startswith('__') and name.endswith('__'): continue
                walk_controller(root_class, value, hooks)

class HookController(object):
    '''
    A base class for controllers that would like to specify hooks on
    their controller methods. Simply create a list of hook objects
    called ``__hooks__`` as a member of the controller's namespace.
    '''

    __hooks__ = []

    class __metaclass__(type):
        def __init__(cls, name, bases, dict_):
            walk_controller(cls, cls, dict_['__hooks__'])

class PecanHook(object):
    '''
    A base class for Pecan hooks. Inherit from this class to create your
    own hooks. Set a priority on a hook by setting the ``priority``
    attribute for the hook, which defaults to 100.
    '''

    priority = 100

    def on_route(self, state):
        '''
        Override this method to create a hook that gets called upon
        the start of routing.

        :param state: The Pecan ``state`` object for the current request.
        '''
        return

    def before(self, state):
        '''
        Override this method to create a hook that gets called after
        routing, but before the request gets passed to your controller.

        :param state: The Pecan ``state`` object for the current request.
        '''
        return

    def after(self, state):
        '''
        Override this method to create a hook that gets called after
        the request has been handled by the controller.

        :param state: The Pecan ``state`` object for the current request.
        '''
        return

    def on_error(self, state, e):
        '''
        Override this method to create a hook that gets called upon
        an exception being raised in your controller.

        :param state: The Pecan ``state`` object for the current request.
        :param e: The ``Exception`` object that was raised.
        '''
        return

class TransactionHook(PecanHook):
    '''
    A basic framework hook for supporting wrapping requests in
    transactions. By default, it will wrap all but ``GET`` and ``HEAD``
    requests in a transaction. Override the ``is_transactional`` method
    to define your own rules for what requests should be transactional.
    '''

    def __init__(self, start, start_ro, commit, rollback, clear):
        '''
        :param start: A callable that will bind to a writable database and start a transaction.
        :param start_ro: A callable that will bind to a readable database.
        :param commit: A callable that will commit the active transaction.
        :param rollback: A callable that will roll back the active transaction.
        :param clear: A callable that will clear your current context.
        '''

        self.start    = start
        self.start_ro = start_ro
        self.commit   = commit
        self.rollback = rollback
        self.clear    = clear

    def is_transactional(self, state):
        '''
        Decide if a request should be wrapped in a transaction, based
        upon the state of the request. By default, wraps all but ``GET``
        and ``HEAD`` requests in a transaction, along with respecting
        the ``transactional`` decorator from :mod:pecan.decorators.

        :param state: The Pecan state object for the current request.
        '''

        controller = getattr(state, 'controller', None)
        if controller:
            force_transactional = _cfg(controller).get('transactional', False)
        else:
            force_transactional = False

        if state.request.method not in ('GET', 'HEAD') or force_transactional:
            return True
        return False

    def on_route(self, state):
        state.request.error = False
        if self.is_transactional(state):
            state.request.transactional = True
            self.start()
        else:
            state.request.transactional = False
            self.start_ro()

    def before(self, state):
        if self.is_transactional(state) and not state.request.transactional:
            self.clear()
            state.request.transactional = True
            self.start()

    def on_error(self, state, e):
        #
        # If we should ignore redirects,
        # (e.g., shouldn't consider them rollback-worthy)
        # don't set `state.request.error = True`.
        #
        transactional_ignore_redirects = state.request.method not in ('GET', 'HEAD')
        if state.controller is not None:
            transactional_ignore_redirects = _cfg(state.controller).get('transactional_ignore_redirects', transactional_ignore_redirects)
        if type(e) is HTTPFound and transactional_ignore_redirects is True:
            return
        state.request.error = True

    def after(self, state):
        if state.request.transactional:
            if state.request.error:
                self.rollback()
            else:
                self.commit()

                #
                # If a controller was routed to, find any
                # after_commit actions it may have registered, and perform
                # them.
                #
                controller = getattr(state, 'controller', None)
                if controller is not None:
                    actions = _cfg(controller).get('after_commit', [])
                    for action in actions:
                        action()

        self.clear()

class RequestViewerHook(PecanHook):
    '''
    Returns some information about what is going on in a single request.  It
    accepts specific items to report on but uses a default list of items when
    none are passed in.  Based on the requested ``url``, items can also be
    blacklisted.
    Configuration is flexible, can be passed in (or not) and can contain some or
    all the keys supported.

    ``items``
    ---------
    This key holds the items that this hook will display. When this key is passed
    only the items in the list will be used.
    Valid items are *any* item that the ``request`` object holds, by default it uses
    the following:

    * path
    * status
    * method
    * controller
    * params
    * hooks

    .. :note::
        This key should always use a ``list`` of items to use.

    ``blacklist``
    -------------
    This key holds items that will be blacklisted based on ``url``. If there is a need
    to ommit urls that start with `/javascript`, then this key would look like::

        'blacklist': ['/javascript']

    As many blacklisting items as needed can be contained in the list. The hook
    will verify that the url is not starting with items in this list to display
    results, otherwise it will get ommited.

    .. :note::
        This key should always use a ``list`` of items to use.

    For more detailed documentation about this hook, please see :ref:`requestviewerhook`
    '''

    available = ['path', 'status', 'method', 'controller', 'params', 'hooks']

    def __init__(self, config=None, writer=sys.stdout, terminal=True, headers=True):
        '''
        :param config:   A (optional) dictionary that can hold ``items`` and/or
                         ``blacklist`` keys.
        :param writer:   The stream writer to use. Can redirect output to other
                         streams as long as the passed in stream has a ``write``
                         callable method.
        :param terminal: Outputs to the chosen stream writer (usually the terminal)
        :param headers:  Sets values to the X-HTTP headers
        '''
        if not config:
            self.config = {'items' : self.available}
        else:
            if config.__class__.__name__ == 'Config':
                self.config = config.as_dict()
            else:
                self.config = config
        self.writer     = writer
        self.items      = self.config.get('items', self.available)
        self.blacklist  = self.config.get('blacklist', [])
        self.terminal   = terminal
        self.headers    = headers

    def after(self, state):

        # Default and/or custom response information
        responses = {
             'controller' : lambda self, state: self.get_controller(state),
             'method'     : lambda self, state: state.request.method,
             'path'       : lambda self, state: state.request.path,
             'params'     : lambda self, state: state.request.str_params.items(),
             'status'     : lambda self, state: state.response.status,
             'hooks'      : lambda self, state: self.format_hooks(state.app.hooks),
         }

        is_available = [
                i for i in self.items
                if i in self.available or hasattr(state.request, i)
        ]

        terminal  = []
        headers   = []
        will_skip = [i for i in self.blacklist if state.request.path.startswith(i)]

        if will_skip:
            return

        for request_info in is_available:
            try:
                value = responses.get(request_info)
                if not value:
                    value = getattr(state.request, request_info)
                else:
                    value = value(self, state)
            except Exception, e:
                value = e

            terminal.append('%-12s - %s\n' % (request_info, value))
            headers.append((request_info, value))

        if self.terminal:
            self.writer.write(''.join(terminal))
            self.writer.write('\n\n')

        if self.headers:
            for h in headers:
                key   = str(h[0])
                value = str(h[1])
                name  = 'X-Pecan-%s' % key
                state.response.headers[name] = value

    def get_controller(self, state):
        '''
        Retrieves the actual controller name from the application
        Specific to Pecan (not available in the request object)
        '''
        path = state.request.pecan['routing_path'].split('/')[1:]
        controller, reminder = lookup_controller(state.app.root, path)
        return controller.__str__().split()[2]

    def format_hooks(self, hooks):
        '''
        Tries to format the hook objects to be more readable
        Specific to Pecan (not available in the request object)
        '''
        str_hooks = [str(i).split()[0].strip('<') for i in hooks]
        return [i.split('.')[-1] for i in str_hooks if '.' in i]

<commit_msg>update to use the correct param key and encode into utf-8<commit_after>import sys
from inspect   import getmembers
from webob.exc import HTTPFound

from util      import iscontroller, _cfg
from routing   import lookup_controller

__all__ = ['PecanHook', 'TransactionHook', 'HookController', 'RequestViewerHook']

def walk_controller(root_class, controller, hooks):
    if not isinstance(controller, (int, dict)):
        for name, value in getmembers(controller):
            if name == 'controller': continue
            if name.startswith('__') and name.endswith('__'): continue

            if iscontroller(value):
                for hook in hooks:
                    value._pecan.setdefault('hooks', []).append(hook)
            elif hasattr(value, '__class__'):
                if name.startswith('__') and name.endswith('__'): continue
                walk_controller(root_class, value, hooks)

class HookController(object):
    '''
    A base class for controllers that would like to specify hooks on
    their controller methods. Simply create a list of hook objects
    called ``__hooks__`` as a member of the controller's namespace.
    '''

    __hooks__ = []

    class __metaclass__(type):
        def __init__(cls, name, bases, dict_):
            walk_controller(cls, cls, dict_['__hooks__'])

class PecanHook(object):
    '''
    A base class for Pecan hooks. Inherit from this class to create your
    own hooks. Set a priority on a hook by setting the ``priority``
    attribute for the hook, which defaults to 100.
    '''

    priority = 100

    def on_route(self, state):
        '''
        Override this method to create a hook that gets called upon
        the start of routing.

        :param state: The Pecan ``state`` object for the current request.
        '''
        return

    def before(self, state):
        '''
        Override this method to create a hook that gets called after
        routing, but before the request gets passed to your controller.

        :param state: The Pecan ``state`` object for the current request.
        '''
        return

    def after(self, state):
        '''
        Override this method to create a hook that gets called after
        the request has been handled by the controller.

        :param state: The Pecan ``state`` object for the current request.
        '''
        return

    def on_error(self, state, e):
        '''
        Override this method to create a hook that gets called upon
        an exception being raised in your controller.

        :param state: The Pecan ``state`` object for the current request.
        :param e: The ``Exception`` object that was raised.
        '''
        return

class TransactionHook(PecanHook):
    '''
    A basic framework hook for supporting wrapping requests in
    transactions. By default, it will wrap all but ``GET`` and ``HEAD``
    requests in a transaction. Override the ``is_transactional`` method
    to define your own rules for what requests should be transactional.
    '''

    def __init__(self, start, start_ro, commit, rollback, clear):
        '''
        :param start: A callable that will bind to a writable database and start a transaction.
        :param start_ro: A callable that will bind to a readable database.
        :param commit: A callable that will commit the active transaction.
        :param rollback: A callable that will roll back the active transaction.
        :param clear: A callable that will clear your current context.
        '''

        self.start    = start
        self.start_ro = start_ro
        self.commit   = commit
        self.rollback = rollback
        self.clear    = clear

    def is_transactional(self, state):
        '''
        Decide if a request should be wrapped in a transaction, based
        upon the state of the request. By default, wraps all but ``GET``
        and ``HEAD`` requests in a transaction, along with respecting
        the ``transactional`` decorator from :mod:pecan.decorators.

        :param state: The Pecan state object for the current request.
        '''

        controller = getattr(state, 'controller', None)
        if controller:
            force_transactional = _cfg(controller).get('transactional', False)
        else:
            force_transactional = False

        if state.request.method not in ('GET', 'HEAD') or force_transactional:
            return True
        return False

    def on_route(self, state):
        state.request.error = False
        if self.is_transactional(state):
            state.request.transactional = True
            self.start()
        else:
            state.request.transactional = False
            self.start_ro()

    def before(self, state):
        if self.is_transactional(state) and not state.request.transactional:
            self.clear()
            state.request.transactional = True
            self.start()

    def on_error(self, state, e):
        #
        # If we should ignore redirects,
        # (e.g., shouldn't consider them rollback-worthy)
        # don't set `state.request.error = True`.
        #
        transactional_ignore_redirects = state.request.method not in ('GET', 'HEAD')
        if state.controller is not None:
            transactional_ignore_redirects = _cfg(state.controller).get('transactional_ignore_redirects', transactional_ignore_redirects)
        if type(e) is HTTPFound and transactional_ignore_redirects is True:
            return
        state.request.error = True

    def after(self, state):
        if state.request.transactional:
            if state.request.error:
                self.rollback()
            else:
                self.commit()

                #
                # If a controller was routed to, find any
                # after_commit actions it may have registered, and perform
                # them.
                #
                controller = getattr(state, 'controller', None)
                if controller is not None:
                    actions = _cfg(controller).get('after_commit', [])
                    for action in actions:
                        action()

        self.clear()

class RequestViewerHook(PecanHook):
    '''
    Returns some information about what is going on in a single request.  It
    accepts specific items to report on but uses a default list of items when
    none are passed in.  Based on the requested ``url``, items can also be
    blacklisted.
    Configuration is flexible, can be passed in (or not) and can contain some or
    all the keys supported.

    ``items``
    ---------
    This key holds the items that this hook will display. When this key is passed
    only the items in the list will be used.
    Valid items are *any* item that the ``request`` object holds, by default it uses
    the following:

    * path
    * status
    * method
    * controller
    * params
    * hooks

    .. :note::
        This key should always use a ``list`` of items to use.

    ``blacklist``
    -------------
    This key holds items that will be blacklisted based on ``url``. If there is a need
    to ommit urls that start with `/javascript`, then this key would look like::

        'blacklist': ['/javascript']

    As many blacklisting items as needed can be contained in the list. The hook
    will verify that the url is not starting with items in this list to display
    results, otherwise it will get ommited.

    .. :note::
        This key should always use a ``list`` of items to use.

    For more detailed documentation about this hook, please see :ref:`requestviewerhook`
    '''

    available = ['path', 'status', 'method', 'controller', 'params', 'hooks']

    def __init__(self, config=None, writer=sys.stdout, terminal=True, headers=True):
        '''
        :param config:   A (optional) dictionary that can hold ``items`` and/or
                         ``blacklist`` keys.
        :param writer:   The stream writer to use. Can redirect output to other
                         streams as long as the passed in stream has a ``write``
                         callable method.
        :param terminal: Outputs to the chosen stream writer (usually the terminal)
        :param headers:  Sets values to the X-HTTP headers
        '''
        if not config:
            self.config = {'items' : self.available}
        else:
            if config.__class__.__name__ == 'Config':
                self.config = config.as_dict()
            else:
                self.config = config
        self.writer     = writer
        self.items      = self.config.get('items', self.available)
        self.blacklist  = self.config.get('blacklist', [])
        self.terminal   = terminal
        self.headers    = headers

    def after(self, state):

        # Default and/or custom response information
        responses = {
             'controller' : lambda self, state: self.get_controller(state),
             'method'     : lambda self, state: state.request.method,
             'path'       : lambda self, state: state.request.path,
             'params'     : lambda self, state: [p.encode('utf-8') for p in state.request.params.items()],
             'status'     : lambda self, state: state.response.status,
             'hooks'      : lambda self, state: self.format_hooks(state.app.hooks),
         }

        is_available = [
                i for i in self.items
                if i in self.available or hasattr(state.request, i)
        ]

        terminal  = []
        headers   = []
        will_skip = [i for i in self.blacklist if state.request.path.startswith(i)]

        if will_skip:
            return

        for request_info in is_available:
            try:
                value = responses.get(request_info)
                if not value:
                    value = getattr(state.request, request_info)
                else:
                    value = value(self, state)
            except Exception, e:
                value = e

            terminal.append('%-12s - %s\n' % (request_info, value))
            headers.append((request_info, value))

        if self.terminal:
            self.writer.write(''.join(terminal))
            self.writer.write('\n\n')

        if self.headers:
            for h in headers:
                key   = str(h[0])
                value = str(h[1])
                name  = 'X-Pecan-%s' % key
                state.response.headers[name] = value

    def get_controller(self, state):
        '''
        Retrieves the actual controller name from the application
        Specific to Pecan (not available in the request object)
        '''
        path = state.request.pecan['routing_path'].split('/')[1:]
        controller, reminder = lookup_controller(state.app.root, path)
        return controller.__str__().split()[2]

    def format_hooks(self, hooks):
        '''
        Tries to format the hook objects to be more readable
        Specific to Pecan (not available in the request object)
        '''
        str_hooks = [str(i).split()[0].strip('<') for i in hooks]
        return [i.split('.')[-1] for i in str_hooks if '.' in i]

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from pint.unit import DimensionalityError
import six
from odin import exceptions
from odin.contrib.pint.units import registry
from odin.fields import Field
from odin.validators import EMPTY_VALUES

__all__ = ('FloatQField',)

class FloatQField(Field):
    default_error_messages = {
        'invalid': "'%s' value must be a float.",
    }

    def __init__(self, units, **kwargs):
        super(FloatQField, self).__init__(**kwargs)

        # Ensure we have valid units
        if units is None:
            raise ValueError("Units cannot be None")
        if isinstance(units, six.string_types):
            units = registry[units]
        #if not units_ in units.registry:
        #    raise ValueError("Units object is not a member of `odin.units.registry`. Any custom units must be "
        #                     "registered with Odin's unit registry.")
        self.units = units

    def to_python(self, value):
        if value in EMPTY_VALUES:
            return None
        if not isinstance(value, registry.Quantity):
            if isinstance(value, tuple) and len(value) == 2:
                magnitude, units = value
            else:
                magnitude, units = value, self.units
            if isinstance(units, six.string_types):
                units = registry[units]
            try:
                value = float(magnitude) * units
            except ValueError:
                msg = self.error_messages['invalid'] % value
                raise exceptions.ValidationError(msg)
        try:
            return value.to(self.units)
        except DimensionalityError as de:
            raise exceptions.ValidationError(de)
<commit_msg>Split field to allow for simpler extension<commit_after># -*- coding: utf-8 -*-
from pint.unit import DimensionalityError
import six
from odin import exceptions
from odin.contrib.pint.units import registry
from odin.fields import Field
from odin.validators import EMPTY_VALUES

__all__ = ('FloatField',)

class PintField(Field):
    def __init__(self, units, **kwargs):
        super(PintField, self).__init__(**kwargs)

        # Ensure we have valid units
        if units is None:
            raise ValueError("Units cannot be None")
        if isinstance(units, six.string_types):
            units = registry[units]
        #if not units_ in units.registry:
        #    raise ValueError("Units object is not a member of `odin.units.registry`. Any custom units must be "
        #                     "registered with Odin's unit registry.")
        self.units = units

    def to_quantity(self, value):
        if not isinstance(value, registry.Quantity):
            # Split out units from underlying magnitudes
            if isinstance(value, (tuple, list)) and len(value) == 2:
                raw_value, units = value
            else:
                raw_value, units = value, self.units
            # Extract the units
            if isinstance(units, six.string_types):
                units = registry[units]
            # Convert the magnitude and apply units
            value = self.to_magnitude(raw_value) * units

        try:
            return value.to(self.units)
        except DimensionalityError as de:
            raise exceptions.ValidationError(de)

    def to_magnitude(self, value):
        raise NotImplementedError()

class FloatField(PintField):
    default_error_messages = {
        'invalid': "'%s' value must be a float.",
    }

    def to_magnitude(self, value):
        try:
            return float(value)
        except ValueError:
            msg = self.error_messages['invalid'] % value
            raise exceptions.ValidationError(msg)

    def to_python(self, value):
        if value in EMPTY_VALUES:
            return None
        return self.to_quantity(value)
<|endoftext|>


<commit_before># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 OpenStack, LLC
#
# Copyright 2012 Nebula, Inc.
#
#    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.

"""
Installation script for the OpenStack Dashboard development virtualenv.
"""

import os
import subprocess
import sys

ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
VENV = os.path.join(ROOT, '.venv')
WITH_VENV = os.path.join(ROOT, 'tools', 'with_venv.sh')
PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires')
TEST_REQUIRES = os.path.join(ROOT, 'tools', 'test-requires')

def die(message, *args):
    print >> sys.stderr, message % args
    sys.exit(1)

def run_command(cmd, redirect_output=True, check_exit_code=True, cwd=ROOT,
                die_message=None):
    """
    Runs a command in an out-of-process shell, returning the
    output of that command.  Working directory is ROOT.
    """
    if redirect_output:
        stdout = subprocess.PIPE
    else:
        stdout = None

    proc = subprocess.Popen(cmd, cwd=cwd, stdout=stdout)
    output = proc.communicate()[0]
    if check_exit_code and proc.returncode != 0:
        if die_message is None:
            die('Command "%s" failed.\n%s', ' '.join(cmd), output)
        else:
            die(die_message)
    return output

HAS_EASY_INSTALL = bool(run_command(['which', 'easy_install'],
                                    check_exit_code=False).strip())
HAS_VIRTUALENV = bool(run_command(['which', 'virtualenv'],
                                  check_exit_code=False).strip())

def check_dependencies():
    """Make sure virtualenv is in the path."""

    print 'Checking dependencies...'
    if not HAS_VIRTUALENV:
        print 'Virtual environment not found.'
        # Try installing it via easy_install...
        if HAS_EASY_INSTALL:
            print 'Installing virtualenv via easy_install...',
            run_command(['easy_install', 'virtualenv'],
                        die_message='easy_install failed to install virtualenv'
                                    '\ndevelopment requires virtualenv, please'
                                    ' install it using your favorite tool')
            if not run_command(['which', 'virtualenv']):
                die('ERROR: virtualenv not found in path.\n\ndevelopment '
                    ' requires virtualenv, please install it using your'
                    ' favorite package management tool and ensure'
                    ' virtualenv is in your path')
            print 'virtualenv installation done.'
        else:
            die('easy_install not found.\n\nInstall easy_install'
                ' (python-setuptools in ubuntu) or virtualenv by hand,'
                ' then rerun.')
    run_command(['sudo', 'apt-get', 'install', 'libmysqlclient-dev', 'python-dev'])
    print 'dependency check done.'

def create_virtualenv(venv=VENV):
    """Creates the virtual environment and installs PIP only into the
    virtual environment
    """
    print 'Creating venv...',
    run_command(['virtualenv', '-q', '--no-site-packages', VENV])
    print 'done.'
    print 'Installing pip in virtualenv...',
    if not run_command([WITH_VENV, 'easy_install', 'pip']).strip():
        die("Failed to install pip.")
    print 'done.'
    print 'Installing distribute in virtualenv...'
    pip_install('distribute>=0.6.24')
    print 'done.'

def pip_install(*args):
    args = [WITH_VENV, 'pip', 'install', '--upgrade'] + list(args)
    run_command(args, redirect_output=False)

def install_dependencies(venv=VENV):
    print "Installing dependencies..."
    print "(This may take several minutes, don't panic)"
    pip_install('-r', TEST_REQUIRES)
    pip_install('-r', PIP_REQUIRES)

    # Tell the virtual env how to "import dashboard"
    py = 'python%d.%d' % (sys.version_info[0], sys.version_info[1])
    pthfile = os.path.join(venv, "lib", py, "site-packages", "dashboard.pth")
    f = open(pthfile, 'w')
    f.write("%s\n" % ROOT)

"""
def install_horizon():
    print 'Installing horizon module in development mode...'
    run_command([WITH_VENV, 'python', 'setup.py', 'develop'], cwd=ROOT)
"""

def print_summary():
    summary = """
Dome development environment setup is complete.

To activate the virtualenv for the extent of your current shell session you
can run:

$ source .venv/bin/activate
"""
    print summary

def main():
    check_dependencies()
    create_virtualenv()
    install_dependencies()
    #install_horizon()
    print_summary()

if __name__ == '__main__':
    main()
<commit_msg>Update install_venv.py<commit_after># vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2012 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
#
# Copyright 2012 OpenStack, LLC
#
# Copyright 2012 Nebula, Inc.
#
#    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.

"""
Installation script for the OpenStack Dashboard development virtualenv.
"""

import os
import subprocess
import sys

ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
VENV = os.path.join(ROOT, '.venv')
WITH_VENV = os.path.join(ROOT, 'tools', 'with_venv.sh')
PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires')
TEST_REQUIRES = os.path.join(ROOT, 'tools', 'test-requires')

def die(message, *args):
    print >> sys.stderr, message % args
    sys.exit(1)

def run_command(cmd, redirect_output=True, check_exit_code=True, cwd=ROOT,
                die_message=None):
    """
    Runs a command in an out-of-process shell, returning the
    output of that command.  Working directory is ROOT.
    """
    if redirect_output:
        stdout = subprocess.PIPE
    else:
        stdout = None

    proc = subprocess.Popen(cmd, cwd=cwd, stdout=stdout)
    output = proc.communicate()[0]
    if check_exit_code and proc.returncode != 0:
        if die_message is None:
            die('Command "%s" failed.\n%s', ' '.join(cmd), output)
        else:
            die(die_message)
    return output

HAS_EASY_INSTALL = bool(run_command(['which', 'easy_install'],
                                    check_exit_code=False).strip())
HAS_VIRTUALENV = bool(run_command(['which', 'virtualenv'],
                                  check_exit_code=False).strip())

def check_dependencies():
    """Make sure virtualenv is in the path."""

    print 'Checking dependencies...'
    if not HAS_VIRTUALENV:
        print 'Virtual environment not found.'
        # Try installing it via easy_install...
        if HAS_EASY_INSTALL:
            print 'Installing virtualenv via easy_install...',
            run_command(['easy_install', 'virtualenv'],
                        die_message='easy_install failed to install virtualenv'
                                    '\ndevelopment requires virtualenv, please'
                                    ' install it using your favorite tool')
            if not run_command(['which', 'virtualenv']):
                die('ERROR: virtualenv not found in path.\n\ndevelopment '
                    ' requires virtualenv, please install it using your'
                    ' favorite package management tool and ensure'
                    ' virtualenv is in your path')
            print 'virtualenv installation done.'
        else:
            die('easy_install not found.\n\nInstall easy_install'
                ' (python-setuptools in ubuntu) or virtualenv by hand,'
                ' then rerun.')

    #install support for mysql-python package on Ubuntu
    run_command(['sudo', 'apt-get', 'install', 'libmysqlclient-dev', 'python-dev'])
    print 'dependency check done.'

def create_virtualenv(venv=VENV):
    """Creates the virtual environment and installs PIP only into the
    virtual environment
    """
    print 'Creating venv...',
    run_command(['virtualenv', '-q', '--no-site-packages', VENV])
    print 'done.'
    print 'Installing pip in virtualenv...',
    if not run_command([WITH_VENV, 'easy_install', 'pip']).strip():
        die("Failed to install pip.")
    print 'done.'
    print 'Installing distribute in virtualenv...'
    pip_install('distribute>=0.6.24')
    print 'done.'

def pip_install(*args):
    args = [WITH_VENV, 'pip', 'install', '--upgrade'] + list(args)
    run_command(args, redirect_output=False)

def install_dependencies(venv=VENV):
    print "Installing dependencies..."
    print "(This may take several minutes, don't panic)"
    pip_install('-r', TEST_REQUIRES)
    pip_install('-r', PIP_REQUIRES)

    # Tell the virtual env how to "import dashboard"
    py = 'python%d.%d' % (sys.version_info[0], sys.version_info[1])
    pthfile = os.path.join(venv, "lib", py, "site-packages", "dashboard.pth")
    f = open(pthfile, 'w')
    f.write("%s\n" % ROOT)

"""
def install_horizon():
    print 'Installing horizon module in development mode...'
    run_command([WITH_VENV, 'python', 'setup.py', 'develop'], cwd=ROOT)
"""

def print_summary():
    summary = """
Dome development environment setup is complete.

To activate the virtualenv for the extent of your current shell session you
can run:

$ source .venv/bin/activate
"""
    print summary

def main():
    check_dependencies()
    create_virtualenv()
    install_dependencies()
    #install_horizon()
    print_summary()

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


<commit_before>#!/usr/bin/python

import random
import re
import string
import sys
import time

from random import randint

from core.morse import Morse
from core.phonetic import Phonetic
from core.voicesynthetizer import VoiceSynthetizer

from modules.command import Command

class MorseTeacher(object):

    def __init__(self, voicesynthetizer):

        self.morse = Morse()
        self.speaker = voicesynthetizer
        self.phonetic = Phonetic()
        self.command = Command(voicesynthetizer)

    def __del__(self):
        pass

    def message(self, message):
        self.speaker.speechit(message)

    def welcome(self):
        self.message("Modulo de Aprendizaje de Codigo Morse, sugerencias escribir a ")
        self.message(" ".join(self.phonetic.decode('xe1gyq@gmail.com')))

    def randomnumber(self, n):
        range_start = 10**(n-1)
        range_end = (10**n)-1
        return randint(range_start, range_end)

    def randomletter(self, n):
        letters = []
        for x in range(0, n):
            letters.append(random.choice(string.ascii_letters))
        return "".join(letters)

    def randomnumberplay(self, help, iterations):
        random = self.randomnumber(iterations)
        self.message("Seccion de Prueba de Numeros Aleatorios")
        for x in str(random):
            if not help:
                self.morse.generate(x)
                self.message("El numero codificado fue, " + x + ", " + " ".join(self.phonetic.decode(x)))
            if help:
                self.message("El numero, " + x + ", " + " ".join(self.phonetic.decode(x)) + "codificado es, ")
                self.morse.generate(x)
            time.sleep(1)

    def randomletterplay(self, help, iterations):
        random = self.randomletter(iterations)
        self.message("Seccion de Prueba de Letras Aleatorias")
        for x in str(random):
            if not help:
                self.morse.generate(x)
                self.message("La letra codificada fue, " + x + ", " + " ".join(self.phonetic.decode(x)))
            if help:
                self.message("La letra, " + x + ", de " + " ".join(self.phonetic.decode(x)) + "codificada es, ")
                self.morse.generate(x)
            time.sleep(1)

    def golearn(self):
        print '[Cancun] Morse Teacher Learning'
        self.welcome()
        self.randomnumberplay(True, 5)
        self.randomnumberplay(False, 5)
        self.message("Hagamos una pausa de 10 segundos")
        time.sleep(10)
        self.randomletterplay(True, 5)
        self.randomletterplay(False, 5)

    def gocompete(self):
        print '[Cancun] Morse Teacher Contest'
        self.message("Concurso Decodificando Texto")
        self.message("Envia tus resultados a " + " ".join(self.phonetic.decode('xe1gyq@gmail.com')))
        self.message("El primer correo con el texto correcto sera ganador de una tarjeta de 200 pesos para Star Bucks")
        self.message("Listo? Comenzamos...")
        file = open('learning/morsecontest.text')
        for line in file.readlines():
            self.morse.generate(''.join(e for e in line if e.isalnum()))
        return

    def goask(self):
        print '[Cancun] Morse Teacher Ask'
        self.message("Aprendizaje de Codigo Morse")
        self.message("Quieres escuchar 2 letras para que las decodifiques?")
        self.message("Responde con las palabras afirmativo o negativo en los proximos 5 segundos")

        self.command.record("google")
        output = self.command.decode("google")

        if re.search(r'afirma', output, re.M|re.I):
                print 'afirma'
                self.message("Tu respuesta fue afirmativa")
                self.randomletterplay(True, 2)
        elif re.search(r'nega', output, re.M|re.I):
                print 'nel pastel'
                self.message("Tu respuesta fue negativa ")
        else:
                self.message("No entendimos tu respuesta")
        self.message("Hasta Pronto")

if __name__ == '__main__':

    mymorse = MorseTeacher()
    mymorse.golearn()
    mymorse.gocompete()
<commit_msg>Learning: Morse Voice Command<commit_after>#!/usr/bin/python

import random
import re
import string
import sys
import time

from random import randint

from core.morse import Morse
from core.phonetic import Phonetic
from core.voicecommand import VoiceCommand
from core.voicesynthetizer import VoiceSynthetizer

class MorseTeacher(object):

    def __init__(self, voicesynthetizer):

        self.morse = Morse()
        self.speaker = voicesynthetizer
        self.phonetic = Phonetic()
        self.voicecommand = VoiceCommand(voicesynthetizer)

    def __del__(self):
        pass

    def message(self, message):
        self.speaker.speechit(message)

    def welcome(self):
        self.message("Modulo de Aprendizaje de Codigo Morse, sugerencias escribir a ")
        self.message(" ".join(self.phonetic.decode('xe1gyq@gmail.com')))

    def randomnumber(self, n):
        range_start = 10**(n-1)
        range_end = (10**n)-1
        return randint(range_start, range_end)

    def randomletter(self, n):
        letters = []
        for x in range(0, n):
            letters.append(random.choice(string.ascii_letters))
        return "".join(letters)

    def randomnumberplay(self, help, iterations):
        random = self.randomnumber(iterations)
        self.message("Seccion de Prueba de Numeros Aleatorios")
        for x in str(random):
            if not help:
                self.morse.generate(x)
                self.message("El numero codificado fue, " + x + ", " + " ".join(self.phonetic.decode(x)))
            if help:
                self.message("El numero, " + x + ", " + " ".join(self.phonetic.decode(x)) + "codificado es, ")
                self.morse.generate(x)
            time.sleep(1)

    def randomletterplay(self, help, iterations):
        random = self.randomletter(iterations)
        self.message("Seccion de Prueba de Letras Aleatorias")
        for x in str(random):
            if not help:
                self.morse.generate(x)
                self.message("La letra codificada fue, " + x + ", " + " ".join(self.phonetic.decode(x)))
            if help:
                self.message("La letra, " + x + ", de " + " ".join(self.phonetic.decode(x)) + "codificada es, ")
                self.morse.generate(x)
            time.sleep(1)

    def golearn(self):
        print '[Cancun] Morse Teacher Learning'
        self.welcome()
        self.randomnumberplay(True, 5)
        self.randomnumberplay(False, 5)
        self.message("Hagamos una pausa de 10 segundos")
        time.sleep(10)
        self.randomletterplay(True, 5)
        self.randomletterplay(False, 5)

    def gocompete(self):
        print '[Cancun] Morse Teacher Contest'
        self.message("Concurso Decodificando Texto")
        self.message("Envia tus resultados a " + " ".join(self.phonetic.decode('xe1gyq@gmail.com')))
        self.message("El primer correo con el texto correcto sera ganador de una tarjeta de 200 pesos para Star Bucks")
        self.message("Listo? Comenzamos...")
        file = open('learning/morsecontest.text')
        for line in file.readlines():
            self.morse.generate(''.join(e for e in line if e.isalnum()))
        return

    def goask(self):
        print '[Cancun] Morse Teacher Ask'
        self.message("Aprendizaje de Codigo Morse")
        self.message("Quieres escuchar 2 letras para que las decodifiques?")
        self.message("Responde con las palabras afirmativo o negativo en los proximos 5 segundos")

        self.voicecommand.record()
        output = self.voicecommand.decode()

        if re.search(r'afirma', output, re.M|re.I):
                self.message("Tu respuesta fue afirmativa")
                self.randomletterplay(True, 2)
        elif re.search(r'nega', output, re.M|re.I):
                self.message("Tu respuesta fue negativa ")
        else:
                self.message("No entendimos tu respuesta")
        self.message("Hasta Pronto!")

if __name__ == '__main__':

    mymorse = MorseTeacher()
    mymorse.golearn()
    mymorse.gocompete()
<|endoftext|>