<commit_before># Copyright 2022 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     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.
"""TensorAudio class."""

import numpy as np

from tensorflow_lite_support.python.task.audio.core.pybinds import _pywrap_audio_buffer
from tensorflow_lite_support.python.task.audio.core import audio_record

_CppAudioBuffer = _pywrap_audio_buffer.AudioBuffer
_CppAudioFormat = _pywrap_audio_buffer.AudioFormat
_LoadAudioBufferFromFile = _pywrap_audio_buffer.LoadAudioBufferFromFile

class TensorAudio(object):
  """A wrapper class to store the input audio."""

  def __init__(self,
               audio_format: _CppAudioFormat,
               sample_count: int,
               audio_data: _CppAudioBuffer = None,
               is_from_file: bool = False,
               ) -> None:
    """Initializes the `TensorAudio` object.

    Args:
      audio_format: C++ AudioFormat object, format of the audio.
      sample_count: int, number of samples in the audio.
      audio_data: C++ AudioBuffer object, contains raw audio data, buffer size
      and audio format info.
      is_from_file: boolean, whether `audio_data` is loaded from the audio file.
    """
    self._format = audio_format
    self._sample_count = sample_count
    self._is_from_file = is_from_file

    if self._is_from_file:
      self._data = audio_data
    else:
      self._buffer = np.zeros(
        [self._sample_count, self._format.channels], dtype=np.float32)

  def clear(self):
    """Clear the internal buffer and fill it with zeros."""
    self._buffer.fill(0)

  @classmethod
  def create_from_wav_file(cls,
                    file_name: str,
                    buffer_size: int) -> "TensorAudio":
    """Creates `TensorAudio` object from the WAV file.

    Args:
      file_name: WAV file name.
      buffer_size: Required input buffer size.

    Returns:
      `TensorAudio` object.

    Raises:
      status.StatusNotOk if the audio file can't be decoded. Need to import
        the module to catch this error: `from pybind11_abseil import status`,
        see https://github.com/pybind/pybind11_abseil#abslstatusor.
    """
    audio = _LoadAudioBufferFromFile(
      file_name, buffer_size, np.zeros([buffer_size]))
    return cls(audio.audio_format, audio.buffer_size, audio, is_from_file=True)

  def load_from_audio_record(self, record: audio_record.AudioRecord) -> None:
    """Loads audio data from an AudioRecord instance.
    Args:
      record: An AudioRecord instance.
    Raises:
      ValueError: Raised if the audio record's config is invalid.
    """
    if record.buffer_size < self._sample_count:
      raise ValueError(
        "The audio record's buffer size cannot be smaller than the tensor "
        "audio's sample count.")

    if record.channels != self._format.channels:
      raise ValueError(
        f"The audio record's channel count doesn't match. "
        f"Expects {self._format.channels} channel(s).")

    if record.sampling_rate != self._format.sample_rate:
      raise ValueError(
        f"The audio record's sampling rate doesn't match. "
        f"Expects {self._format.sample_rate}Hz.")

    # Load audio data from the AudioRecord instance.
    data = record.read(self._sample_count)
    self.load_from_array(data.astype(np.float32))

  def load_from_array(self, src: np.ndarray) -> None:
    """Loads audio data from a NumPy array.

    Args:
      src: A NumPy array contains the input audio.

    Raises:
      ValueError if the input audio is too large or if it contains an invalid
      number of channels.
    """
    if len(src) != len(self._buffer):
      raise ValueError(
        f"Input audio contains an invalid number of samples. "
        f"Expect {len(self._buffer)}.")
    elif src.shape[1] != self._format.channels:
      raise ValueError(
        f"Input audio contains an invalid number of channels. "
        f"Expect {self._format.channels}.")

    self._buffer = src

  @property
  def format(self) -> _CppAudioFormat:
    """Gets the audio format of the audio."""
    return self._format

  @property
  def sample_count(self) -> int:
    """Gets the sample count of the audio."""
    return self._sample_count

  @property
  def data(self) -> _CppAudioBuffer:
    """Gets the C++ AudioBuffer object."""
    if self._is_from_file:
      audio_data = self._data
    else:
      audio_data = _CppAudioBuffer(
        self._buffer, self._sample_count, self._format)
    return audio_data
<commit_msg>Fixed code indents<commit_after># Copyright 2022 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     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.
"""TensorAudio class."""

import numpy as np

from tensorflow_lite_support.python.task.audio.core.pybinds import _pywrap_audio_buffer
from tensorflow_lite_support.python.task.audio.core import audio_record

_CppAudioBuffer = _pywrap_audio_buffer.AudioBuffer
_CppAudioFormat = _pywrap_audio_buffer.AudioFormat
_LoadAudioBufferFromFile = _pywrap_audio_buffer.LoadAudioBufferFromFile

class TensorAudio(object):
  """A wrapper class to store the input audio."""

  def __init__(self,
               audio_format: _CppAudioFormat,
               sample_count: int,
               audio_data: _CppAudioBuffer = None,
               is_from_file: bool = False,
               ) -> None:
    """Initializes the `TensorAudio` object.

    Args:
      audio_format: C++ AudioFormat object, format of the audio.
      sample_count: int, number of samples in the audio.
      audio_data: C++ AudioBuffer object, contains raw audio data, buffer size
      and audio format info.
      is_from_file: boolean, whether `audio_data` is loaded from the audio file.
    """
    self._format = audio_format
    self._sample_count = sample_count
    self._is_from_file = is_from_file

    if self._is_from_file:
      self._data = audio_data
    else:
      self._buffer = np.zeros(
        [self._sample_count, self._format.channels], dtype=np.float32)

  def clear(self):
    """Clear the internal buffer and fill it with zeros."""
    self._buffer.fill(0)

  @classmethod
  def create_from_wav_file(cls,
                           file_name: str,
                           buffer_size: int) -> "TensorAudio":
    """Creates `TensorAudio` object from the WAV file.

    Args:
      file_name: WAV file name.
      buffer_size: Required input buffer size.

    Returns:
      `TensorAudio` object.

    Raises:
      status.StatusNotOk if the audio file can't be decoded. Need to import
        the module to catch this error: `from pybind11_abseil import status`,
        see https://github.com/pybind/pybind11_abseil#abslstatusor.
    """
    audio = _LoadAudioBufferFromFile(
      file_name, buffer_size, np.zeros([buffer_size]))
    return cls(audio.audio_format, audio.buffer_size, audio, is_from_file=True)

  def load_from_audio_record(self, record: audio_record.AudioRecord) -> None:
    """Loads audio data from an AudioRecord instance.
    Args:
      record: An AudioRecord instance.
    Raises:
      ValueError: Raised if the audio record's config is invalid.
    """
    if record.buffer_size < self._sample_count:
      raise ValueError(
        "The audio record's buffer size cannot be smaller than the tensor "
        "audio's sample count.")

    if record.channels != self._format.channels:
      raise ValueError(
        f"The audio record's channel count doesn't match. "
        f"Expects {self._format.channels} channel(s).")

    if record.sampling_rate != self._format.sample_rate:
      raise ValueError(
        f"The audio record's sampling rate doesn't match. "
        f"Expects {self._format.sample_rate}Hz.")

    # Load audio data from the AudioRecord instance.
    data = record.read(self._sample_count)
    self.load_from_array(data.astype(np.float32))

  def load_from_array(self, src: np.ndarray) -> None:
    """Loads audio data from a NumPy array.

    Args:
      src: A NumPy array contains the input audio.

    Raises:
      ValueError if the input audio is too large or if it contains an invalid
      number of channels.
    """
    if len(src) != len(self._buffer):
      raise ValueError(
        f"Input audio contains an invalid number of samples. "
        f"Expect {len(self._buffer)}.")
    elif src.shape[1] != self._format.channels:
      raise ValueError(
        f"Input audio contains an invalid number of channels. "
        f"Expect {self._format.channels}.")

    self._buffer = src

  @property
  def format(self) -> _CppAudioFormat:
    """Gets the audio format of the audio."""
    return self._format

  @property
  def sample_count(self) -> int:
    """Gets the sample count of the audio."""
    return self._sample_count

  @property
  def data(self) -> _CppAudioBuffer:
    """Gets the C++ AudioBuffer object."""
    if self._is_from_file:
      audio_data = self._data
    else:
      audio_data = _CppAudioBuffer(
        self._buffer, self._sample_count, self._format)
    return audio_data
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2014 Abstract (http://www.abstract.it)
#    @author Davide Corio <davide.corio@abstract.it>
#    Copyright (C) 2014 Agile Business Group (http://www.agilebg.com)
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import logging
from openerp import fields
from openerp import models
from openerp import api
from openerp import _
from openerp.exceptions import Warning
from openerp.osv import osv
from datetime import datetime, timedelta
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class StockPickingCarriageCondition(models.Model):

    _name = "stock.picking.carriage_condition"
    _description = "Carriage Condition"

    name = fields.Char(string='Carriage Condition', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockPickingGoodsDescription(models.Model):

    _name = 'stock.picking.goods_description'
    _description = "Description of Goods"

    name = fields.Char(string='Description of Goods', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockPickingTransportationReason(models.Model):

    _name = 'stock.picking.transportation_reason'
    _description = 'Reason for Transportation'

    name = fields.Char(string='Reason For Transportation', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockPickingTransportationMethod(models.Model):

    _name = 'stock.picking.transportation_method'
    _description = 'Method of Transportation'

    name = fields.Char(string='Method of Transportation', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockMove(models.Model):
    _inherit = "stock.move"

    ddt_id = fields.Many2one('stock.ddt', ondelete="set null")

class StockDdT(models.Model):

    _name = 'stock.ddt'
    _description = 'DdT'

    # -------------------------------------------------------------------------
    # Button event:
    # -------------------------------------------------------------------------
    @api.one
    def set_not_invoiced_true(self):
        self.write({'not_invoiced': True})

    @api.one
    def set_not_invoiced_false(self):
        self.write({'not_invoiced': False})

    @api.multi
    def get_sequence(self):
        # XXX: allow config of default seq per company
        return self.env['ir.sequence'].search(
            [('code', '=', 'stock.ddt')])[0].id

    name = fields.Char(string='Number')
    date = fields.Datetime(
        required=True,
        #default=fields.Datetime.now(),
        default=datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
        )
    delivery_date = fields.Datetime()
    sequence = fields.Many2one(
        'ir.sequence', string='Sequence',
        default=get_sequence, required=True)
    picking_ids = fields.One2many(
        'stock.picking', 'ddt_id', string='Pickings', readonly=True)
    ddt_lines = fields.One2many(
        'stock.move', 'ddt_id', string='DdT Line', readonly=True,
        compute='_get_lines')
    invoice_id = fields.Many2one(
        'account.invoice', string='Invoice', required=False)
    not_invoiced = fields.Boolean('Not invoiced')
    partner_id = fields.Many2one(
        'res.partner', string='Partner', required=True)
    delivery_address_id = fields.Many2one(
        'res.partner', string='Delivery Address', required=False)
    carriage_condition_id = fields.Many2one(
        'stock.picking.carriage_condition', 'Carriage Condition')
    goods_description_id = fields.Many2one(
        'stock.picking.goods_description', 'Description of Goods')
    transportation_reason_id = fields.Many2one(
        'stock.picking.transportation_reason',
        'Reason for Transportation')
    transportation_method_id = fields.Many2one(
        'stock.picking.transportation_method',
        'Method of Transportation')
    carrier_id = fields.Many2one(
        'res.partner', string='Carrier')
    parcels = fields.Integer()
    note = fields.Text('Note')
    state = fields.Selection(
        [('draft', 'Draft'),
         ('confirmed', 'Confirmed'),
         ('cancelled', 'Cancelled')],
        string='State',
        default='draft'
    )

    def _get_lines(self):
        for ddt in self:
            for picking in ddt.picking_ids:
                ddt.ddt_lines += picking.move_lines

    @api.multi
    def set_number(self):
        for ddt in self:
            if not ddt.name:
                ddt.write({
                    'name': ddt.sequence.get(ddt.sequence.code),
                })

    @api.multi
    def action_confirm(self):
        self.write({'state': 'confirmed'})

    @api.multi
    def action_cancel(self):
        self.write({'state': 'cancelled'})

    @api.multi
    def action_reopen(self):
        self.write({'state': 'draft'})
        self.delete_workflow()
        self.create_workflow()
        return True

    @api.multi
    def name_get(self):
        result = []
        for ddt in self:
            result.append((ddt.id, "%s" % (ddt.name or 'N/A')))
        return result

class StockPicking(models.Model):

    _inherit = "stock.picking"

    carriage_condition_id = fields.Many2one(
        'stock.picking.carriage_condition', string='Carriage Condition')
    goods_description_id = fields.Many2one(
        'stock.picking.goods_description', string='Description of Goods')
    transportation_reason_id = fields.Many2one(
        'stock.picking.transportation_reason',
        string='Reason for Transportation')
    transportation_method_id = fields.Many2one(
        'stock.picking.transportation_method',
        string='Method of Transportation')
    parcels = fields.Integer()
    ddt_id = fields.Many2one('stock.ddt', string='DdT')
    ddt_type = fields.Selection(
        string="DdT Type", related='picking_type_id.code')
    #invoice_id = fields.Many2one('account.invoice', string="Invoice",
    #    related='ddt_id.invoice_id', store=False, readonly=True)
    invoice_id = fields.Many2one('account.invoice', string='Direct invoice')

    def action_invoice_create(
            self, cr, uid, ids, journal_id, group=False, type='out_invoice',
            context=None):
        ''' Action for create invoice from pickings (or DDT > pick > invoice)
            Note: Inherit Append DDT extra data
        '''
        if not context:
            context = {}
        invoice_obj = self.pool['account.invoice']
        res = super(StockPicking, self).action_invoice_create(
            cr, uid, ids, journal_id, group, type, context)

        # TODO Use only first element?
        note_pre = ''
        note_pre_list = []
        note_post = ''
        note_post_list = []
        destination_partner_id = False
        for picking in self.browse(cr, uid, ids, context=context):
            # Pre pick + DDT (if exist)
            pre_all = (picking.ddt_text_note_pre or '').strip() or (
                picking.text_note_pre or '').strip()
            if pre_all and pre_all not in note_pre_list:
                note_pre += '%s\n' % pre_all
                note_pre_list.append(pre_all)

            # Post pick + DDT (if exist)
            post_all = (picking.ddt_text_note_post or '').strip() or (
                picking.text_note_post or '').strip()
            if post_all and post_all not in note_post_list:
                note_post += '%s\n' % post_all
                note_post_list.append(post_all)

            # TODO remove from middle of the loop and check that are all
            # equals!!!
            if not destination_partner_id and picking.destination_partner_id:
                destination_partner_id = picking.destination_partner_id.id
            if destination_partner_id != picking.destination_partner_id.id:
                raise osv.except_osv(_('Error'), _('Different destination!'))
            invoice_obj.write(cr, uid, res, {
                # DDT fields:
                'destination_partner_id':
                picking.destination_partner_id and
                picking.destination_partner_id.id,
                #TODO invoice?!?!
                'carriage_condition_id':
                picking.carriage_condition_id and
                picking.carriage_condition_id.id,
                'goods_description_id':
                picking.goods_description_id and
                picking.goods_description_id.id,
                'transportation_reason_id':
                picking.transportation_reason_id and
                picking.transportation_reason_id.id,
                'transportation_method_id':
                picking.transportation_method_id and
                picking.transportation_method_id.id,
                'parcels': picking.parcels,
            })
        invoice_obj.write(cr, uid, res, {
            'text_note_pre': note_pre,
            'text_note_post': note_post,
            })
        return res
<commit_msg>fast git<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Copyright (C) 2014 Abstract (http://www.abstract.it)
#    @author Davide Corio <davide.corio@abstract.it>
#    Copyright (C) 2014 Agile Business Group (http://www.agilebg.com)
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    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 General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import logging
from openerp import fields
from openerp import models
from openerp import api
from openerp import _
from openerp.exceptions import Warning
from openerp.osv import osv
from datetime import datetime, timedelta
from openerp.tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class StockPickingCarriageCondition(models.Model):

    _name = "stock.picking.carriage_condition"
    _description = "Carriage Condition"

    name = fields.Char(string='Carriage Condition', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockPickingGoodsDescription(models.Model):

    _name = 'stock.picking.goods_description'
    _description = "Description of Goods"

    name = fields.Char(string='Description of Goods', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockPickingTransportationReason(models.Model):

    _name = 'stock.picking.transportation_reason'
    _description = 'Reason for Transportation'

    name = fields.Char(string='Reason For Transportation', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockPickingTransportationMethod(models.Model):

    _name = 'stock.picking.transportation_method'
    _description = 'Method of Transportation'

    name = fields.Char(string='Method of Transportation', required=True,
       translate=True)
    note = fields.Text(string='Note')

class StockMove(models.Model):
    _inherit = "stock.move"

    ddt_id = fields.Many2one('stock.ddt', ondelete="set null")

class StockDdT(models.Model):

    _name = 'stock.ddt'
    _description = 'DdT'

    # -------------------------------------------------------------------------
    # Button event:
    # -------------------------------------------------------------------------
    @api.one
    def set_not_invoiced_true(self):
        self.write({'not_invoiced': True})

    @api.one
    def set_not_invoiced_false(self):
        self.write({'not_invoiced': False})

    # -------------------------------------------------------------------------
    # Utility:
    # -------------------------------------------------------------------------
    @api.multi
    def get_sequence(self):
        # XXX: allow config of default seq per company
        return self.env['ir.sequence'].search(
            [('code', '=', 'stock.ddt')])[0].id

    name = fields.Char(string='Number')
    date = fields.Datetime(
        required=True,
        #default=fields.Datetime.now(),
        default=datetime.now().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
        )
    delivery_date = fields.Datetime()
    sequence = fields.Many2one(
        'ir.sequence', string='Sequence',
        default=get_sequence, required=True)
    picking_ids = fields.One2many(
        'stock.picking', 'ddt_id', string='Pickings', readonly=True)
    ddt_lines = fields.One2many(
        'stock.move', 'ddt_id', string='DdT Line', readonly=True,
        compute='_get_lines')
    invoice_id = fields.Many2one(
        'account.invoice', string='Invoice', required=False)
    not_invoiced = fields.Boolean('Not invoiced')
    partner_id = fields.Many2one(
        'res.partner', string='Partner', required=True)
    delivery_address_id = fields.Many2one(
        'res.partner', string='Delivery Address', required=False)
    carriage_condition_id = fields.Many2one(
        'stock.picking.carriage_condition', 'Carriage Condition')
    goods_description_id = fields.Many2one(
        'stock.picking.goods_description', 'Description of Goods')
    transportation_reason_id = fields.Many2one(
        'stock.picking.transportation_reason',
        'Reason for Transportation')
    transportation_method_id = fields.Many2one(
        'stock.picking.transportation_method',
        'Method of Transportation')
    carrier_id = fields.Many2one(
        'res.partner', string='Carrier')
    parcels = fields.Integer()
    note = fields.Text('Note')
    state = fields.Selection(
        [('draft', 'Draft'),
         ('confirmed', 'Confirmed'),
         ('cancelled', 'Cancelled')],
        string='State',
        default='draft'
    )

    def _get_lines(self):
        for ddt in self:
            for picking in ddt.picking_ids:
                ddt.ddt_lines += picking.move_lines

    @api.multi
    def set_number(self):
        for ddt in self:
            if not ddt.name:
                ddt.write({
                    'name': ddt.sequence.get(ddt.sequence.code),
                })

    @api.multi
    def action_confirm(self):
        self.write({'state': 'confirmed'})

    @api.multi
    def action_cancel(self):
        self.write({'state': 'cancelled'})

    @api.multi
    def action_reopen(self):
        self.write({'state': 'draft'})
        self.delete_workflow()
        self.create_workflow()
        return True

    @api.multi
    def name_get(self):
        result = []
        for ddt in self:
            result.append((ddt.id, "%s" % (ddt.name or 'N/A')))
        return result

class StockPicking(models.Model):

    _inherit = "stock.picking"

    carriage_condition_id = fields.Many2one(
        'stock.picking.carriage_condition', string='Carriage Condition')
    goods_description_id = fields.Many2one(
        'stock.picking.goods_description', string='Description of Goods')
    transportation_reason_id = fields.Many2one(
        'stock.picking.transportation_reason',
        string='Reason for Transportation')
    transportation_method_id = fields.Many2one(
        'stock.picking.transportation_method',
        string='Method of Transportation')
    parcels = fields.Integer()
    ddt_id = fields.Many2one('stock.ddt', string='DdT')
    ddt_type = fields.Selection(
        string="DdT Type", related='picking_type_id.code')
    #invoice_id = fields.Many2one('account.invoice', string="Invoice",
    #    related='ddt_id.invoice_id', store=False, readonly=True)
    invoice_id = fields.Many2one('account.invoice', string='Direct invoice')

    def action_invoice_create(
            self, cr, uid, ids, journal_id, group=False, type='out_invoice',
            context=None):
        ''' Action for create invoice from pickings (or DDT > pick > invoice)
            Note: Inherit Append DDT extra data
        '''
        if not context:
            context = {}
        invoice_obj = self.pool['account.invoice']
        res = super(StockPicking, self).action_invoice_create(
            cr, uid, ids, journal_id, group, type, context)

        # TODO Use only first element?
        note_pre = ''
        note_pre_list = []
        note_post = ''
        note_post_list = []
        destination_partner_id = False
        for picking in self.browse(cr, uid, ids, context=context):
            # Pre pick + DDT (if exist)
            pre_all = (picking.ddt_text_note_pre or '').strip() or (
                picking.text_note_pre or '').strip()
            if pre_all and pre_all not in note_pre_list:
                note_pre += '%s\n' % pre_all
                note_pre_list.append(pre_all)

            # Post pick + DDT (if exist)
            post_all = (picking.ddt_text_note_post or '').strip() or (
                picking.text_note_post or '').strip()
            if post_all and post_all not in note_post_list:
                note_post += '%s\n' % post_all
                note_post_list.append(post_all)

            # TODO remove from middle of the loop and check that are all
            # equals!!!
            if not destination_partner_id and picking.destination_partner_id:
                destination_partner_id = picking.destination_partner_id.id
            if destination_partner_id != picking.destination_partner_id.id:
                raise osv.except_osv(_('Error'), _('Different destination!'))
            invoice_obj.write(cr, uid, res, {
                # DDT fields:
                'destination_partner_id':
                picking.destination_partner_id and
                picking.destination_partner_id.id,
                #TODO invoice?!?!
                'carriage_condition_id':
                picking.carriage_condition_id and
                picking.carriage_condition_id.id,
                'goods_description_id':
                picking.goods_description_id and
                picking.goods_description_id.id,
                'transportation_reason_id':
                picking.transportation_reason_id and
                picking.transportation_reason_id.id,
                'transportation_method_id':
                picking.transportation_method_id and
                picking.transportation_method_id.id,
                'parcels': picking.parcels,
            })
        invoice_obj.write(cr, uid, res, {
            'text_note_pre': note_pre,
            'text_note_post': note_post,
            })
        return res
<|endoftext|>


<commit_before>"""General decorators for the landlab library.

General Landlab decorators
++++++++++++++++++++++++++

.. autosummary::
    :toctree: generated/

    ~landlab.utils.decorators.use_file_name_or_kwds
    ~landlab.utils.decorators.use_field_name_or_array
    ~landlab.utils.decorators.make_return_array_immutable
    ~landlab.utils.decorators.deprecated
"""

import os
import warnings
from functools import wraps
import textwrap

import numpy as np
import six

from ..core.model_parameter_loader import load_params

class store_result_in_grid(object):
    def __init__(self, name=None):
        self._attr = name

    def __call__(self, func):
        @wraps(func)
        def _wrapped(grid):
            name = self._attr or '_' + func.__name__
            try:
                getattr(grid, name)
            except AttributeError:
                setattr(grid, name, func(grid))
            finally:
                return getattr(grid, name)

        return _wrapped

def read_only_array(func):
    """Decorate a function so that its return array is read-only.

    Parameters
    ----------
    func : function
        A function that returns a numpy array.

    Returns
    -------
    func
        A wrapped function that returns a read-only numpy array.
    """
    @wraps(func)
    def _wrapped(self, *args, **kwds):
        """Make the returned array read-only."""
        array = func(self, *args, **kwds)
        array.flags.writeable = False
        return array
    return _wrapped

def use_file_name_or_kwds(func):

    """Decorate a method so that it takes a file name or keywords.

    Parameters
    ----------
    func : A function
        A method function that accepts a ModelGrid as a first argument.

    Returns
    -------
    function
        A function that takes an optional second argument, a file, from which
        to read keywords.

    Examples
    --------
    >>> from landlab import RasterModelGrid
    >>> from landlab.utils.decorators import use_file_name_or_kwds

    >>> class MyClass(object):
    ...     @use_file_name_or_kwds
    ...     def __init__(self, grid, kw=0.):
    ...         self.kw = kw

    >>> grid = RasterModelGrid((4, 5))
    >>> foo = MyClass(grid)
    >>> foo.kw
    0.0

    >>> foo = MyClass(grid, "kw: 1945")
    >>> foo.kw
    1945
    >>> foo = MyClass(grid, "kw: 1945", kw=1973)
    >>> foo.kw
    1973

    >>> mpd = \"\"\"
    ... kw: kw value
    ... 1e6
    ... \"\"\"
    >>> foo = MyClass(grid, mpd)
    >>> foo.kw
    1000000.0
    """

    @wraps(func)
    def _wrapped(self, *args, **kwds):
        from ..grid import ModelGrid

        if not isinstance(args[0], ModelGrid):
            raise ValueError('first argument must be a ModelGrid')

        if len(args) == 2:
            warnings.warn(
                "Passing a file to a component's __init__ method is "
                "deprecated. Instead, pass parameters as keywords.",
                category=DeprecationWarning)

            if os.path.isfile(args[1]):
                with open(args[1], 'r') as fp:
                    params = load_params(fp)
            else:
                params = load_params(args[1])
        else:
            params = {}

        params.update(kwds)

        func(self, args[0], **params)

    return _wrapped

class use_field_name_or_array(object):

    """Decorate a function so that it accepts a field name or array.

    Parameters
    ----------
    func : function
        A function that accepts a grid and array as arguments.
    at_element : str
        The element type that the field is defined on ('node', 'cell',
        etc.)

    Returns
    -------
    func
        A wrapped function that accepts a grid and either a field name or
        a numpy array.

    Examples
    --------
    >>> from landlab import RasterModelGrid
    >>> grid = RasterModelGrid((4, 5), spacing=(1, 2))

    >>> def my_func(grid, vals):
    ...     return grid.area_of_cell * vals
    >>> my_func(grid, np.arange(grid.number_of_cells))
    array([  0.,   2.,   4.,   6.,   8.,  10.])

    Decorate the function so that the second argument can be array-like or
    the name of a field contained withing the grid. The decorator takes a
    single argument that is the name (as a `str`) of the grid element that
    the values are defined on ("node", "cell", etc.).

    >>> from landlab.utils.decorators import use_field_name_or_array
    >>> @use_field_name_or_array('cell')
    ... def my_func(grid, vals):
    ...     return grid.area_of_cell * vals

    The array of values now can be list or anything that can be converted to
    a numpy array.

    >>> my_func(grid, [0, 1, 2, 3, 4, 5])
    array([  0.,   2.,   4.,   6.,   8.,  10.])

    The array of values doesn't have to be flat.

    >>> vals = np.array([[0, 1, 2], [3, 4, 5]])
    >>> my_func(grid, vals)
    array([  0.,   2.,   4.,   6.,   8.,  10.])

    The array of values can be a field name.

    >>> _ = grid.add_field('cell', 'elevation', [0, 1, 2, 3, 4, 5])
    >>> my_func(grid, 'elevation')
    array([  0.,   2.,   4.,   6.,   8.,  10.])
    """

    def __init__(self, at_element):
        """Initialize the decorator.

        Parameters
        ----------
        at_element : str
            The element type that the field is defined on ('node', 'cell',
            etc.)
        """
        self._at = at_element

    def __call__(self, func):
        """Wrap the function."""
        @wraps(func)
        def _wrapped(grid, vals, *args, **kwds):
            """Convert the second argument to an array."""
            if isinstance(vals, six.string_types):
                vals = grid[self._at][vals]
            else:
                vals = np.asarray(vals).flatten()

            return func(grid, vals, *args, **kwds)
        return _wrapped

def make_return_array_immutable(func):
    """Decorate a function so that its return array is read-only.

    Parameters
    ----------
    func : function
        A function that returns a numpy array.

    Returns
    -------
    func
        A wrapped function that returns a read-only view of an array.
    """
    @wraps(func)
    def _wrapped(self, *args, **kwds):
        """Make the returned array read-only."""
        array = func(self, *args, **kwds)
        immutable_array = array.view()
        immutable_array.flags.writeable = False
        return immutable_array
    return _wrapped

# def deprecated(use, version):
#     """Mark a function as deprecated.
#
#     Parameters
#     ----------
#     use : str
#         Name of replacement function to use.
#     version : str
#         Version number when function was marked as deprecated.
#
#     Returns
#     -------
#     func
#         A wrapped function that issues a deprecation warning.
#     """
#     def real_decorator(func):
#
#         def _wrapped(*args, **kwargs):
#             """Warn that the function is deprecated before calling it."""
#             warnings.warn(
#                 "Call to deprecated function {name}.".format(
#                     name=func.__name__), category=DeprecationWarning)
#             return func(*args, **kwargs)
#         _wrapped.__dict__.update(func.__dict__)
#
#         return _wrapped
#
#     return real_decorator

def deprecated(use, version):
    """Mark a function as deprecated.

    Parameters
    ----------
    use : str
        Name of replacement function to use.
    version : str
        Version number when function was marked as deprecated.

    Returns
    -------
    func
        A wrapped function that issues a deprecation warning.
    """
    def real_decorator(func):
        warning_str = """
.. note:: This method is deprecated as of Landlab version {ver}.

    Use :func:`{use}` instead.

""".format(ver=version, use=use)

        doc_lines = (func.__doc__ or "").split(os.linesep)

        for lineno, line in enumerate(doc_lines):
            if len(line.rstrip()) == 0:
                break

        head = doc_lines[:lineno]
        body = doc_lines[lineno:]

        head = textwrap.dedent(os.linesep.join(head))
        body = textwrap.dedent(os.linesep.join(body))

        func.__doc__ = os.linesep.join([head, warning_str, body])

        @wraps(func)
        def _wrapped(*args, **kwargs):
            if func.__name__.startswith('_'):
                pass
            else:
                warnings.warn(
                    message="Call to deprecated function {name}.".format(
                        name=func.__name__), category=DeprecationWarning)
            return func(*args, **kwargs)
        _wrapped.__dict__.update(func.__dict__)

        return _wrapped

    return real_decorator
<commit_msg>Minor change to @use_field_name_or_array to check the size of the array<commit_after>"""General decorators for the landlab library.

General Landlab decorators
++++++++++++++++++++++++++

.. autosummary::
    :toctree: generated/

    ~landlab.utils.decorators.use_file_name_or_kwds
    ~landlab.utils.decorators.use_field_name_or_array
    ~landlab.utils.decorators.make_return_array_immutable
    ~landlab.utils.decorators.deprecated
"""

import os
import warnings
from functools import wraps
import textwrap

import numpy as np
import six

from ..core.model_parameter_loader import load_params

class store_result_in_grid(object):
    def __init__(self, name=None):
        self._attr = name

    def __call__(self, func):
        @wraps(func)
        def _wrapped(grid):
            name = self._attr or '_' + func.__name__
            try:
                getattr(grid, name)
            except AttributeError:
                setattr(grid, name, func(grid))
            finally:
                return getattr(grid, name)

        return _wrapped

def read_only_array(func):
    """Decorate a function so that its return array is read-only.

    Parameters
    ----------
    func : function
        A function that returns a numpy array.

    Returns
    -------
    func
        A wrapped function that returns a read-only numpy array.
    """
    @wraps(func)
    def _wrapped(self, *args, **kwds):
        """Make the returned array read-only."""
        array = func(self, *args, **kwds)
        array.flags.writeable = False
        return array
    return _wrapped

def use_file_name_or_kwds(func):

    """Decorate a method so that it takes a file name or keywords.

    Parameters
    ----------
    func : A function
        A method function that accepts a ModelGrid as a first argument.

    Returns
    -------
    function
        A function that takes an optional second argument, a file, from which
        to read keywords.

    Examples
    --------
    >>> from landlab import RasterModelGrid
    >>> from landlab.utils.decorators import use_file_name_or_kwds

    >>> class MyClass(object):
    ...     @use_file_name_or_kwds
    ...     def __init__(self, grid, kw=0.):
    ...         self.kw = kw

    >>> grid = RasterModelGrid((4, 5))
    >>> foo = MyClass(grid)
    >>> foo.kw
    0.0

    >>> foo = MyClass(grid, "kw: 1945")
    >>> foo.kw
    1945
    >>> foo = MyClass(grid, "kw: 1945", kw=1973)
    >>> foo.kw
    1973

    >>> mpd = \"\"\"
    ... kw: kw value
    ... 1e6
    ... \"\"\"
    >>> foo = MyClass(grid, mpd)
    >>> foo.kw
    1000000.0
    """

    @wraps(func)
    def _wrapped(self, *args, **kwds):
        from ..grid import ModelGrid

        if not isinstance(args[0], ModelGrid):
            raise ValueError('first argument must be a ModelGrid')

        if len(args) == 2:
            warnings.warn(
                "Passing a file to a component's __init__ method is "
                "deprecated. Instead, pass parameters as keywords.",
                category=DeprecationWarning)

            if os.path.isfile(args[1]):
                with open(args[1], 'r') as fp:
                    params = load_params(fp)
            else:
                params = load_params(args[1])
        else:
            params = {}

        params.update(kwds)

        func(self, args[0], **params)

    return _wrapped

class use_field_name_or_array(object):

    """Decorate a function so that it accepts a field name or array.

    Parameters
    ----------
    func : function
        A function that accepts a grid and array as arguments.
    at_element : str
        The element type that the field is defined on ('node', 'cell',
        etc.)

    Returns
    -------
    func
        A wrapped function that accepts a grid and either a field name or
        a numpy array.

    Examples
    --------
    >>> from landlab import RasterModelGrid
    >>> grid = RasterModelGrid((4, 5), spacing=(1, 2))

    >>> def my_func(grid, vals):
    ...     return grid.area_of_cell * vals
    >>> my_func(grid, np.arange(grid.number_of_cells))
    array([  0.,   2.,   4.,   6.,   8.,  10.])

    Decorate the function so that the second argument can be array-like or
    the name of a field contained withing the grid. The decorator takes a
    single argument that is the name (as a `str`) of the grid element that
    the values are defined on ("node", "cell", etc.).

    >>> from landlab.utils.decorators import use_field_name_or_array
    >>> @use_field_name_or_array('cell')
    ... def my_func(grid, vals):
    ...     return grid.area_of_cell * vals

    The array of values now can be list or anything that can be converted to
    a numpy array.

    >>> my_func(grid, [0, 1, 2, 3, 4, 5])
    array([  0.,   2.,   4.,   6.,   8.,  10.])

    The array of values doesn't have to be flat.

    >>> vals = np.array([[0, 1, 2], [3, 4, 5]])
    >>> my_func(grid, vals)
    array([  0.,   2.,   4.,   6.,   8.,  10.])

    The array of values can be a field name.

    >>> _ = grid.add_field('cell', 'elevation', [0, 1, 2, 3, 4, 5])
    >>> my_func(grid, 'elevation')
    array([  0.,   2.,   4.,   6.,   8.,  10.])
    """

    def __init__(self, at_element):
        """Initialize the decorator.

        Parameters
        ----------
        at_element : str
            The element type that the field is defined on ('node', 'cell',
            etc.)
        """
        self._at = at_element

    def __call__(self, func):
        """Wrap the function."""
        @wraps(func)
        def _wrapped(grid, vals, *args, **kwds):
            """Convert the second argument to an array."""
            if isinstance(vals, six.string_types):
                vals = grid[self._at][vals]
            else:
                if vals.size != grid.number_of_elements(self._at):
                    raise ValueError('Element Size Mismatch')
                vals = np.asarray(vals).flatten()

            return func(grid, vals, *args, **kwds)
        return _wrapped

def make_return_array_immutable(func):
    """Decorate a function so that its return array is read-only.

    Parameters
    ----------
    func : function
        A function that returns a numpy array.

    Returns
    -------
    func
        A wrapped function that returns a read-only view of an array.
    """
    @wraps(func)
    def _wrapped(self, *args, **kwds):
        """Make the returned array read-only."""
        array = func(self, *args, **kwds)
        immutable_array = array.view()
        immutable_array.flags.writeable = False
        return immutable_array
    return _wrapped

# def deprecated(use, version):
#     """Mark a function as deprecated.
#
#     Parameters
#     ----------
#     use : str
#         Name of replacement function to use.
#     version : str
#         Version number when function was marked as deprecated.
#
#     Returns
#     -------
#     func
#         A wrapped function that issues a deprecation warning.
#     """
#     def real_decorator(func):
#
#         def _wrapped(*args, **kwargs):
#             """Warn that the function is deprecated before calling it."""
#             warnings.warn(
#                 "Call to deprecated function {name}.".format(
#                     name=func.__name__), category=DeprecationWarning)
#             return func(*args, **kwargs)
#         _wrapped.__dict__.update(func.__dict__)
#
#         return _wrapped
#
#     return real_decorator

def deprecated(use, version):
    """Mark a function as deprecated.

    Parameters
    ----------
    use : str
        Name of replacement function to use.
    version : str
        Version number when function was marked as deprecated.

    Returns
    -------
    func
        A wrapped function that issues a deprecation warning.
    """
    def real_decorator(func):
        warning_str = """
.. note:: This method is deprecated as of Landlab version {ver}.

    Use :func:`{use}` instead.

""".format(ver=version, use=use)

        doc_lines = (func.__doc__ or "").split(os.linesep)

        for lineno, line in enumerate(doc_lines):
            if len(line.rstrip()) == 0:
                break

        head = doc_lines[:lineno]
        body = doc_lines[lineno:]

        head = textwrap.dedent(os.linesep.join(head))
        body = textwrap.dedent(os.linesep.join(body))

        func.__doc__ = os.linesep.join([head, warning_str, body])

        @wraps(func)
        def _wrapped(*args, **kwargs):
            if func.__name__.startswith('_'):
                pass
            else:
                warnings.warn(
                    message="Call to deprecated function {name}.".format(
                        name=func.__name__), category=DeprecationWarning)
            return func(*args, **kwargs)
        _wrapped.__dict__.update(func.__dict__)

        return _wrapped

    return real_decorator
<|endoftext|>


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

import json
from flask import Flask
from flask import request
import requests
app = Flask(__name__)
import logging
import sys

__author__ = "Alan Castonguay and Steve Flanders"
__copyright__ = "Copyright 2016"
__credits__ = ["Alan Castonguay", "Steve Flanders"]
__license__ = "Apache v2"
__version__ = "1.0"
__maintainer__ = "Alan Castonguay and Steve Flanders"
__email__ = "li-cord@vmware.com"
__status__ = "Beta"

#######################################
# VARIABLES CHANGEME!!!
#######################################

# Port to use when running the shim
PORT=5001

# Socialcast
SOCIALCASTURL=''

# Slack
SLACKURL=''

# Pushbullet
PUSHBULLETURL='https://api.pushbullet.com/v2/pushes'
# This is an access token that you can obtain from https://www.pushbullet.com/#settings/account
# Please protect this access token since an unauthorized user who has access to this will be able to perform actions on your behalf
PUSHBULLETTOKEN = ''
#######################################
# DO NOT CHANGE ANYTHHING BELOW HERE!!!
#######################################

# PagerDuty
PAGERDUTYURL="https://events.pagerduty.com/generic/2010-04-15/create_event.json" # Do not change

# Configure logging

# file - override on every start
logging.basicConfig(filename='li_webhook_shim.log', filemode='w', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s')

# stdout
root = logging.getLogger()
root.setLevel(logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)

def parse(request):
    """ Parse JSON from alert webhook, return python dict or log exception """
    try:
        payload = request.get_json()
        #logging.info("Request=%s" % payload)
        # Need to support user alers and system notifications
        # Given different formats, some keys need to be checked
        alert = {
            "AlertName": payload['AlertName'],
            "info": payload['Info'] if 'Info' in payload else "",
            "Messages": payload['messages'],
            "url": payload['Url'] if 'Url' in payload else "",
            "editurl": payload['EditUrl'] if 'EditUrl' in payload else "",
            "HasMoreResults": payload['HasMoreResults'] if 'HasMoreResults' in payload else "",
            # may be less than length of messages, if there's more events
            "NumHits": payload['NumHits'] if 'NumHits' in payload else ""
        }
    except:
        logging.info("Body=%s" % request.get_data())
        logging.exception("Unexpected payload, is it in proper JSON format?")
        raise
    logging.info("Parsed=%s" % alert)
    return alert

def sendevent(url, payload, headers=None):
    """ Send payload in JSON to remote destination """
    if not headers:
        headers = {'Content-type': 'application/json'}
    try:
        logging.info("URL=%s" % url)
        logging.info("Headers=%s" % headers)
        logging.info("Body=%s" % payload)
        r = requests.post(url, headers=headers, data=payload)
        if r.status_code >= 200 and r.status_code < 300:
            return ("OK", r.status_code, None)
    except:
        logging.exception("Can't create new payload. Check code and try again.")
        raise
    return ("Failed to POST event, error_code=%d" % r.status_code, r.status_code, None)

@app.route("/")
def root():
    return ("""
This is a demo shim for a VMware vRealize Log Insight 3.3 or newer webhook.

IMPORTANT: It is NOT SUPPORTED to run this shim on the Log Insight virtual appliance!!

This shim features translations for:

Socialcast (NOTE: payload must be under 1MB or webhook will fail)

/endpoint/socialcast -- Requires specifying a SOCIALCASTURL and sends up to 10 events

/endpoint/socialcast/<NUMRESULTS> -- Requires specifying a SOCIALCASTURL and passing the NUMRESULTS to be forwarded

Slack (/endpoint/slack)

/endpoint/slack -- Requires specifying a SLACKURL and sends up to 10 events

/endpoint/slack/<NUMRESULTS> -- Requires specifying a SLACKURL and passing the NUMRESULTS to be forwarded

PagerDuty (NOTE: SERVICEKEY can be email address or integration key for service)

/endpoint/pagerduty/<SERVICEKEY> -- Requires passing a SERVICEKEY in the URL

Pushbullet (NOTE: PUSHBULLETTOKEN needs to be set on the shim)

/endpoint/pushbullet -- Sends a 'link' notification on all devices on pushbullet

Test

/endpoint/test -- Does not require anything and just dumps the body of the POST event

IMPORTANT: This code is current in %s status. Known issues:

This shim is very trusting; does not guarantee the notification source identity or require any shared secret

This shim does not convert HTML encoding so results may not appear on the destination in the desired output

This shim does not retry to send an event, it is fire and forget

No tests to ensure this shim respects the APIs it is calling

This shim has only partial exception handling and logging

Please send feedback to: %s

""" % (__status__, __email__, __email__), 200, None)

@app.route("/endpoint/test", methods=['POST'])
def test():
    logging.info(request.get_data())
    return "OK"

@app.route("/endpoint/pushbullet", methods=['POST'])
def pushbullet():
    if not PUSHBULLETURL: return ("PUSHBULLET parameter must be set, please edit the shim!", 500, None)
    if not PUSHBULLETTOKEN: return ("PUSHBULLETTOKEN parameter must be set, please edit the shim!", 500, None)

    a = parse(request)

    payload = {
        "body" : a['info'],
        "title" : a['AlertName'],
        "type" : "link",
        "url" : a['url']
    }

    headers = {'Content-type': 'application/json', 'Access-Token' : PUSHBULLETTOKEN}

    return sendevent(PUSHBULLETURL, json.dumps(payload), headers)

@app.route("/endpoint/socialcast", methods=['POST'])
@app.route("/endpoint/socialcast/<int:NUMRESULTS>", methods=['POST'])
def socialcast(NUMRESULTS=10):
    if not SOCIALCASTURL: return ("SOCIALCASTURL parameter must be set, please edit the shim!", 500, None)

    # Socialcast cares about the order of the information in the body
    # json.dumps() does not preserve the order so just use raw get_data()
    return sendevent(SOCIALCASTURL, request.get_data())

@app.route("/endpoint/slack", methods=['POST'])
@app.route("/endpoint/slack/<int:NUMRESULTS>", methods=['POST'])
def slack(NUMRESULTS=10):
    if not SLACKURL: return ("SLACKURL parameter must be set, please edit the shim!", 500, None)

    a = parse(request)

    slack_attachments = []
    try:
        for message in a['Messages'][:NUMRESULTS]:
            slack_attachments.append({
                "title": a['AlertName'],
                "title_link": a['url'],
                "color": "warning",
                "fallback": a['info'],
                "text": message.get('text', 'empty'),
                "fields": [{"title":f['name'], "value":f['content'], "short": True if len(f['content'])<20 else False} for f in message['fields'] if not f['name'].startswith('__') ],
                "pretext": a['info'] + ("\n\nYou can edit this alert by clicking: %s" % a['editurl'] if a['editurl'] else "")
            })
    except:
        logging.exception("Can't create new payload. Check code and try again.")
        raise
    payload={
        "username": a['AlertName'],
        "icon_url": "http://blogs.vmware.com/management/files/2015/04/li-logo.png",
        "pretext": a['info'],
        "attachments": slack_attachments,
    }
    return sendevent(SLACKURL, json.dumps(payload))

@app.route("/endpoint/pagerduty", methods=['POST'])
@app.route("/endpoint/pagerduty/<SERVICEKEY>", methods=['POST'])
def pagerduty(SERVICEKEY=None):
    if not SERVICEKEY: return ("SERVICEKEY must be set in the URL (e.g. /endpoint/pagerduty/<SERVICEKEY>", 500, None)

    # Retrieve fields in notification
    a = parse(request)

    payload={
        "service_key": SERVICEKEY,
        "event_type": "trigger",
        "description": a['AlertName'],
        "details": {
            "notes": a['info'],
            "events": str(a['Messages']),
        },
        "contexts":[
            {
                "type": "link",
                "href": a['url'],
                "text": "View search results in Log Insight"
            },{
                "type": "link",
                "href": a['editurl'],
                "text": "View alert definition in Log Insight"
            }
        ]
    }
    return sendevent(PAGERDUTYURL, json.dumps(payload))

if __name__ == "__main__":
    logging.info("Please navigate to the below URL for the available options in this shim")
    app.run(host='0.0.0.0', port=PORT)
<commit_msg>Added pushbullet as a destination<commit_after>#!/usr/bin/env python

import json
from flask import Flask
from flask import request
import requests
app = Flask(__name__)
import logging
import sys

__author__ = "Alan Castonguay and Steve Flanders"
__copyright__ = "Copyright 2016"
__credits__ = ["Alan Castonguay", "Steve Flanders"]
__license__ = "Apache v2"
__version__ = "1.0"
__maintainer__ = "Alan Castonguay and Steve Flanders"
__email__ = "li-cord@vmware.com"
__status__ = "Beta"

#######################################
# VARIABLES CHANGEME!!!
#######################################

# Port to use when running the shim
PORT=5001

# Socialcast
SOCIALCASTURL=''

# Slack
SLACKURL=''

# Pushbullet
PUSHBULLETURL='https://api.pushbullet.com/v2/pushes'
# This is an access token that you can obtain from https://www.pushbullet.com/#settings/account
# Please protect this access token since an unauthorized user who has access to this will be able to perform actions on your behalf
PUSHBULLETTOKEN = ''
#######################################
# DO NOT CHANGE ANYTHHING BELOW HERE!!!
#######################################

# PagerDuty
PAGERDUTYURL="https://events.pagerduty.com/generic/2010-04-15/create_event.json" # Do not change

# Configure logging

# file - override on every start
logging.basicConfig(filename='li_webhook_shim.log', filemode='w', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s')

# stdout
root = logging.getLogger()
root.setLevel(logging.DEBUG)
ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
ch.setFormatter(formatter)
root.addHandler(ch)

def parse(request):
    """ Parse JSON from alert webhook, return python dict or log exception """
    try:
        payload = request.get_json()
        # Need to support user alers and system notifications
        # Given different formats, some keys need to be checked
        alert = {
            "AlertName": payload['AlertName'],
            "info": payload['Info'] if 'Info' in payload else "",
            "Messages": payload['messages'],
            "url": payload['Url'] if 'Url' in payload else "",
            "editurl": payload['EditUrl'] if 'EditUrl' in payload else "",
            "HasMoreResults": payload['HasMoreResults'] if 'HasMoreResults' in payload else "",
            # may be less than length of messages, if there's more events
            "NumHits": payload['NumHits'] if 'NumHits' in payload else ""
        }
    except:
        logging.info("Body=%s" % request.get_data())
        logging.exception("Unexpected payload, is it in proper JSON format?")
        raise
    logging.info("Parsed=%s" % alert)
    return alert

def sendevent(url, payload, headers=None):
    """ Send payload in JSON to remote destination """
    if not headers:
        headers = {'Content-type': 'application/json'}
    try:
        logging.info("URL=%s" % url)
        logging.info("Headers=%s" % headers)
        logging.info("Body=%s" % payload)
        r = requests.post(url, headers=headers, data=payload)
        if r.status_code >= 200 and r.status_code < 300:
            return ("OK", r.status_code, None)
    except:
        logging.exception("Can't create new payload. Check code and try again.")
        raise
    return ("Failed to POST event, error_code=%d" % r.status_code, r.status_code, None)

@app.route("/")
def root():
    return ("""
This is a demo shim for a VMware vRealize Log Insight 3.3 or newer webhook.

IMPORTANT: It is NOT SUPPORTED to run this shim on the Log Insight virtual appliance!!

This shim features translations for:

Socialcast (NOTE: payload must be under 1MB or webhook will fail)

/endpoint/socialcast -- Requires specifying a SOCIALCASTURL and sends up to 10 events

/endpoint/socialcast/<NUMRESULTS> -- Requires specifying a SOCIALCASTURL and passing the NUMRESULTS to be forwarded

Slack (/endpoint/slack)

/endpoint/slack -- Requires specifying a SLACKURL and sends up to 10 events

/endpoint/slack/<NUMRESULTS> -- Requires specifying a SLACKURL and passing the NUMRESULTS to be forwarded

PagerDuty (NOTE: SERVICEKEY can be email address or integration key for service)

/endpoint/pagerduty/<SERVICEKEY> -- Requires passing a SERVICEKEY in the URL

Pushbullet (NOTE: PUSHBULLETTOKEN needs to be set on the shim)

/endpoint/pushbullet -- Sends a 'link' notification on all devices on pushbullet

Test

/endpoint/test -- Does not require anything and just dumps the body of the POST event

IMPORTANT: This code is current in %s status. Known issues:

This shim is very trusting; does not guarantee the notification source identity or require any shared secret

This shim does not convert HTML encoding so results may not appear on the destination in the desired output

This shim does not retry to send an event, it is fire and forget

No tests to ensure this shim respects the APIs it is calling

This shim has only partial exception handling and logging

Please send feedback to: %s

""" % (__status__, __email__, __email__), 200, None)

@app.route("/endpoint/test", methods=['POST'])
def test():
    logging.info(request.get_data())
    return "OK"

@app.route("/endpoint/pushbullet", methods=['POST'])
def pushbullet():
    if not PUSHBULLETURL: return ("PUSHBULLET parameter must be set, please edit the shim!", 500, None)
    if not PUSHBULLETTOKEN: return ("PUSHBULLETTOKEN parameter must be set, please edit the shim!", 500, None)

    a = parse(request)

    payload = {
        "body" : a['info'],
        "title" : a['AlertName'],
        "type" : "link",
        "url" : a['url']
    }

    headers = {'Content-type': 'application/json', 'Access-Token' : PUSHBULLETTOKEN}

    return sendevent(PUSHBULLETURL, json.dumps(payload), headers)

@app.route("/endpoint/socialcast", methods=['POST'])
@app.route("/endpoint/socialcast/<int:NUMRESULTS>", methods=['POST'])
def socialcast(NUMRESULTS=10):
    if not SOCIALCASTURL: return ("SOCIALCASTURL parameter must be set, please edit the shim!", 500, None)

    # Socialcast cares about the order of the information in the body
    # json.dumps() does not preserve the order so just use raw get_data()
    return sendevent(SOCIALCASTURL, request.get_data())

@app.route("/endpoint/slack", methods=['POST'])
@app.route("/endpoint/slack/<int:NUMRESULTS>", methods=['POST'])
def slack(NUMRESULTS=10):
    if not SLACKURL: return ("SLACKURL parameter must be set, please edit the shim!", 500, None)

    a = parse(request)

    slack_attachments = []
    try:
        for message in a['Messages'][:NUMRESULTS]:
            slack_attachments.append({
                "title": a['AlertName'],
                "title_link": a['url'],
                "color": "warning",
                "fallback": a['info'],
                "text": message.get('text', 'empty'),
                "fields": [{"title":f['name'], "value":f['content'], "short": True if len(f['content'])<20 else False} for f in message['fields'] if not f['name'].startswith('__') ],
                "pretext": a['info'] + ("\n\nYou can edit this alert by clicking: %s" % a['editurl'] if a['editurl'] else "")
            })
    except:
        logging.exception("Can't create new payload. Check code and try again.")
        raise
    payload={
        "username": a['AlertName'],
        "icon_url": "http://blogs.vmware.com/management/files/2015/04/li-logo.png",
        "pretext": a['info'],
        "attachments": slack_attachments,
    }
    return sendevent(SLACKURL, json.dumps(payload))

@app.route("/endpoint/pagerduty", methods=['POST'])
@app.route("/endpoint/pagerduty/<SERVICEKEY>", methods=['POST'])
def pagerduty(SERVICEKEY=None):
    if not SERVICEKEY: return ("SERVICEKEY must be set in the URL (e.g. /endpoint/pagerduty/<SERVICEKEY>", 500, None)

    # Retrieve fields in notification
    a = parse(request)

    payload={
        "service_key": SERVICEKEY,
        "event_type": "trigger",
        "description": a['AlertName'],
        "details": {
            "notes": a['info'],
            "events": str(a['Messages']),
        },
        "contexts":[
            {
                "type": "link",
                "href": a['url'],
                "text": "View search results in Log Insight"
            },{
                "type": "link",
                "href": a['editurl'],
                "text": "View alert definition in Log Insight"
            }
        ]
    }
    return sendevent(PAGERDUTYURL, json.dumps(payload))

if __name__ == "__main__":
    logging.info("Please navigate to the below URL for the available options in this shim")
    app.run(host='0.0.0.0', port=PORT)
<|endoftext|>


<commit_before>"""
Manages the lookup tables for the module
"""

import logging
import inspect
from os.path import samefile

from presets import registerPreset, addToRunQueue

_module_lookup = {}

class PModulePreset(object):

    def __init__(self, name):
        self.name = name

    def __call__(self, p):
        addToRunQueue(p, self.name)

# a decorator
def pmodule(c):
    name = c._name = c.__name__.lower()

    assert type(name) is str

    if name in _module_lookup:
        m = _module_lookup[name]

        cf = inspect.getfile(c)
        mf = inspect.getfile(m)

        if c is not m and cf != mf and not samefile(cf, mf):
            raise NameError("Module '%s' doubly defined (%s, %s)." % (name, cf, mf))
        else:
            return

    c.log = logging.getLogger(c._name)

    _module_lookup[name] = c

    registerPreset("r." + name, PModulePreset(name),
                   description = "Runs processing module '%s'." % c.__name__)

    return c

def getPModuleClass(name):

    try:
        return _module_lookup[name]
    except KeyError:
        raise NameError("Module '%s' not found." % name)

def isPModule(name):
    return name in _module_lookup
<commit_msg>Fixed small bug in determining whether two modules were from the same file, as one could be from the compiled file and one from the uncompiled.<commit_after>"""
Manages the lookup tables for the module
"""

import logging
import inspect
import re
from os.path import samefile

from presets import registerPreset, addToRunQueue

_module_lookup = {}

class PModulePreset(object):

    def __init__(self, name):
        self.name = name

    def __call__(self, p):
        addToRunQueue(p, self.name)

# a decorator
def pmodule(c):
    name = c._name = c.__name__.lower()

    assert type(name) is str

    if name in _module_lookup:
        m = _module_lookup[name]

        cf = inspect.getfile(c)
        mf = inspect.getfile(m)

        if c is not m and cf != mf and not samefile(cf, mf):

            # It's still possible that one file is the compiled
            # version of the other file.

            if not samefile(cf.replace('.pyc', '.py'), mf.replace('.pyc', '.py')):
                raise NameError("Module '%s' doubly defined (%s, %s)." % (name, cf, mf))
        else:
            return

    c.log = logging.getLogger(c._name)

    _module_lookup[name] = c

    registerPreset("r." + name, PModulePreset(name),
                   description = "Runs processing module '%s'." % c.__name__)

    return c

def getPModuleClass(name):

    try:
        return _module_lookup[name]
    except KeyError:
        raise NameError("Module '%s' not found." % name)

def isPModule(name):
    return name in _module_lookup
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
""" controller actions for E15Contest and E15Nominee

    :copyright: Copyright (c) 2015 Bivio Software, Inc.  All Rights Reserved.
    :license: Apache, see LICENSE for more details.
"""

import datetime
import flask
import json
import pytz
import random
import werkzeug.exceptions

from . import form as pef
from . import model as pem
from .. import biv
from .. import common
from .. import controller as ppc
from ..auth import model as pam
from ..general import oauth
from ..contest import model as pcm

_template = common.Template('evc2015')

class E15Contest(ppc.Task):
    """Contest actions"""

    @common.decorator_login_required
    @common.decorator_user_is_admin
    def action_admin_review_nominees(biv_obj):
        nominees = pem.E15Nominee.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == biv_obj.biv_id,
            pam.BivAccess.target_biv_id == pem.E15Nominee.biv_id
        ).all()
        nominees = sorted(nominees, key=lambda nominee: nominee.display_name)
        res = []
        for nominee in nominees:
            submitter = E15Contest._nominee_submitter(nominee)
            res.append({
                'biv_id': nominee.biv_id,
                'display_name': nominee.display_name,
                'url': nominee.url,
                'youtube_code': nominee.youtube_code,
                'nominee_desc': nominee.nominee_desc,
                'is_public': nominee.is_public,
                'founders': E15Contest._founder_info_for_nominee(nominee),
                'submitter_display_name': submitter.display_name,
                'submitter_email': submitter.user_email,
            })
        return flask.jsonify({
            'nominees': res,
        })

    @common.decorator_login_required
    @common.decorator_user_is_admin
    def action_admin_set_nominee_visibility(biv_obj):
        data = flask.request.get_json()
        nominee_biv_id = data['biv_id']
        is_public = data['is_public']
        nominee = pem.E15Nominee.query.filter_by(
            biv_id=nominee_biv_id,
        ).first_or_404()
        nominee.is_public = is_public
        ppc.db.session.add(nominee)
        return '{}'

    def action_contest_info(biv_obj):
        tz = pytz.timezone('US/Mountain')
        end_of_day = tz.localize(
            datetime.datetime(
                2015, 10, 14,
                23, 59, 59))
        seconds_remaining = (end_of_day - datetime.datetime.now(tz)).total_seconds()
        return flask.jsonify({
            'allowNominations': seconds_remaining > 0,
            'contestantCount': len(E15Contest._public_nominees(biv_obj)),
        })

    def action_index(biv_obj):
        """Returns angular app home"""
        return _template.render_template(
            biv_obj,
            'index',
            version='20151019-4',
        )

    def action_logout(biv_obj):
        oauth.logout()
        return E15Contest.action_user_state(biv_obj)

    def action_nominee_form_metadata(biv_obj):
        form = pef.Nominate()
        res = []
        for field in form:
            res.append({
                'name': field.name,
                'type': field.type,
                'label': field.label.text,
                'helpText': form.help_text(field.name),
            })
        return flask.jsonify(form_metadata=res)

    def action_nominee_form_submit(biv_obj):
        #TODO(pjm): need decorator for this
        if not flask.session.get('user.is_logged_in'):
            werkzeug.exceptions.abort(403)
        return flask.jsonify(pef.Nominate().execute(biv_obj))

    def action_nominee_info(biv_obj):
        data = json.loads(flask.request.data.decode('unicode-escape'))
        nominee_biv_id = biv.URI(data['nominee_biv_id']).biv_id
        # ensure the Nominee is related to this contest
        pam.BivAccess.query.filter_by(
            source_biv_id=biv_obj.biv_id,
            target_biv_id=nominee_biv_id,
        ).first_or_404()
        nominee = pem.E15Nominee.query.filter_by(
            biv_id=nominee_biv_id,
        ).first_or_404()
        return flask.jsonify(nominee={
            'biv_id': nominee.biv_id,
            'display_name': nominee.display_name,
            'url': nominee.url,
            'youtube_code': nominee.youtube_code,
            'nominee_desc': nominee.nominee_desc,
            'founders': E15Contest._founder_info_for_nominee(nominee),
        })

    def action_public_nominee_list(biv_obj):
        data = json.loads(flask.request.data.decode('unicode-escape'))
        nominees = E15Contest._public_nominees(biv_obj)
        random.Random(data['random_value']).shuffle(nominees)
        res = []
        for nominee in nominees:
            res.append({
                'biv_id': biv.Id(nominee.biv_id).to_biv_uri(),
                'display_name': nominee.display_name,
                'youtube_code': nominee.youtube_code,
                'nominee_summary': common.summary_text(nominee.nominee_desc),
            })
        return flask.jsonify({
            'nominees': res,
        })

    def action_rules(biv_obj):
        return flask.redirect('/static/pdf/20150914-evc-rules.pdf')

    def action_sponsors(biv_obj):
        return flask.jsonify(sponsors=biv_obj.get_sponsors())

    def action_user_state(biv_obj):
        return flask.jsonify(user_state={
            'is_logged_in': True if flask.session.get('user.is_logged_in') else False,
            'is_admin': pam.Admin.is_admin(),
            'is_judge': biv_obj.is_judge(),
            'random_value': random.random(),
        })

    def get_template():
        return _template

    def _founder_info_for_nominee(nominee):
        founders = pcm.Founder.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == nominee.biv_id,
            pam.BivAccess.target_biv_id == pcm.Founder.biv_id
        ).all()
        res = []
        for founder in founders:
            res.append({
                'biv_id': founder.biv_id,
                'display_name': founder.display_name,
                'founder_desc': founder.founder_desc,
            })
        return res

    def _nominee_submitter(nominee):
        return  pam.User.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == pam.User.biv_id,
            pam.BivAccess.target_biv_id == nominee.biv_id,
        ).first_or_404()

    def _public_nominees(contest):
        return pem.E15Nominee.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == contest.biv_id,
            pam.BivAccess.target_biv_id == pem.E15Nominee.biv_id,
            pem.E15Nominee.is_public == True,
        ).all()
<commit_msg>moved user randomValue to client only<commit_after># -*- coding: utf-8 -*-
""" controller actions for E15Contest and E15Nominee

    :copyright: Copyright (c) 2015 Bivio Software, Inc.  All Rights Reserved.
    :license: Apache, see LICENSE for more details.
"""

import datetime
import flask
import json
import pytz
import random
import werkzeug.exceptions

from . import form as pef
from . import model as pem
from .. import biv
from .. import common
from .. import controller as ppc
from ..auth import model as pam
from ..general import oauth
from ..contest import model as pcm

_template = common.Template('evc2015')

class E15Contest(ppc.Task):
    """Contest actions"""

    @common.decorator_login_required
    @common.decorator_user_is_admin
    def action_admin_review_nominees(biv_obj):
        nominees = pem.E15Nominee.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == biv_obj.biv_id,
            pam.BivAccess.target_biv_id == pem.E15Nominee.biv_id
        ).all()
        nominees = sorted(nominees, key=lambda nominee: nominee.display_name)
        res = []
        for nominee in nominees:
            submitter = E15Contest._nominee_submitter(nominee)
            res.append({
                'biv_id': nominee.biv_id,
                'display_name': nominee.display_name,
                'url': nominee.url,
                'youtube_code': nominee.youtube_code,
                'nominee_desc': nominee.nominee_desc,
                'is_public': nominee.is_public,
                'founders': E15Contest._founder_info_for_nominee(nominee),
                'submitter_display_name': submitter.display_name,
                'submitter_email': submitter.user_email,
            })
        return flask.jsonify({
            'nominees': res,
        })

    @common.decorator_login_required
    @common.decorator_user_is_admin
    def action_admin_set_nominee_visibility(biv_obj):
        data = flask.request.get_json()
        nominee_biv_id = data['biv_id']
        is_public = data['is_public']
        nominee = pem.E15Nominee.query.filter_by(
            biv_id=nominee_biv_id,
        ).first_or_404()
        nominee.is_public = is_public
        ppc.db.session.add(nominee)
        return '{}'

    def action_contest_info(biv_obj):
        tz = pytz.timezone('US/Mountain')
        end_of_day = tz.localize(
            datetime.datetime(
                2015, 10, 14,
                23, 59, 59))
        seconds_remaining = (end_of_day - datetime.datetime.now(tz)).total_seconds()
        return flask.jsonify({
            'allowNominations': seconds_remaining > 0,
            'contestantCount': len(E15Contest._public_nominees(biv_obj)),
        })

    def action_index(biv_obj):
        """Returns angular app home"""
        return _template.render_template(
            biv_obj,
            'index',
            version='20151019-5',
        )

    def action_logout(biv_obj):
        oauth.logout()
        return E15Contest.action_user_state(biv_obj)

    def action_nominee_form_metadata(biv_obj):
        form = pef.Nominate()
        res = []
        for field in form:
            res.append({
                'name': field.name,
                'type': field.type,
                'label': field.label.text,
                'helpText': form.help_text(field.name),
            })
        return flask.jsonify(form_metadata=res)

    def action_nominee_form_submit(biv_obj):
        #TODO(pjm): need decorator for this
        if not flask.session.get('user.is_logged_in'):
            werkzeug.exceptions.abort(403)
        return flask.jsonify(pef.Nominate().execute(biv_obj))

    def action_nominee_info(biv_obj):
        data = json.loads(flask.request.data.decode('unicode-escape'))
        nominee_biv_id = biv.URI(data['nominee_biv_id']).biv_id
        # ensure the Nominee is related to this contest
        pam.BivAccess.query.filter_by(
            source_biv_id=biv_obj.biv_id,
            target_biv_id=nominee_biv_id,
        ).first_or_404()
        nominee = pem.E15Nominee.query.filter_by(
            biv_id=nominee_biv_id,
        ).first_or_404()
        return flask.jsonify(nominee={
            'biv_id': nominee.biv_id,
            'display_name': nominee.display_name,
            'url': nominee.url,
            'youtube_code': nominee.youtube_code,
            'nominee_desc': nominee.nominee_desc,
            'founders': E15Contest._founder_info_for_nominee(nominee),
        })

    def action_public_nominee_list(biv_obj):
        data = json.loads(flask.request.data.decode('unicode-escape'))
        nominees = E15Contest._public_nominees(biv_obj)
        random.Random(data['random_value']).shuffle(nominees)
        res = []
        for nominee in nominees:
            res.append({
                'biv_id': biv.Id(nominee.biv_id).to_biv_uri(),
                'display_name': nominee.display_name,
                'youtube_code': nominee.youtube_code,
                'nominee_summary': common.summary_text(nominee.nominee_desc),
            })
        return flask.jsonify({
            'nominees': res,
        })

    def action_rules(biv_obj):
        return flask.redirect('/static/pdf/20150914-evc-rules.pdf')

    def action_sponsors(biv_obj):
        return flask.jsonify(sponsors=biv_obj.get_sponsors())

    def action_user_state(biv_obj):
        return flask.jsonify(user_state={
            'is_logged_in': True if flask.session.get('user.is_logged_in') else False,
            'is_admin': pam.Admin.is_admin(),
            'is_judge': biv_obj.is_judge(),
        })

    def get_template():
        return _template

    def _founder_info_for_nominee(nominee):
        founders = pcm.Founder.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == nominee.biv_id,
            pam.BivAccess.target_biv_id == pcm.Founder.biv_id
        ).all()
        res = []
        for founder in founders:
            res.append({
                'biv_id': founder.biv_id,
                'display_name': founder.display_name,
                'founder_desc': founder.founder_desc,
            })
        return res

    def _nominee_submitter(nominee):
        return  pam.User.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == pam.User.biv_id,
            pam.BivAccess.target_biv_id == nominee.biv_id,
        ).first_or_404()

    def _public_nominees(contest):
        return pem.E15Nominee.query.select_from(pam.BivAccess).filter(
            pam.BivAccess.source_biv_id == contest.biv_id,
            pam.BivAccess.target_biv_id == pem.E15Nominee.biv_id,
            pem.E15Nominee.is_public == True,
        ).all()
<|endoftext|>