<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#     Author:  Fekete Mihai <mihai.fekete@forbiom.eu>
#    Copyright (C) 2014 FOREST AND BIOMASS SERVICES ROMANIA SA (http://www.forbiom.eu).
#
#    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 os
from datetime import date
from subprocess import Popen, PIPE

from zipfile import ZipFile
from StringIO import StringIO
import requests

from openerp import models, fields, api, _
from openerp.exceptions import Warning

ANAF_URL = 'http://static.anaf.ro/static/10/Anaf/TVA_incasare/ultim_%s.zip'

class res_partner_anaf(models.Model):
    _name = "res.partner.anaf"
    _description = "ANAF History about VAT on Payment"
    _order = "vat, operation_date DESC, end_date, start_date"

    vat = fields.Char('VAT', select=True)
    start_date = fields.Date('Start Date', select=True)
    end_date = fields.Date('End Date', select=True)
    publish_date = fields.Date('Publish Date')
    operation_date = fields.Date('Operation Date')
    operation_type = fields.Selection([('I', 'Register'),
                                       ('E', 'Fix error'),
                                       ('D', 'Removal')],
                                      'Operation Type')

class res_partner(models.Model):
    _name = "res.partner"
    _inherit = "res.partner"

    @api.one
    @api.depends('vat')
    def _compute_vat(self):
        self.vat_number = self.vat and self.vat[2:].replace(' ', '')

    @api.one
    @api.depends('vat_number')
    def _compute_anaf_history(self):
        history = self.env['res.partner.anaf'].search(
            [('vat', '=', self.vat_number)])
        if history:
            self.anaf_history = [(6, 0, [line.id for line in history])]

    vat_number = fields.Char('VAT', compute='_compute_vat')
    anaf_history = fields.One2many(
        'res.partner.anaf',
        compute='_compute_anaf_history',
        string='ANAF History',
        readonly=True
    )

    # Grab VAT on Payment data from ANAF, update table - SQL injection
    @api.model
    def _download_anaf_data(self):
        path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
        istoric = os.path.join(path, "istoric.txt")
        if os.path.exists(istoric):
            modify = date.fromtimestamp(os.path.getmtime(istoric))
        else:
            modify = date.fromtimestamp(0)
        if bool(date.today() - modify):
            result = requests.get(ANAF_URL % date.today().strftime('%Y%m%d'))
            if result.status_code == requests.codes.ok:
                files = ZipFile(StringIO(result.content))
                files.extractall(path=str(path))

    @api.model
    def _insert_relevant_anaf_data(self, partners):
        vat_numbers = [
            p.vat_number for p in partners if p.vat.lower().startswith('ro')]
        if vat_numbers == []:
            return
        istoric = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            'data',
            'istoric.txt')
        vat_regex = '^[0-9]+#(%s)#' % '|'.join(vat_numbers)
        anaf_data = Popen(
            ['egrep', vat_regex, istoric],
            stdout=PIPE
        )
        (process_lines, err) = anaf_data.communicate()
        process_lines = [x.split('#') for x in process_lines.split()]
        lines = self.env['res.partner.anaf'].search([
            ('id', 'in', [int(x[0]) for x in process_lines])])
        line_ids = [l.id for l in lines]
        for line in process_lines:
            if int(line[0]) not in line_ids:
                for k, v in enumerate(line):
                    if k == 0:
                        continue
                    elif v == '':
                        line[k] = 'NULL'
                    else:
                        line[k] = "'%s'" % v
                self._cr.execute("""
INSERT INTO res_partner_anaf
    (id,vat,start_date, end_date, publish_date, operation_date, operation_type)
VALUES
    %s""" % '(' + ','.join(line) + ')')

    @api.multi
    def _check_vat_on_payment(self):
        ctx = dict(self._context)
        vat_on_payment = False
        if self.anaf_history:
            if len(self.anaf_history) > 1 and ctx.get('check_date', False):
                lines = self.env['res.partner.anaf'].search([
                    ('id', 'in', [rec.id for rec in self.anaf_history]),
                    ('start_date', '<=', ctx['check_date']),
                    ('end_date', '>=', ctx['check_date'])
                ])
                if lines and lines[0].operation_type == 'D':
                    vat_on_payment = True
            else:
                if self.anaf_history[0].operation_type == 'I':
                    vat_on_payment = True
        return vat_on_payment

    @api.one
    def check_vat_on_payment(self):
        ctx = dict(self._context)
        ctx.update({'check_date': date.today()})
        self.vat_on_payment = self.with_context(ctx)._check_vat_on_payment()

    @api.multi
    def _check_vat_subjected(self):
        vat_s = vat_number = vat_country = False
        if self.vat:
            vat_country, vat_number = self._split_vat(self.vat)
        if vat_number and vat_country and vat_country.upper() == 'RO':
            res = requests.get(
                'http://openapi.ro/api/companies/' +
                str(vat_number) +
                '.json')
            if res.status_code == 200:
                res = res.json()
                if res['vat'] == '1':
                    vat_s = True
        elif vat_number and vat_country:
            vat_s = self.vies_vat_check(vat_country, vat_number)
        return vat_s

    @api.one
    def check_vat_subjected(self):
        if self.vat_on_payment:
            self.vat_subjected = True
        else:
            self.vat_subjected = self._check_vat_subjected()

    @api.multi
    def update_vat_one(self):
        for partner in self:
            partner.check_vat_on_payment()
            partner.check_vat_subjected()
        return True

    @api.one
    def button_get_partner_data(self):
        super(res_partner, self).button_get_partner_data()
        self._insert_relevant_anaf_data([self[0]])
        self.check_vat_on_payment()

    @api.multi
    def update_vat_all(self):
        self._download_anaf_data()
        partners = self.search([('vat', '!=', False)])
        self._insert_relevant_anaf_data(partners)
        for partner in partners:
            partner.check_vat_on_payment()
            partner.check_vat_subjected()

    @api.model
    def _update_vat_all(self):
        self.update_vat_all()
<commit_msg>Update openapi with addres moddification.<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#     Author:  Fekete Mihai <mihai.fekete@forbiom.eu>
#    Copyright (C) 2014 FOREST AND BIOMASS SERVICES ROMANIA SA (http://www.forbiom.eu).
#
#    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 os
from datetime import date
from subprocess import Popen, PIPE

from zipfile import ZipFile
from StringIO import StringIO
import requests

from openerp import models, fields, api, _
from openerp.exceptions import Warning

ANAF_URL = 'http://static.anaf.ro/static/10/Anaf/TVA_incasare/ultim_%s.zip'

class res_partner_anaf(models.Model):
    _name = "res.partner.anaf"
    _description = "ANAF History about VAT on Payment"
    _order = "vat, operation_date DESC, end_date, start_date"

    vat = fields.Char('VAT', select=True)
    start_date = fields.Date('Start Date', select=True)
    end_date = fields.Date('End Date', select=True)
    publish_date = fields.Date('Publish Date')
    operation_date = fields.Date('Operation Date')
    operation_type = fields.Selection([('I', 'Register'),
                                       ('E', 'Fix error'),
                                       ('D', 'Removal')],
                                      'Operation Type')

class res_partner(models.Model):
    _name = "res.partner"
    _inherit = "res.partner"

    @api.one
    @api.depends('vat')
    def _compute_vat(self):
        self.vat_number = self.vat and self.vat[2:].replace(' ', '')

    @api.one
    @api.depends('vat_number')
    def _compute_anaf_history(self):
        history = self.env['res.partner.anaf'].search(
            [('vat', '=', self.vat_number)])
        if history:
            self.anaf_history = [(6, 0, [line.id for line in history])]

    vat_number = fields.Char('VAT', compute='_compute_vat')
    anaf_history = fields.One2many(
        'res.partner.anaf',
        compute='_compute_anaf_history',
        string='ANAF History',
        readonly=True
    )

    # Grab VAT on Payment data from ANAF, update table - SQL injection
    @api.model
    def _download_anaf_data(self):
        path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
        istoric = os.path.join(path, "istoric.txt")
        if os.path.exists(istoric):
            modify = date.fromtimestamp(os.path.getmtime(istoric))
        else:
            modify = date.fromtimestamp(0)
        if bool(date.today() - modify):
            result = requests.get(ANAF_URL % date.today().strftime('%Y%m%d'))
            if result.status_code == requests.codes.ok:
                files = ZipFile(StringIO(result.content))
                files.extractall(path=str(path))

    @api.model
    def _insert_relevant_anaf_data(self, partners):
        vat_numbers = [
            p.vat_number for p in partners if p.vat.lower().startswith('ro')]
        if vat_numbers == []:
            return
        istoric = os.path.join(
            os.path.dirname(os.path.abspath(__file__)),
            'data',
            'istoric.txt')
        vat_regex = '^[0-9]+#(%s)#' % '|'.join(vat_numbers)
        anaf_data = Popen(
            ['egrep', vat_regex, istoric],
            stdout=PIPE
        )
        (process_lines, err) = anaf_data.communicate()
        process_lines = [x.split('#') for x in process_lines.split()]
        lines = self.env['res.partner.anaf'].search([
            ('id', 'in', [int(x[0]) for x in process_lines])])
        line_ids = [l.id for l in lines]
        for line in process_lines:
            if int(line[0]) not in line_ids:
                for k, v in enumerate(line):
                    if k == 0:
                        continue
                    elif v == '':
                        line[k] = 'NULL'
                    else:
                        line[k] = "'%s'" % v
                self._cr.execute("""
INSERT INTO res_partner_anaf
    (id,vat,start_date, end_date, publish_date, operation_date, operation_type)
VALUES
    %s""" % '(' + ','.join(line) + ')')

    @api.multi
    def _check_vat_on_payment(self):
        ctx = dict(self._context)
        vat_on_payment = False
        if self.anaf_history:
            if len(self.anaf_history) > 1 and ctx.get('check_date', False):
                lines = self.env['res.partner.anaf'].search([
                    ('id', 'in', [rec.id for rec in self.anaf_history]),
                    ('start_date', '<=', ctx['check_date']),
                    ('end_date', '>=', ctx['check_date'])
                ])
                if lines and lines[0].operation_type == 'D':
                    vat_on_payment = True
            else:
                if self.anaf_history[0].operation_type == 'I':
                    vat_on_payment = True
        return vat_on_payment

    @api.one
    def check_vat_on_payment(self):
        ctx = dict(self._context)
        ctx.update({'check_date': date.today()})
        self.vat_on_payment = self.with_context(ctx)._check_vat_on_payment()

    @api.multi
    def _check_vat_subjected(self):
        vat_s = vat_number = vat_country = False
        if self.vat:
            vat_country, vat_number = self._split_vat(self.vat)
        if vat_number and vat_country and vat_country.upper() == 'RO':
            res = requests.get(
                'http://legacy.openapi.ro/api/companies/' +
                str(vat_number) +
                '.json')
            if res.status_code == 200:
                res = res.json()
                if res['vat'] == '1':
                    vat_s = True
        elif vat_number and vat_country:
            vat_s = self.vies_vat_check(vat_country, vat_number)
        return vat_s

    @api.one
    def check_vat_subjected(self):
        if self.vat_on_payment:
            self.vat_subjected = True
        else:
            self.vat_subjected = self._check_vat_subjected()

    @api.multi
    def update_vat_one(self):
        for partner in self:
            partner.check_vat_on_payment()
            partner.check_vat_subjected()
        return True

    @api.one
    def button_get_partner_data(self):
        super(res_partner, self).button_get_partner_data()
        self._insert_relevant_anaf_data([self[0]])
        self.check_vat_on_payment()

    @api.multi
    def update_vat_all(self):
        self._download_anaf_data()
        partners = self.search([('vat', '!=', False)])
        self._insert_relevant_anaf_data(partners)
        for partner in partners:
            partner.check_vat_on_payment()
            partner.check_vat_subjected()

    @api.model
    def _update_vat_all(self):
        self.update_vat_all()
<|endoftext|>


<commit_before>"""Leetcode 144. Binary Tree Preorder Traversal
Medium

URL: https://leetcode.com/problems/binary-tree-preorder-traversal/

Given a binary tree, return the preorder traversal of its nodes' values.

Example:
Input: [1,null,2,3]
   1
    \
     2
    /
   3
Output: [1,2,3]

Follow up: Recursive solution is trivial, could you do it iteratively?
"""

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

class SolutionRecur(object):
    def _preorderRecur(self, root, vals):
        if not root:
            return None

        current = root
        vals.append(current.val)
        self._preorderRecur(current.left, vals)
        self._preorderRecur(current.right, vals)

    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]

        Time complexity: O(n).
        Space complexity: O(logn) for balanced tree; O(n) for single sided tree.
        """
        # Apply recursive preorder traversal.
        vals = []
        self._preorderRecur(root, vals)
        return vals

def main():
    # Input: [1,null,2,3]
    #    1
    #     \
    #      2
    #     /
    #    3
    # Output: [1,2,3]
    root = TreeNode(1)
    root.right = TreeNode(2)
    root.right.left = TreeNode(3)

    print SolutionRecur().preorderTraversal(root)

if __name__ == '__main__':
    main()
<commit_msg>Complete iter sol<commit_after>"""Leetcode 144. Binary Tree Preorder Traversal
Medium

URL: https://leetcode.com/problems/binary-tree-preorder-traversal/

Given a binary tree, return the preorder traversal of its nodes' values.

Example:
Input: [1,null,2,3]
   1
    \
     2
    /
   3
Output: [1,2,3]

Follow up: Recursive solution is trivial, could you do it iteratively?
"""

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

class SolutionRecur(object):
    def _preorderRecur(self, root, vals):
        if not root:
            return None

        current = root
        vals.append(current.val)
        self._preorderRecur(current.left, vals)
        self._preorderRecur(current.right, vals)

    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]

        Time complexity: O(n).
        Space complexity: O(logn) for balanced tree; O(n) for single sided tree.
        """
        # Apply recursive preorder traversal.
        vals = []
        self._preorderRecur(root, vals)
        return vals

class SolutionIter(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]

        Time complexity: O(n).
        Space complexity: O(logn) for balanced tree; O(n) for single sided tree.
        """
        if not root:
            return None

        # Apply iterative preorder traversal with stack.
        vals = []

        stack = [root]

        while stack:
            current = stack.pop()
            vals.append(current.val)

            # Append right and then left since we use stack with LIFO.
            if current.right:
                stack.append(current.right)
            if current.left:
                stack.append(current.left)

        return vals

def main():
    # Input: [1,null,2,3]
    #    1
    #     \
    #      2
    #     /
    #    3
    # Output: [1,2,3]
    root = TreeNode(1)
    root.right = TreeNode(2)
    root.right.left = TreeNode(3)

    print SolutionRecur().preorderTraversal(root)
    print SolutionIter().preorderTraversal(root)

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


<commit_before>from abc import abstractmethod
from collections import namedtuple
from urllib.parse import urlencode

from jsonapiquery import url

import functools

Filter = namedtuple('Filter', ['fields', 'strategy', 'values'])
Sort = namedtuple('Sort', ['fields', 'direction'])

class JSONAPIQuery(object):
    """JSONAPI query orchestration class."""

    model_driver = None
    view_driver = None

    def __init__(self, parameters, model, view):
        self.parameters = parameters
        self.model = model
        self.view = view

    def make_query(self, query, options):
        """Return a filtered, sorted, compounded, and paginated query or error.

        Keyword arguments:
            query: ORM query object.
            options (dict): Option, boolean pairs.
        """
        total = None
        selects = []
        schemas = []

        errors = []
        if options.get('can_filter', True):
            query, errors = self.filter(query, errors)
        if options.get('can_sort', True):
            query, errors = self.sort(query, errors)
        if options.get('can_compound', True):
            query, selects, schemas, errors = self.compound(query, errors)
        if options.get('can_paginate', True):
            query, total, errors = self.paginate(query, errors)

        if errors:
            raise self.make_errors(errors)
        return query, total, selects, schemas

    def make_included_response(self, response, models, schemas):
        """Return a compounded response."""
        included = self.serialize_included(models, schemas)
        if included:
            response['included'] = included
        return response

    def make_paginated_response(self, response, total):
        """Return a paginated response."""
        if total is not None:
            links = self.make_pagination_links(self.parameters, total)
            response['meta'] = {'total': total}
            response['links'] = links
        return response

    @abstractmethod
    def make_errors(self, errors):
        """Return a JSONAPI exception class instance.

        Keyword arguments:
            errors (list): List of JSONAPI error objects.
        """
        return

    @abstractmethod
    def serialize_included(self, models, schemas):
        """Return a serialized set of included objects.

        Keyword arguments:
            models (list): List of lists of like model instances.
            schemas (lust): List of schemas instances.
        """
        return

    @property
    @functools.lru_cache()
    def filters(self):
        """Return a list of filter parameters paths."""
        return url.get_filters(self.parameters)

    def filter(self, query, global_errors=[]):
        """Return a filtered query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        fields, errors = self.make_filter_fields()
        if errors:
            global_errors.extend(errors)
            return query, global_errors
        filters = self.make_query_filters(fields)
        return query.apply_filters(filters), global_errors

    def make_filter_fields(self):
        """Return a list of parsed filters."""
        filters, errors = [], []
        for filter in self.filters:
            filter, error = self.make_filter_field(*filter)
            filters.append(filter)
            errors.extend(error)
        return filters, errors

    def make_filter_field(self, path, strategy, values):
        """Return a tuple of fields, strategy, and typed values."""
        try:
            fields = self.view_driver.make_from_path(path, self.view)
        except AttributeError as exc:
            return None, [self.make_error('filter[{}]'.format(path), str(exc))]
        try:
            values = fields[-1].deserialize_values(values)
        except Exception as exc:
            return None, [self.make_error('filter[{}]'.format(path), str(exc))]
        return Filter(fields, strategy, values), []

    def make_query_filters(self, fields):
        """Return a list of `filter` tuples."""
        filters = []
        for filter in fields:
            component, driver = self.make_query_from_fields(filter.fields)
            strategy = filter.strategy or driver.get_default_strategy()
            filters.append((
                component.column, strategy, filter.values, component.joins))
        return filters

    @property
    @functools.lru_cache()
    def sorts(self):
        """Return a list of sort paramter paths."""
        return url.get_sorts(self.parameters)

    def sort(self, query, global_errors=[]):
        """Return a sorted query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        fields, errors = self.make_sort_fields()
        if errors:
            global_errors.extend(errors)
            return query, global_errors
        sorts = self.make_query_sorts(fields)
        return query.apply_sorts(sorts), global_errors

    def make_sort_fields(self):
        """Return a list of parsed sorts."""
        sorts, errors = [], []
        for sort in self.sorts:
            sort, error = self.make_sort_field(*sort)
            sorts.append(sort)
            errors.extend(error)
        return sorts, errors

    def make_sort_field(self, path, direction):
        """Return a tuple of fields, strategy, and typed values."""
        try:
            fields = self.view_driver.make_from_path(path, self.view)
            return Sort(fields, direction), []
        except AttributeError as exc:
            return None, [self.make_error('sort', str(exc))]

    def make_query_sorts(self, fields):
        """Return a list of `sort` tuples."""
        sorts = []
        for sort in fields:
            component, driver = self.make_query_from_fields(sort.fields)
            sorts.append((
                component.column, sort.direction, component.joins))
        return sorts

    @property
    @functools.lru_cache()
    def includes(self):
        """Return a list of include parameter paths."""
        return url.get_includes(self.parameters)

    def include(self, query, global_errors=[]):
        """Return a compounded query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        fields, errors = self.make_include_fields()
        if errors:
            global_errors.extend(errors)
            return query, [], [], global_errors
        mappers, selects, schemas = self.make_query_includes(fields)
        return query.include(mappers), selects, schemas, global_errors

    def make_include_fields(self):
        """Return a list of parsed includes."""
        includes, errors = [], []
        for include in self.includes:
            fields, error = self.make_include_field(include)
            includes.append(Includes(fields))
            errors.extend(error)
        return includes, errors

    def make_include_field(self, path):
        """Return a tuple of fields."""
        try:
            return self.view_driver.make_from_path(path, self.view), []
        except AttributeError as exc:
            return [], [self.make_error('include', str(exc))]

    def make_query_includes(self, fields):
        """Return a list of `include` tuples."""
        mappers, selects, schemas = [], [], []
        for include_ in fields:
            component, driver = self.make_query_from_fields(include_)
            mappers.extend(component.joins)
            selects.extend(component.selects)
            schemas.extend(include_.schemas)
        return mappers, selects, schemas

    @property
    @functools.lru_cache()
    def paginators(self):
        """Return a list of page parameters paths."""
        return url.get_paginators(self.parameters)

    def paginate(self, query, global_errors=[]):
        """Return a paginated query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        errors = self._validate_paginators()
        if errors:
            global_errors.extend(errors)
            return query, None, global_errors
        total = query.count()
        return query.apply_paginators(self.paginators), total, global_errors

    def _validate_paginators(self):
        errors = []
        for key, value in self.paginators:
            errors.extend(self._validate_paginator(key, value))
        return errors

    def _validate_paginator(self, key, value):
        error = 'Invalid value "{}" specified.'.format(value)
        if not value.isdigit():
            return [self.make_error('page[{}]'.format(key), error)]
        return []

    def make_error(self, parameter, message):
        """Return a JSONAPI compliant parameter error object.

        Keyword arguments:
            parameter (str): URL parameter name.
            message (str): Human-readable error message.
        """
        return {
            'source': {'parameter': parameter},
            'detail': message
        }

    def make_query_from_fields(self, fields):
        """Return a `Query` tuple from a set of fields."""
        return self.model_driver.make_from_fields(fields, self.model)

    def make_pagination_links(self, base_url, parameters, total):
        """Return a dictionary of pagination links.

        Based on the pagination strategy, calculate the correct limits
        and offsets and encode the parameters into a URL safe format.
        """
        if 'page[number]' in parameters:
            return self._paginate_number(base_url, parameters, total)
        return self._paginate_offset(base_url, parameters, total)

    def _paginate_offset(self, base_url, params, total):
        limit, offset = 50, 0
        for strategy, value in self.paginators:
            if strategy == 'limit':
                limit = int(value)
            elif strategy == 'offset':
                offset = int(value)

        url = base_url + '?{}'
        values = self._build_page_offset_values(total, limit, offset)
        return {
            'first': url.format(self._encode_page_offset(params, values[0])),
            'last': url.format(self._encode_page_offset(params, values[1])),
            'next': url.format(self._encode_page_offset(params, values[2])),
            'prev': url.format(self._encode_page_offset(params, values[3])),
            'self': base_url
        }

    def _paginate_number(self, base_url, params, total):
        limit, page = 50, 1
        for strategy, value in self.paginators:
            if strategy == 'limit':
                limit = int(value)
            elif strategy == 'number':
                page = int(value)

        url = base_url + '?{}'
        values = self._build_page_number_values(total, limit, page)
        return {
            'first': url.format(self._encode_page_number(params, values[0])),
            'last': url.format(self._encode_page_number(params, values[1])),
            'next': url.format(self._encode_page_number(params, values[2])),
            'prev': url.format(self._encode_page_number(params, values[3])),
            'self': base_url
        }

    def _build_page_offset_values(self, total, limit, offset):
        """Return a tuple of offset values.

        The response, in order of position, is `first`, `last`, `next`,
        and `prev`.
        """
        return 0, max(total - limit, 0), offset + limit, max(offset - limit, 0)

    def _build_page_number_values(self, total, limit, current):
        """Return a tuple of page number values.

        The response, in order of position, is `first`, `last`, `next`,
        and `prev`.
        """
        return 1, max(total / limit, 1), current + 1, max(current - 1, 1)

    def _encode_page_offset(self, params, value):
        """Return encoded page[offset] parameters."""
        return self._encode_parameters(params, 'page[offset]', value)

    def _encode_page_number(self, params, value):
        """Return encoded page[number] parameters."""
        return self._encode_parameters(params, 'page[number]', value)

    def _encode_parameters(self, params, key, value):
        """Return a URL encoded parameter object."""
        params = params.copy()
        params[key] = value
        return urlencode(params)

class Includes(object):

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

    def __len__(self):
        return len(self.fields)

    def __getitem__(self, index):
        if index >= len(self):
            raise IndexError
        return self.fields[index]

    @property
    @functools.lru_cache()
    def schemas(self):
        """Return a list of schema instances."""
        return [field.related_class for field in self.fields]
<commit_msg>Added base include handling<commit_after>from abc import abstractmethod
from collections import namedtuple
from urllib.parse import urlencode

from jsonapiquery import url

import functools

Filter = namedtuple('Filter', ['fields', 'strategy', 'values'])
Sort = namedtuple('Sort', ['fields', 'direction'])

class JSONAPIQuery(object):
    """JSONAPI query orchestration class."""

    model_driver = None
    view_driver = None

    def __init__(self, parameters, model, view):
        self.parameters = parameters
        self.model = model
        self.view = view

    def make_query(self, query, options):
        """Return a filtered, sorted, compounded, and paginated query or error.

        Keyword arguments:
            query: ORM query object.
            options (dict): Option, boolean pairs.
        """
        total = None
        selects = []
        schemas = []

        errors = []
        if options.get('can_filter', True):
            query, errors = self.filter(query, errors)
        if options.get('can_sort', True):
            query, errors = self.sort(query, errors)
        if options.get('can_compound', True):
            query, selects, schemas, errors = self.include(query, errors)
        if options.get('can_paginate', True):
            query, total, errors = self.paginate(query, errors)

        if errors:
            raise self.make_errors(errors)
        return query, total, selects, schemas

    def make_included_response(self, response, models, schemas):
        """Return a compounded response."""
        included = []
        for position, rows in enumerate(models):
            output = self.serialize_included(schemas[position], models)
            included.extend(output)
        if included:
            response['included'] = included
        return response

    def make_paginated_response(self, response, total):
        """Return a paginated response."""
        if total is not None:
            links = self.make_pagination_links(self.parameters, total)
            response['meta'] = {'total': total}
            response['links'] = links
        return response

    @abstractmethod
    def make_errors(self, errors):
        """Return a JSONAPI exception class instance.

        Keyword arguments:
            errors (list): List of JSONAPI error objects.
        """
        return

    @abstractmethod
    def serialize_included(self, schema, models):
        """Return a serialized set of included objects.

        Keyword arguments:
            schema: Serializer class instance.
            models (list): List of model class instances.
        """
        return

    @property
    @functools.lru_cache()
    def filters(self):
        """Return a list of filter parameters paths."""
        return url.get_filters(self.parameters)

    def filter(self, query, global_errors=[]):
        """Return a filtered query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        fields, errors = self.make_filter_fields()
        if errors:
            global_errors.extend(errors)
            return query, global_errors
        filters = self.make_query_filters(fields)
        return query.apply_filters(filters), global_errors

    def make_filter_fields(self):
        """Return a list of parsed filters."""
        filters, errors = [], []
        for filter in self.filters:
            filter, error = self.make_filter_field(*filter)
            filters.append(filter)
            errors.extend(error)
        return filters, errors

    def make_filter_field(self, path, strategy, values):
        """Return a tuple of fields, strategy, and typed values."""
        try:
            fields = self.view_driver.make_from_path(path, self.view)
        except AttributeError as exc:
            return None, [self.make_error('filter[{}]'.format(path), str(exc))]
        try:
            values = fields[-1].deserialize_values(values)
        except Exception as exc:
            return None, [self.make_error('filter[{}]'.format(path), str(exc))]
        return Filter(fields, strategy, values), []

    def make_query_filters(self, fields):
        """Return a list of `filter` tuples."""
        filters = []
        for filter in fields:
            component, driver = self.make_query_from_fields(filter.fields)
            strategy = filter.strategy or driver.get_default_strategy()
            filters.append((
                component.column, strategy, filter.values, component.joins))
        return filters

    @property
    @functools.lru_cache()
    def sorts(self):
        """Return a list of sort paramter paths."""
        return url.get_sorts(self.parameters)

    def sort(self, query, global_errors=[]):
        """Return a sorted query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        fields, errors = self.make_sort_fields()
        if errors:
            global_errors.extend(errors)
            return query, global_errors
        sorts = self.make_query_sorts(fields)
        return query.apply_sorts(sorts), global_errors

    def make_sort_fields(self):
        """Return a list of parsed sorts."""
        sorts, errors = [], []
        for sort in self.sorts:
            sort, error = self.make_sort_field(*sort)
            sorts.append(sort)
            errors.extend(error)
        return sorts, errors

    def make_sort_field(self, path, direction):
        """Return a tuple of fields, strategy, and typed values."""
        try:
            fields = self.view_driver.make_from_path(path, self.view)
            return Sort(fields, direction), []
        except AttributeError as exc:
            return None, [self.make_error('sort', str(exc))]

    def make_query_sorts(self, fields):
        """Return a list of `sort` tuples."""
        sorts = []
        for sort in fields:
            component, driver = self.make_query_from_fields(sort.fields)
            sorts.append((
                component.column, sort.direction, component.joins))
        return sorts

    @property
    @functools.lru_cache()
    def includes(self):
        """Return a list of include parameter paths."""
        return url.get_includes(self.parameters)

    def include(self, query, global_errors=[]):
        """Return a compounded query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        fields, errors = self.make_include_fields()
        if errors:
            global_errors.extend(errors)
            return query, [], [], global_errors
        mappers, selects, schemas = self.make_query_includes(fields)
        return query.include(mappers), selects, schemas, global_errors

    def make_include_fields(self):
        """Return a list of parsed includes."""
        includes, errors = [], []
        for include in self.includes:
            fields, error = self.make_include_field(include)
            includes.append(Includes(fields))
            errors.extend(error)
        return includes, errors

    def make_include_field(self, path):
        """Return a tuple of fields."""
        try:
            return self.view_driver.make_from_path(path, self.view), []
        except AttributeError as exc:
            return [], [self.make_error('include', str(exc))]

    def make_query_includes(self, fields):
        """Return a list of `include` tuples."""
        mappers, selects, schemas = [], [], []
        for include_ in fields:
            component, driver = self.make_query_from_fields(include_)
            mappers.extend(component.joins)
            selects.extend(component.selects)
            schemas.extend(include_.schemas)
        return mappers, selects, schemas

    @property
    @functools.lru_cache()
    def paginators(self):
        """Return a list of page parameters paths."""
        return url.get_paginators(self.parameters)

    def paginate(self, query, global_errors=[]):
        """Return a paginated query or a list of errors.

        Keyword arguments:
            query: ORM query object.
            global_errors (list): List of error messages.
        """
        errors = self._validate_paginators()
        if errors:
            global_errors.extend(errors)
            return query, None, global_errors
        total = query.count()
        return query.apply_paginators(self.paginators), total, global_errors

    def _validate_paginators(self):
        errors = []
        for key, value in self.paginators:
            errors.extend(self._validate_paginator(key, value))
        return errors

    def _validate_paginator(self, key, value):
        error = 'Invalid value "{}" specified.'.format(value)
        if not value.isdigit():
            return [self.make_error('page[{}]'.format(key), error)]
        return []

    def make_error(self, parameter, message):
        """Return a JSONAPI compliant parameter error object.

        Keyword arguments:
            parameter (str): URL parameter name.
            message (str): Human-readable error message.
        """
        return {
            'source': {'parameter': parameter},
            'detail': message
        }

    def make_query_from_fields(self, fields):
        """Return a `Query` tuple from a set of fields."""
        return self.model_driver.make_from_fields(fields, self.model)

    def make_pagination_links(self, base_url, parameters, total):
        """Return a dictionary of pagination links.

        Based on the pagination strategy, calculate the correct limits
        and offsets and encode the parameters into a URL safe format.
        """
        if 'page[number]' in parameters:
            return self._paginate_number(base_url, parameters, total)
        return self._paginate_offset(base_url, parameters, total)

    def _paginate_offset(self, base_url, params, total):
        limit, offset = 50, 0
        for strategy, value in self.paginators:
            if strategy == 'limit':
                limit = int(value)
            elif strategy == 'offset':
                offset = int(value)

        url = base_url + '?{}'
        values = self._build_page_offset_values(total, limit, offset)
        return {
            'first': url.format(self._encode_page_offset(params, values[0])),
            'last': url.format(self._encode_page_offset(params, values[1])),
            'next': url.format(self._encode_page_offset(params, values[2])),
            'prev': url.format(self._encode_page_offset(params, values[3])),
            'self': base_url
        }

    def _paginate_number(self, base_url, params, total):
        limit, page = 50, 1
        for strategy, value in self.paginators:
            if strategy == 'limit':
                limit = int(value)
            elif strategy == 'number':
                page = int(value)

        url = base_url + '?{}'
        values = self._build_page_number_values(total, limit, page)
        return {
            'first': url.format(self._encode_page_number(params, values[0])),
            'last': url.format(self._encode_page_number(params, values[1])),
            'next': url.format(self._encode_page_number(params, values[2])),
            'prev': url.format(self._encode_page_number(params, values[3])),
            'self': base_url
        }

    def _build_page_offset_values(self, total, limit, offset):
        """Return a tuple of offset values.

        The response, in order of position, is `first`, `last`, `next`,
        and `prev`.
        """
        return 0, max(total - limit, 0), offset + limit, max(offset - limit, 0)

    def _build_page_number_values(self, total, limit, current):
        """Return a tuple of page number values.

        The response, in order of position, is `first`, `last`, `next`,
        and `prev`.
        """
        return 1, max(total / limit, 1), current + 1, max(current - 1, 1)

    def _encode_page_offset(self, params, value):
        """Return encoded page[offset] parameters."""
        return self._encode_parameters(params, 'page[offset]', value)

    def _encode_page_number(self, params, value):
        """Return encoded page[number] parameters."""
        return self._encode_parameters(params, 'page[number]', value)

    def _encode_parameters(self, params, key, value):
        """Return a URL encoded parameter object."""
        params = params.copy()
        params[key] = value
        return urlencode(params)

class Includes(object):

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

    def __len__(self):
        return len(self.fields)

    def __getitem__(self, index):
        if index >= len(self):
            raise IndexError
        return self.fields[index]

    @property
    @functools.lru_cache()
    def schemas(self):
        """Return a list of schema instances."""
        return [field.related_class for field in self.fields]
<|endoftext|>


<commit_before>#   Foremast - Pipeline Tooling
#
#   Copyright 2016 Gogo, LLC
#
#   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.
"""Construct a block section of Stages in a Spinnaker Pipeline."""
import collections
import copy
import json
import logging
from pprint import pformat

from ..consts import ASG_WHITELIST, DEFAULT_EC2_SECURITYGROUPS
from ..utils import generate_encoded_user_data, get_template

LOG = logging.getLogger(__name__)

def check_provider_healthcheck(settings, default_provider='Discovery'):
    """Set Provider Health Check when specified.

    Returns:
        collections.namedtuple: **ProviderHealthCheck** with attributes:

            * providers (list): Providers set to use native Health Check.
            * has_healthcheck (bool): If any native Health Checks requested.
    """
    ProviderHealthCheck = collections.namedtuple('ProviderHealthCheck', ['providers', 'has_healthcheck'])

    eureka_enabled = settings['app']['eureka_enabled']
    providers = settings['asg']['provider_healthcheck']

    LOG.debug('Template defined Health Check Providers: %s', providers)

    health_check_providers = []
    has_healthcheck = False

    normalized_default_provider = default_provider.capitalize()

    if eureka_enabled:
        LOG.info('Eureka enabled, enabling default Provider Health Check: %s', normalized_default_provider)

        for provider, active in providers.items():
            if provider.lower() == normalized_default_provider.lower():
                providers[provider] = True
                LOG.debug('Override defined Provider Health Check: %s -> %s', active, providers[provider])
                break
        else:
            LOG.debug('Adding default Provider Health Check: %s', normalized_default_provider)
            providers[normalized_default_provider] = True

    for provider, active in providers.items():
        if active:
            health_check_providers.append(provider.capitalize())
    LOG.info('Provider healthchecks: %s', health_check_providers)

    if len(health_check_providers) > 0:
        has_healthcheck = True

    return ProviderHealthCheck(providers=health_check_providers, has_healthcheck=has_healthcheck)

def get_template_name(env, pipeline_type):
    """Generates the correct template name based on pipeline type

    Args:
        env (str): environment to generate templates for
        pipeline_type (str): Type of pipeline like ec2 or lambda

    Returns:
        str: Name of template
    """
    if pipeline_type == 'ec2':
        if env.startswith('prod'):
            template_name = 'pipeline/pipeline_{}.json.j2'.format(env)
        else:
            template_name = 'pipeline/pipeline_stages.json.j2'
    else:
        if env.startswith('prod'):
            template_name = 'pipeline/pipeline_{}_{}.json.j2'.format(env, pipeline_type)
        else:
            template_name = 'pipeline/pipeline_stages_{}.json.j2'.format(pipeline_type)

    return template_name

def construct_pipeline_block(env='',
                             generated=None,
                             previous_env=None,
                             region='us-east-1',
                             settings=None,
                             pipeline_data=None,
                             pipeline_type='ec2',
                             **kwargs):
    """Create the Pipeline JSON from template.

    This handles the common repeatable patterns in a pipeline, such as
    judgement, infrastructure, tagger and qe.

    Note:
       ASG Health Check type is overridden to `EC2` when deploying to **dev** or
       using :ref:`eureka_enabled`.

    Args:
        env (str): Deploy environment name, e.g. dev, stage, prod.
        generated (gogoutils.Generator): Gogo Application name generator.
        previous_env (str): The previous deploy environment to use as
            Trigger.
        region (str): AWS Region to deploy to.
        settings (dict): Environment settings from configurations.
        region_subnets (dict): Subnets for a Region, e.g.
            {'us-west-2': ['us-west-2a', 'us-west-2b', 'us-west-2c']}.

    Returns:
        dict: Pipeline JSON template rendered with configurations.

    """

    LOG.info('%s block for [%s].', env, region)
    LOG.debug('%s info:\n%s', env, pformat(settings))

    gen_app_name = generated.app_name()
    data = copy.deepcopy(settings)

    setup_kwargs = {
        'appname': gen_app_name,
        'settings': settings,
        'env': env,
        'region': region,
        'project': generated.project
    }

    if pipeline_type == 'ec2':
        setup_kwargs['region_subnets'] = kwargs['region_subnets']
        data = ec2_pipeline_setup(**setup_kwargs)

    data['app'].update({
        'appname': gen_app_name,
        'repo_name': generated.repo,
        'group_name': generated.project,
        'environment': env,
        'region': region,
        'previous_env': previous_env,
        'promote_restrict': pipeline_data['promote_restrict'],
        'owner_email': pipeline_data['owner_email'],
    })

    LOG.debug('Block data:\n%s', pformat(data))

    template_name = get_template_name(env, pipeline_type)
    pipeline_json = get_template(template_file=template_name, data=data)
    return pipeline_json

def ec2_pipeline_setup(**kwargs):
    """Handles ec2 pipeline data setup

    Returns:
        dict: Updated settings to pass to templates for EC2 info
    """

    settings = kwargs['settings']
    appname = kwargs['appname']
    env = kwargs['env']
    region = kwargs['region']
    project = kwargs['project']
    data = copy.deepcopy(settings)

    user_data = generate_encoded_user_data(env=env, region=region, app_name=appname, group_name=project)

    # Use different variable to keep template simple
    instance_security_groups = DEFAULT_EC2_SECURITYGROUPS[env]
    instance_security_groups.append(gen_app_name)
    instance_security_groups.extend(settings['security_group']['instance_extras'])

    LOG.info('Instance security groups to attach: {0}'.format(instance_security_groups))

    # check if scaling policy exists
    if settings['asg']['scaling_policy']:
        scalingpolicy = True
        LOG.info('Found scaling policy')
    else:
        scalingpolicy = False
        LOG.info('No scaling policy found')

    if settings['app']['eureka_enabled']:
        elb = []
    else:
        elb = ['{0}'.format(appname)]
    LOG.info('Attaching the following ELB: {0}'.format(elb))

    health_checks = check_provider_healthcheck(settings)

    # Use EC2 Health Check for DEV or Eureka enabled
    if env == 'dev' or settings['app']['eureka_enabled']:
        data['asg'].update({'hc_type': 'EC2'})
        LOG.info('Switching health check type to: EC2')

    # Aggregate the default grace period, plus the exposed app_grace_period
    # to allow per repo extension of asg healthcheck grace period
    hc_grace_period = data['asg'].get('hc_grace_period')
    app_grace_period = data['asg'].get('app_grace_period')
    grace_period = hc_grace_period + app_grace_period

    # TODO: Migrate the naming logic to an external library to make it easier
    #       to update in the future. Gogo-Utils looks like a good candidate
    ssh_keypair = data['asg'].get('ssh_keypair', None)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))
    if not ssh_keypair:
        ssh_keypair = '{0}_{1}_default'.format(env, region)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))

    if settings['app']['canary']:
        canary_user_data = generate_encoded_user_data(
            env=env, region=region, app_name=appname, group_name=project, canary=True)
        data['app'].update({
            'canary_encoded_user_data': canary_user_data,
        })

    data['asg'].update({
        'hc_type': data['asg'].get('hc_type').upper(),
        'hc_grace_period': grace_period,
        'ssh_keypair': ssh_keypair,
        'provider_healthcheck': json.dumps(health_checks.providers),
        'enable_public_ips': json.dumps(settings['asg']['enable_public_ips']),
        'has_provider_healthcheck': health_checks.has_healthcheck,
        'asg_whitelist': ASG_WHITELIST,
    })

    data['app'].update({
        'az_dict': json.dumps(kwargs['region_subnets']),
        'encoded_user_data': user_data,
        'instance_security_groups': json.dumps(instance_security_groups),
        'elb': json.dumps(elb),
        'scalingpolicy': scalingpolicy,
    })

    return data
<commit_msg>flattened template block and moved formatting to one call<commit_after>#   Foremast - Pipeline Tooling
#
#   Copyright 2016 Gogo, LLC
#
#   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.
"""Construct a block section of Stages in a Spinnaker Pipeline."""
import collections
import copy
import json
import logging
from pprint import pformat

from ..consts import ASG_WHITELIST, DEFAULT_EC2_SECURITYGROUPS
from ..utils import generate_encoded_user_data, get_template

LOG = logging.getLogger(__name__)

def check_provider_healthcheck(settings, default_provider='Discovery'):
    """Set Provider Health Check when specified.

    Returns:
        collections.namedtuple: **ProviderHealthCheck** with attributes:

            * providers (list): Providers set to use native Health Check.
            * has_healthcheck (bool): If any native Health Checks requested.
    """
    ProviderHealthCheck = collections.namedtuple('ProviderHealthCheck', ['providers', 'has_healthcheck'])

    eureka_enabled = settings['app']['eureka_enabled']
    providers = settings['asg']['provider_healthcheck']

    LOG.debug('Template defined Health Check Providers: %s', providers)

    health_check_providers = []
    has_healthcheck = False

    normalized_default_provider = default_provider.capitalize()

    if eureka_enabled:
        LOG.info('Eureka enabled, enabling default Provider Health Check: %s', normalized_default_provider)

        for provider, active in providers.items():
            if provider.lower() == normalized_default_provider.lower():
                providers[provider] = True
                LOG.debug('Override defined Provider Health Check: %s -> %s', active, providers[provider])
                break
        else:
            LOG.debug('Adding default Provider Health Check: %s', normalized_default_provider)
            providers[normalized_default_provider] = True

    for provider, active in providers.items():
        if active:
            health_check_providers.append(provider.capitalize())
    LOG.info('Provider healthchecks: %s', health_check_providers)

    if len(health_check_providers) > 0:
        has_healthcheck = True

    return ProviderHealthCheck(providers=health_check_providers, has_healthcheck=has_healthcheck)

def get_template_name(env, pipeline_type):
    """Generates the correct template name based on pipeline type

    Args:
        env (str): environment to generate templates for
        pipeline_type (str): Type of pipeline like ec2 or lambda

    Returns:
        str: Name of template
    """
    if pipeline_type == 'ec2' and env.startswith('prod'):
        template_name_format = '{pipeline_base}_{env}.json.j2'
    elif pipeline_type == 'ec2':
        template_name_format = '{pipeline_base}_stages.json.j2'
    elif pipeline_type != 'ec2' and env.startswith('prod'):
        template_name_format = '{pipeline_base}_{env}_{pipeline_type}.json.j2'
    else:
        template_name_format = '{pipeline_base}_stages_{pipeline_type}.json.j2'

    pipeline_base = 'pipeline/pipeline'
    template_name = template_name_format.format(pipeline_base=pipeline_base, env=env, pipeline_type=pipeline_type)

    return template_name

def construct_pipeline_block(env='',
                             generated=None,
                             previous_env=None,
                             region='us-east-1',
                             settings=None,
                             pipeline_data=None,
                             pipeline_type='ec2',
                             **kwargs):
    """Create the Pipeline JSON from template.

    This handles the common repeatable patterns in a pipeline, such as
    judgement, infrastructure, tagger and qe.

    Note:
       ASG Health Check type is overridden to `EC2` when deploying to **dev** or
       using :ref:`eureka_enabled`.

    Args:
        env (str): Deploy environment name, e.g. dev, stage, prod.
        generated (gogoutils.Generator): Gogo Application name generator.
        previous_env (str): The previous deploy environment to use as
            Trigger.
        region (str): AWS Region to deploy to.
        settings (dict): Environment settings from configurations.
        region_subnets (dict): Subnets for a Region, e.g.
            {'us-west-2': ['us-west-2a', 'us-west-2b', 'us-west-2c']}.

    Returns:
        dict: Pipeline JSON template rendered with configurations.

    """

    LOG.info('%s block for [%s].', env, region)
    LOG.debug('%s info:\n%s', env, pformat(settings))

    gen_app_name = generated.app_name()
    data = copy.deepcopy(settings)

    setup_kwargs = {
        'appname': gen_app_name,
        'settings': settings,
        'env': env,
        'region': region,
        'project': generated.project
    }

    if pipeline_type == 'ec2':
        setup_kwargs['region_subnets'] = kwargs['region_subnets']
        data = ec2_pipeline_setup(**setup_kwargs)

    data['app'].update({
        'appname': gen_app_name,
        'repo_name': generated.repo,
        'group_name': generated.project,
        'environment': env,
        'region': region,
        'previous_env': previous_env,
        'promote_restrict': pipeline_data['promote_restrict'],
        'owner_email': pipeline_data['owner_email'],
    })

    LOG.debug('Block data:\n%s', pformat(data))

    template_name = get_template_name(env, pipeline_type)
    pipeline_json = get_template(template_file=template_name, data=data)
    return pipeline_json

def ec2_pipeline_setup(**kwargs):
    """Handles ec2 pipeline data setup

    Returns:
        dict: Updated settings to pass to templates for EC2 info
    """

    settings = kwargs['settings']
    appname = kwargs['appname']
    env = kwargs['env']
    region = kwargs['region']
    project = kwargs['project']
    data = copy.deepcopy(settings)

    user_data = generate_encoded_user_data(env=env, region=region, app_name=appname, group_name=project)

    # Use different variable to keep template simple
    instance_security_groups = DEFAULT_EC2_SECURITYGROUPS[env]
    instance_security_groups.append(gen_app_name)
    instance_security_groups.extend(settings['security_group']['instance_extras'])

    LOG.info('Instance security groups to attach: {0}'.format(instance_security_groups))

    # check if scaling policy exists
    if settings['asg']['scaling_policy']:
        scalingpolicy = True
        LOG.info('Found scaling policy')
    else:
        scalingpolicy = False
        LOG.info('No scaling policy found')

    if settings['app']['eureka_enabled']:
        elb = []
    else:
        elb = ['{0}'.format(appname)]
    LOG.info('Attaching the following ELB: {0}'.format(elb))

    health_checks = check_provider_healthcheck(settings)

    # Use EC2 Health Check for DEV or Eureka enabled
    if env == 'dev' or settings['app']['eureka_enabled']:
        data['asg'].update({'hc_type': 'EC2'})
        LOG.info('Switching health check type to: EC2')

    # Aggregate the default grace period, plus the exposed app_grace_period
    # to allow per repo extension of asg healthcheck grace period
    hc_grace_period = data['asg'].get('hc_grace_period')
    app_grace_period = data['asg'].get('app_grace_period')
    grace_period = hc_grace_period + app_grace_period

    # TODO: Migrate the naming logic to an external library to make it easier
    #       to update in the future. Gogo-Utils looks like a good candidate
    ssh_keypair = data['asg'].get('ssh_keypair', None)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))
    if not ssh_keypair:
        ssh_keypair = '{0}_{1}_default'.format(env, region)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))

    if settings['app']['canary']:
        canary_user_data = generate_encoded_user_data(
            env=env, region=region, app_name=appname, group_name=project, canary=True)
        data['app'].update({
            'canary_encoded_user_data': canary_user_data,
        })

    data['asg'].update({
        'hc_type': data['asg'].get('hc_type').upper(),
        'hc_grace_period': grace_period,
        'ssh_keypair': ssh_keypair,
        'provider_healthcheck': json.dumps(health_checks.providers),
        'enable_public_ips': json.dumps(settings['asg']['enable_public_ips']),
        'has_provider_healthcheck': health_checks.has_healthcheck,
        'asg_whitelist': ASG_WHITELIST,
    })

    data['app'].update({
        'az_dict': json.dumps(kwargs['region_subnets']),
        'encoded_user_data': user_data,
        'instance_security_groups': json.dumps(instance_security_groups),
        'elb': json.dumps(elb),
        'scalingpolicy': scalingpolicy,
    })

    return data
<|endoftext|>


<commit_before>#   Foremast - Pipeline Tooling
#
#   Copyright 2016 Gogo, LLC
#
#   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.
"""Construct a block section of Stages in a Spinnaker Pipeline."""
import collections
import copy
import json
import logging
from pprint import pformat

from ..consts import ASG_WHITELIST, DEFAULT_EC2_SECURITYGROUPS
from ..utils import generate_encoded_user_data, get_template

LOG = logging.getLogger(__name__)

def check_provider_healthcheck(settings, default_provider='Discovery'):
    """Set Provider Health Check when specified.

    Returns:
        collections.namedtuple: **ProviderHealthCheck** with attributes:

            * providers (list): Providers set to use native Health Check.
            * has_healthcheck (bool): If any native Health Checks requested.
    """
    ProviderHealthCheck = collections.namedtuple('ProviderHealthCheck', ['providers', 'has_healthcheck'])

    eureka_enabled = settings['app']['eureka_enabled']
    providers = settings['asg']['provider_healthcheck']

    LOG.debug('Template defined Health Check Providers: %s', providers)

    health_check_providers = []
    has_healthcheck = False

    normalized_default_provider = default_provider.capitalize()

    if eureka_enabled:
        LOG.info('Eureka enabled, enabling default Provider Health Check: %s', normalized_default_provider)

        for provider, active in providers.items():
            if provider.lower() == normalized_default_provider.lower():
                providers[provider] = True
                LOG.debug('Override defined Provider Health Check: %s -> %s', active, providers[provider])
                break
        else:
            LOG.debug('Adding default Provider Health Check: %s', normalized_default_provider)
            providers[normalized_default_provider] = True

    for provider, active in providers.items():
        if active:
            health_check_providers.append(provider.capitalize())
    LOG.info('Provider healthchecks: %s', health_check_providers)

    if len(health_check_providers) > 0:
        has_healthcheck = True

    return ProviderHealthCheck(providers=health_check_providers, has_healthcheck=has_healthcheck)

def construct_pipeline_block(env='',
                             generated=None,
                             previous_env=None,
                             region='us-east-1',
                             region_subnets=None,
                             settings=None,
                             pipeline_data=None):
    """Create the Pipeline JSON from template.

    This handles the common repeatable patterns in a pipeline, such as
    judgement, infrastructure, tagger and qe.

    Args:
        env (str): Deploy environment name, e.g. dev, stage, prod.
        generated (gogoutils.Generator): Gogo Application name generator.
        previous_env (str): The previous deploy environment to use as
            Trigger.
        region (str): AWS Region to deploy to.
        settings (dict): Environment settings from configurations.
        region_subnets (dict): Subnets for a Region, e.g.
            {'us-west-2': ['us-west-2a', 'us-west-2b', 'us-west-2c']}.

    Returns:
        dict: Pipeline JSON template rendered with configurations.
    """
    LOG.info('%s block for [%s].', env, region)

    if env.startswith('prod'):
        template_name = 'pipeline/pipeline_{}.json.j2'.format(env)
    else:
        template_name = 'pipeline/pipeline_stages.json.j2'

    LOG.debug('%s info:\n%s', env, pformat(settings))

    gen_app_name = generated.app_name()
    user_data = generate_encoded_user_data(env=env, region=region, app_name=gen_app_name, group_name=generated.project)

    # Use different variable to keep template simple
    instance_security_groups = list(DEFAULT_EC2_SECURITYGROUPS)
    instance_security_groups.append(gen_app_name)
    instance_security_groups.extend(settings['security_group']['instance_extras'])

    LOG.info('Instance security groups to attach: {0}'.format(instance_security_groups))

    # check if scaling policy exists
    if settings['asg']['scaling_policy']:
        scalingpolicy = True
        LOG.info('Found scaling policy')
    else:
        scalingpolicy = False
        LOG.info('No scaling policy found')

    if settings['app']['eureka_enabled']:
        elb = []
    else:
        elb = ['{0}'.format(gen_app_name)]
    LOG.info('Attaching the following ELB: {0}'.format(elb))

    health_checks = check_provider_healthcheck(settings)

    data = copy.deepcopy(settings)

    # Use EC2 Health Check for DEV or Eureka enabled
    if env == 'dev' or settings['app']['eureka_enabled']:
        data['asg'].update({'hc_type': 'EC2'})
        LOG.info('Switching health check type to: EC2')

    # Aggregate the default grace period, plus the exposed app_grace_period
    # to allow per repo extension of asg healthcheck grace period
    hc_grace_period = data['asg'].get('hc_grace_period')
    app_grace_period = data['asg'].get('app_grace_period')
    grace_period = hc_grace_period + app_grace_period

    # TODO: Migrate the naming logic to an external library to make it easier
    #       to update in the future. Gogo-Utils looks like a good candidate
    ssh_keypair = data['asg'].get('ssh_keypair', None)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))
    if not ssh_keypair:
        ssh_keypair = '{0}_{1}_default'.format(env, region)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))

    data['app'].update({
        'appname': gen_app_name,
        'repo_name': generated.repo,
        'group_name': generated.project,
        'environment': env,
        'region': region,
        'az_dict': json.dumps(region_subnets),
        'previous_env': previous_env,
        'encoded_user_data': user_data,
        'instance_security_groups': json.dumps(instance_security_groups),
        'elb': json.dumps(elb),
        'promote_restrict': pipeline_data['promote_restrict'],
        'owner_email': pipeline_data['owner_email'],
        'scalingpolicy': scalingpolicy,
    })

    if settings['app']['canary']:
        canary_user_data = generate_encoded_user_data(env=env, region=region, app_name=gen_app_name, group_name=generated.project, canary=True)
        data['app'].update({
            'canary_encoded_user_data': canary_user_data,
        })

    data['asg'].update({
        'hc_type': data['asg'].get('hc_type').upper(),
        'hc_grace_period': grace_period,
        'ssh_keypair': ssh_keypair,
        'provider_healthcheck': json.dumps(health_checks.providers),
        'enable_public_ips': json.dumps(settings['asg']['enable_public_ips']),
        'has_provider_healthcheck': health_checks.has_healthcheck,
        'asg_whitelist': ASG_WHITELIST,
    })

    LOG.debug('Block data:\n%s', pformat(data))

    pipeline_json = get_template(template_file=template_name, data=data)
    return pipeline_json
<commit_msg>docs: ASG Health Check type override note<commit_after>#   Foremast - Pipeline Tooling
#
#   Copyright 2016 Gogo, LLC
#
#   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.
"""Construct a block section of Stages in a Spinnaker Pipeline."""
import collections
import copy
import json
import logging
from pprint import pformat

from ..consts import ASG_WHITELIST, DEFAULT_EC2_SECURITYGROUPS
from ..utils import generate_encoded_user_data, get_template

LOG = logging.getLogger(__name__)

def check_provider_healthcheck(settings, default_provider='Discovery'):
    """Set Provider Health Check when specified.

    Returns:
        collections.namedtuple: **ProviderHealthCheck** with attributes:

            * providers (list): Providers set to use native Health Check.
            * has_healthcheck (bool): If any native Health Checks requested.
    """
    ProviderHealthCheck = collections.namedtuple('ProviderHealthCheck', ['providers', 'has_healthcheck'])

    eureka_enabled = settings['app']['eureka_enabled']
    providers = settings['asg']['provider_healthcheck']

    LOG.debug('Template defined Health Check Providers: %s', providers)

    health_check_providers = []
    has_healthcheck = False

    normalized_default_provider = default_provider.capitalize()

    if eureka_enabled:
        LOG.info('Eureka enabled, enabling default Provider Health Check: %s', normalized_default_provider)

        for provider, active in providers.items():
            if provider.lower() == normalized_default_provider.lower():
                providers[provider] = True
                LOG.debug('Override defined Provider Health Check: %s -> %s', active, providers[provider])
                break
        else:
            LOG.debug('Adding default Provider Health Check: %s', normalized_default_provider)
            providers[normalized_default_provider] = True

    for provider, active in providers.items():
        if active:
            health_check_providers.append(provider.capitalize())
    LOG.info('Provider healthchecks: %s', health_check_providers)

    if len(health_check_providers) > 0:
        has_healthcheck = True

    return ProviderHealthCheck(providers=health_check_providers, has_healthcheck=has_healthcheck)

def construct_pipeline_block(env='',
                             generated=None,
                             previous_env=None,
                             region='us-east-1',
                             region_subnets=None,
                             settings=None,
                             pipeline_data=None):
    """Create the Pipeline JSON from template.

    This handles the common repeatable patterns in a pipeline, such as
    judgement, infrastructure, tagger and qe.

    Note:
       ASG Health Check type is overridden to `EC2` when deploying to **dev** or
       using :ref:`eureka_enabled`.

    Args:
        env (str): Deploy environment name, e.g. dev, stage, prod.
        generated (gogoutils.Generator): Gogo Application name generator.
        previous_env (str): The previous deploy environment to use as
            Trigger.
        region (str): AWS Region to deploy to.
        settings (dict): Environment settings from configurations.
        region_subnets (dict): Subnets for a Region, e.g.
            {'us-west-2': ['us-west-2a', 'us-west-2b', 'us-west-2c']}.

    Returns:
        dict: Pipeline JSON template rendered with configurations.

    """
    LOG.info('%s block for [%s].', env, region)

    if env.startswith('prod'):
        template_name = 'pipeline/pipeline_{}.json.j2'.format(env)
    else:
        template_name = 'pipeline/pipeline_stages.json.j2'

    LOG.debug('%s info:\n%s', env, pformat(settings))

    gen_app_name = generated.app_name()
    user_data = generate_encoded_user_data(env=env, region=region, app_name=gen_app_name, group_name=generated.project)

    # Use different variable to keep template simple
    instance_security_groups = list(DEFAULT_EC2_SECURITYGROUPS)
    instance_security_groups.append(gen_app_name)
    instance_security_groups.extend(settings['security_group']['instance_extras'])

    LOG.info('Instance security groups to attach: {0}'.format(instance_security_groups))

    # check if scaling policy exists
    if settings['asg']['scaling_policy']:
        scalingpolicy = True
        LOG.info('Found scaling policy')
    else:
        scalingpolicy = False
        LOG.info('No scaling policy found')

    if settings['app']['eureka_enabled']:
        elb = []
    else:
        elb = ['{0}'.format(gen_app_name)]
    LOG.info('Attaching the following ELB: {0}'.format(elb))

    health_checks = check_provider_healthcheck(settings)

    data = copy.deepcopy(settings)

    # Use EC2 Health Check for DEV or Eureka enabled
    if env == 'dev' or settings['app']['eureka_enabled']:
        data['asg'].update({'hc_type': 'EC2'})
        LOG.info('Switching health check type to: EC2')

    # Aggregate the default grace period, plus the exposed app_grace_period
    # to allow per repo extension of asg healthcheck grace period
    hc_grace_period = data['asg'].get('hc_grace_period')
    app_grace_period = data['asg'].get('app_grace_period')
    grace_period = hc_grace_period + app_grace_period

    # TODO: Migrate the naming logic to an external library to make it easier
    #       to update in the future. Gogo-Utils looks like a good candidate
    ssh_keypair = data['asg'].get('ssh_keypair', None)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))
    if not ssh_keypair:
        ssh_keypair = '{0}_{1}_default'.format(env, region)
    LOG.info('SSH keypair ({0}) used'.format(ssh_keypair))

    data['app'].update({
        'appname': gen_app_name,
        'repo_name': generated.repo,
        'group_name': generated.project,
        'environment': env,
        'region': region,
        'az_dict': json.dumps(region_subnets),
        'previous_env': previous_env,
        'encoded_user_data': user_data,
        'instance_security_groups': json.dumps(instance_security_groups),
        'elb': json.dumps(elb),
        'promote_restrict': pipeline_data['promote_restrict'],
        'owner_email': pipeline_data['owner_email'],
        'scalingpolicy': scalingpolicy,
    })

    if settings['app']['canary']:
        canary_user_data = generate_encoded_user_data(env=env, region=region, app_name=gen_app_name, group_name=generated.project, canary=True)
        data['app'].update({
            'canary_encoded_user_data': canary_user_data,
        })

    data['asg'].update({
        'hc_type': data['asg'].get('hc_type').upper(),
        'hc_grace_period': grace_period,
        'ssh_keypair': ssh_keypair,
        'provider_healthcheck': json.dumps(health_checks.providers),
        'enable_public_ips': json.dumps(settings['asg']['enable_public_ips']),
        'has_provider_healthcheck': health_checks.has_healthcheck,
        'asg_whitelist': ASG_WHITELIST,
    })

    LOG.debug('Block data:\n%s', pformat(data))

    pipeline_json = get_template(template_file=template_name, data=data)
    return pipeline_json
<|endoftext|>


<commit_before>import matplotlib as mpl
import numpy
import PIL

from . import _files

def draw_image(data, obj):
    """Returns the PGFPlots code for an image environment.
    """
    content = []

    filename, rel_filepath = _files.new_filename(data, "img", ".png")

    # store the image as in a file
    img_array = obj.get_array()

    dims = img_array.shape
    if len(dims) == 2:  # the values are given as one real number: look at cmap
        clims = obj.get_clim()
        mpl.pyplot.imsave(
            fname=filename,
            arr=img_array,
            cmap=obj.get_cmap(),
            vmin=clims[0],
            vmax=clims[1],
            origin=obj.origin,
        )
    else:
        # RGB (+alpha) information at each point
        assert len(dims) == 3 and dims[2] in [3, 4]
        # convert to PIL image
        if obj.origin == "lower":
            img_array = numpy.flipud(img_array)

        # Convert mpl image to PIL
        image = PIL.Image.fromarray(numpy.uint8(img_array * 255))

        # If the input image is PIL:
        # image = PIL.Image.fromarray(img_array)

        image.save(filename, origin=obj.origin)

    # write the corresponding information to the TikZ file
    extent = obj.get_extent()

    # the format specification will only accept tuples
    if not isinstance(extent, tuple):
        extent = tuple(extent)

    # Explicitly use \pgfimage as includegrapics command, as the default
    # \includegraphics fails unexpectedly in some cases
    ff = data["float format"]
    content.append(
        "\\addplot graphics [includegraphics cmd=\\pgfimage,"
        f"xmin={extent[0]:{ff}}, xmax={extent[1]:{ff}}, "
        f"ymin={extent[2]:{ff}}, ymax={extent[3]:{ff}}] {{{rel_filepath}}};\n"
    )
    return data, content
<commit_msg>don't multiply by 255 is data is already uint8<commit_after>import matplotlib as mpl
import numpy
import PIL

from . import _files

def draw_image(data, obj):
    """Returns the PGFPlots code for an image environment.
    """
    content = []

    filename, rel_filepath = _files.new_filename(data, "img", ".png")

    # store the image as in a file
    img_array = obj.get_array()

    dims = img_array.shape
    if len(dims) == 2:  # the values are given as one real number: look at cmap
        clims = obj.get_clim()
        mpl.pyplot.imsave(
            fname=filename,
            arr=img_array,
            cmap=obj.get_cmap(),
            vmin=clims[0],
            vmax=clims[1],
            origin=obj.origin,
        )
    else:
        # RGB (+alpha) information at each point
        assert len(dims) == 3 and dims[2] in [3, 4]
        # convert to PIL image
        if obj.origin == "lower":
            img_array = numpy.flipud(img_array)

        # Convert mpl image to PIL
        if img_array.dtype != numpy.uint8:
            img_array = numpy.uint8(img_array * 255)
        image = PIL.Image.fromarray(numpy.uint8(img_array * 255))

        # If the input image is PIL:
        # image = PIL.Image.fromarray(img_array)

        image.save(filename, origin=obj.origin)

    # write the corresponding information to the TikZ file
    extent = obj.get_extent()

    # the format specification will only accept tuples
    if not isinstance(extent, tuple):
        extent = tuple(extent)

    # Explicitly use \pgfimage as includegrapics command, as the default
    # \includegraphics fails unexpectedly in some cases
    ff = data["float format"]
    content.append(
        "\\addplot graphics [includegraphics cmd=\\pgfimage,"
        f"xmin={extent[0]:{ff}}, xmax={extent[1]:{ff}}, "
        f"ymin={extent[2]:{ff}}, ymax={extent[3]:{ff}}] {{{rel_filepath}}};\n"
    )
    return data, content
<|endoftext|>


<commit_before># !/usr/bin/python
# -*- coding: cp1252 -*-
#
##################################################################################
#
#    Copyright 2015 Félix Brezo and Yaiza Rubio (i3visio, contacto@i3visio.com)
#
#    This program is part of OSRFramework. 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 argparse
import json
import logging
import re
import sys
import urllib2

import osrframework.utils.browser as browser
import osrframework.thirdparties.skype.checkInSkype as skype
from osrframework.utils.platforms import Platform

import Skype4Py

class Skype(Platform):
    """
        A <Platform> object for Skype.
    """
    def __init__(self):
        """
            Constructor...
        """
        self.platformName = "Skype"
        self.tags = ["messaging"]

        ########################
        # Defining valid modes #
        ########################
        self.isValidMode = {}
        self.isValidMode["phonefy"] = False
        self.isValidMode["usufy"] = True
        self.isValidMode["searchfy"] = True

        ######################################
        # Search URL for the different modes #
        ######################################
        # Strings with the URL for each and every mode
        self.url = {}
        #self.url["phonefy"] = "http://anyurl.com//phone/" + "<phonefy>"
        self.url["usufy"] = ""
        self.url["searchfy"] = ""

        ######################################
        # Whether the user needs credentials #
        ######################################
        self.needsCredentials = {}
        #self.needsCredentials["phonefy"] = False
        self.needsCredentials["usufy"] = False
        self.needsCredentials["searchfy"] = False

        #################
        # Valid queries #
        #################
        # Strings that will imply that the query number is not appearing
        self.validQuery = {}
        # The regular expression '.*' will match any query.
        #self.validQuery["phonefy"] = re.compile(".*")
        self.validQuery["usufy"] = re.compile(".*")
        self.validQuery["searchfy"] = re.compile(".*")

        ###################
        # Not_found clues #
        ###################
        # Strings that will imply that the query number is not appearing
        self.notFoundText = {}
        #self.notFoundText["phonefy"] = []
        self.notFoundText["usufy"] = [] # N/A in Skype
        self.notFoundText["searchfy"] = [] # N/A in Skype

        #########################
        # Fields to be searched #
        #########################
        self.fieldsRegExp = {}

        # Definition of regular expressions to be searched in phonefy mode
        #self.fieldsRegExp["phonefy"] = {}
        # Example of fields:
        #self.fieldsRegExp["phonefy"]["i3visio.location"] = ""

        # Definition of regular expressions to be searched in usufy mode
        self.fieldsRegExp["usufy"] = {}
        # Example of fields:
        #self.fieldsRegExp["usufy"]["i3visio.location"] = ""
        # Definition of regular expressions to be searched in searchfy mode
        self.fieldsRegExp["searchfy"] = {}
        # Example of fields:
        #self.fieldsRegExp["searchfy"]["i3visio.location"] = ""

        ################
        # Fields found #
        ################
        # This attribute will be feeded when running the program.
        self.foundFields = {}

    def processData(self, uri=None, data=None, mode=None):
        '''
            Method that process the data in a Skype User.

            :return:    A i3visio-like object.
        '''
        info = []

        # splitting info
        pairs = data.split('; ')

        for p in pairs:
            parts = p.split(':')

            aux = {}
            aux["type"] = parts[0]
            aux["value"] = parts[1]
            aux["attributes"] = {}

            info.append(aux)
        return json.dumps(info)

    def processSkypeUser(self, user, handle=None):
        '''
        '''
        aux = {}
        aux["type"] = "i3visio.profile"
        if handle==None:
            handle = str(user.Handle)
        aux["value"] = self.platformName + " - " + handle
        #info = "Username:"#Aliases;Nombre Completo;País;Provincia;Ciudad;Página web;Tfno.Casa;Tfno.Móvil;TfnoOficina;OnlineStatus;MoodText\n"
        #info += user.Handle + ";" #+ str(user.Aliases) +";" + user.FullName + ";" + user.Country + ";" + user.Province + ";" + user.City + ";" + user.Homepage + ";"  + user.PhoneHome +";" + user.PhoneMobile + ";" + user.PhoneOffice  +  ";" + user.OnlineStatus + ";" + user.MoodText +'\n'
        info = ""
        try:
            info += "i3visio.aliases:" + str(user.Aliases)+";i3visio.fullname:" + str(user.FullName) + ";i3visio.location:" + str(user.Country)
            aux["attributes"] = self.processData(data=info, mode=mode)

        except:
            # Capturing exception in case any kind of special character was found
            aux["attributes"] = []

        return aux
    def getInfo(self, query=None, process = False, mode="usufy"):
        '''
            Method that checks the presence of a given query and recovers the first list of complains.

            :param query: Phone number to verify.
            :param proces:  Calling the processing function.
            :param mode:    Mode to be executed.

            :return:    Python structure for the html processed.
        '''
        # Defining variables for this process
        results = {}
        data = ""
        if not self.modeIsValid(mode=mode):
            # TO-DO: InvalidModeException
            #print "InvalidModeException"
            return json.dumps(results)

        try:
            logger = logging.getLogger("osrframework.wrappers")
            # Verifying if the nick is a correct nick
            if self._isValidQuery(query, mode):
                logger.debug("Starting Skype client...")

                logger.warning("A Skype client must be set up... Note that the program will need a valid session of Skype having been started. If you were performing too many searches, the server may block or ban your account depending on the ToS. Please run this program under your own responsibility.")
                # Instantiate Skype object, all further actions are done
                # using this object.

                # Dealing with UTF8
                import codecs
                import sys

                UTF8Writer = codecs.getwriter('utf8')
                sys.stdout = UTF8Writer(sys.stdout)

                # Search for users and display their Skype name, full name
                # and country.
                data = skype.checkInSkype(query)
        except:
            # No information was found, then we return a null entity
            return json.dumps(results)

        # Verifying if the platform exists
        if mode == "usufy":
            for user in data:
                if user["value"] == query.lower():
                    results = self.processSkypeUser(user)
        elif mode == "searchfy":
            results["type"] = "i3visio.search"
            results["value"] = self.platformName + " Search - " + query
            results["attributes"] = data
            """for user in data:
                #print json.dumps(user, indent=2)
                results["attributes"].append(user)
                #results["attributes"].append(self.processSkypeUser(user, handle=query))"""

        return json.dumps(results)

<commit_msg>Skype module fixed to be used in usufy searches.<commit_after># !/usr/bin/python
# -*- coding: cp1252 -*-
#
##################################################################################
#
#    Copyright 2015 Félix Brezo and Yaiza Rubio (i3visio, contacto@i3visio.com)
#
#    This program is part of OSRFramework. 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 argparse
import json
import logging
import re
import sys
import urllib2

import osrframework.utils.browser as browser
import osrframework.thirdparties.skype.checkInSkype as skype
from osrframework.utils.platforms import Platform

import Skype4Py

class Skype(Platform):
    """
        A <Platform> object for Skype.
    """
    def __init__(self):
        """
            Constructor...
        """
        self.platformName = "Skype"
        self.tags = ["messaging"]

        ########################
        # Defining valid modes #
        ########################
        self.isValidMode = {}
        self.isValidMode["phonefy"] = False
        self.isValidMode["usufy"] = True
        self.isValidMode["searchfy"] = True

        ######################################
        # Search URL for the different modes #
        ######################################
        # Strings with the URL for each and every mode
        self.url = {}
        #self.url["phonefy"] = "http://anyurl.com//phone/" + "<phonefy>"
        self.url["usufy"] = ""
        self.url["searchfy"] = ""

        ######################################
        # Whether the user needs credentials #
        ######################################
        self.needsCredentials = {}
        #self.needsCredentials["phonefy"] = False
        self.needsCredentials["usufy"] = False
        self.needsCredentials["searchfy"] = False

        #################
        # Valid queries #
        #################
        # Strings that will imply that the query number is not appearing
        self.validQuery = {}
        # The regular expression '.*' will match any query.
        #self.validQuery["phonefy"] = re.compile(".*")
        self.validQuery["usufy"] = re.compile(".*")
        self.validQuery["searchfy"] = re.compile(".*")

        ###################
        # Not_found clues #
        ###################
        # Strings that will imply that the query number is not appearing
        self.notFoundText = {}
        #self.notFoundText["phonefy"] = []
        self.notFoundText["usufy"] = [] # N/A in Skype
        self.notFoundText["searchfy"] = [] # N/A in Skype

        #########################
        # Fields to be searched #
        #########################
        self.fieldsRegExp = {}

        # Definition of regular expressions to be searched in phonefy mode
        #self.fieldsRegExp["phonefy"] = {}
        # Example of fields:
        #self.fieldsRegExp["phonefy"]["i3visio.location"] = ""

        # Definition of regular expressions to be searched in usufy mode
        self.fieldsRegExp["usufy"] = {}
        # Example of fields:
        #self.fieldsRegExp["usufy"]["i3visio.location"] = ""
        # Definition of regular expressions to be searched in searchfy mode
        self.fieldsRegExp["searchfy"] = {}
        # Example of fields:
        #self.fieldsRegExp["searchfy"]["i3visio.location"] = ""

        ################
        # Fields found #
        ################
        # This attribute will be feeded when running the program.
        self.foundFields = {}

    def processData(self, uri=None, data=None, mode=None):
        '''
            Method that process the data in a Skype User.

            :return:    A i3visio-like object.
        '''
        info = []

        # splitting info
        pairs = data.split('; ')

        for p in pairs:
            parts = p.split(':')

            aux = {}
            aux["type"] = parts[0]
            aux["value"] = parts[1]
            aux["attributes"] = {}

            info.append(aux)
        return json.dumps(info)

    def processSkypeUser(self, user, handle=None):
        '''
        '''
        aux = {}
        aux["type"] = "i3visio.profile"
        if handle==None:
            handle = str(user.Handle)
        aux["value"] = self.platformName + " - " + handle
        #info = "Username:"#Aliases;Nombre Completo;País;Provincia;Ciudad;Página web;Tfno.Casa;Tfno.Móvil;TfnoOficina;OnlineStatus;MoodText\n"
        #info += user.Handle + ";" #+ str(user.Aliases) +";" + user.FullName + ";" + user.Country + ";" + user.Province + ";" + user.City + ";" + user.Homepage + ";"  + user.PhoneHome +";" + user.PhoneMobile + ";" + user.PhoneOffice  +  ";" + user.OnlineStatus + ";" + user.MoodText +'\n'
        info = ""
        try:
            info += "i3visio.aliases:" + str(user.Aliases)+";i3visio.fullname:" + str(user.FullName) + ";i3visio.location:" + str(user.Country)
            aux["attributes"] = self.processData(data=info, mode=mode)

        except:
            # Capturing exception in case any kind of special character was found
            aux["attributes"] = []

        return aux
    def getInfo(self, query=None, process = False, mode="usufy"):
        '''
            Method that checks the presence of a given query and recovers the first list of complains.

            :param query: Phone number to verify.
            :param proces:  Calling the processing function.
            :param mode:    Mode to be executed.

            :return:    Python structure for the html processed.
        '''
        # Defining variables for this process
        results = {}
        data = ""
        if not self.modeIsValid(mode=mode):
            # TO-DO: InvalidModeException
            #print "InvalidModeException"
            return json.dumps(results)

        try:
            logger = logging.getLogger("osrframework.wrappers")
            # Verifying if the nick is a correct nick
            if self._isValidQuery(query, mode):
                logger.debug("Starting Skype client...")

                logger.warning("A Skype client must be set up... Note that the program will need a valid session of Skype having been started. If you were performing too many searches, the server may block or ban your account depending on the ToS. Please run this program under your own responsibility.")
                # Instantiate Skype object, all further actions are done
                # using this object.

                # Dealing with UTF8
                import codecs
                import sys

                UTF8Writer = codecs.getwriter('utf8')
                sys.stdout = UTF8Writer(sys.stdout)

                # Search for users and display their Skype name, full name
                # and country.
                data = skype.checkInSkype(query)
        except:
            # No information was found, then we return a null entity
            return json.dumps(results)

        # Verifying if the platform exists
        if mode == "usufy":
            for user in data:
                if user["value"] == query.lower():
                    results = user
        elif mode == "searchfy":
            results["type"] = "i3visio.search"
            results["value"] = self.platformName + " Search - " + query
            results["attributes"] = data

        return json.dumps(results)

<|endoftext|>