<commit_before>"""(c) All rights reserved. ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE, Switzerland, VPSI, 2017"""
import logging
import os
import csv

class Utils:

    @staticmethod
    def csv_to_dict(file_path, delimiter=','):
        """Returns the rows of the given CSV file as a list of dicts"""
        rows = []
        with open(file_path) as csvfile:
            reader = csv.DictReader(csvfile, delimiter=delimiter)
            for row in reader:
                rows.append(row)
        return rows

    @staticmethod
    def get_optional_env(key, default):
        """
        Return the value of an optional environment variable, and use
        the provided default if it's not set.
        """
        if not os.environ.get(key):
            logging.warning("The optional environment variable %s is not set, using '%s' as default" % (key, default))

        return os.environ.get(key, default)

    @staticmethod
    def get_mandatory_env(key):

        if not os.environ.get(key):
            msg = "The mandatory environment variable {} is not set".format(key)
            logging.error(msg)
            raise Exception(msg)

        return os.environ.get(key)

    @staticmethod
    def set_logging_config(args):
        """
        Set logging with the 'good' level
        """
        level = logging.INFO

        if args['--quiet']:
            level = logging.WARNING
        elif args['--debug']:
            level = logging.DEBUG

        logging.basicConfig()
        logger = logging.getLogger()
        logger.setLevel(level)

        # set up logging to file
        fh = logging.FileHandler(Utils.get_optional_env('LOGGING_FILE', 'jahia2wp.log'))
        fh.setLevel(level)
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)

        # add the handlers to the logger
        logger.addHandler(fh)
<commit_msg>added helpers to generate passwords, usernames<commit_after>"""(c) All rights reserved. ECOLE POLYTECHNIQUE FEDERALE DE LAUSANNE, Switzerland, VPSI, 2017"""
import logging
import os
import csv
import string
import binascii
import random

class Utils(object):
    """Generic and all-purpose helpers"""

    @staticmethod
    def csv_to_dict(file_path, delimiter=','):
        """Returns the rows of the given CSV file as a list of dicts"""
        rows = []
        with open(file_path) as csvfile:
            reader = csv.DictReader(csvfile, delimiter=delimiter)
            for row in reader:
                rows.append(row)
        return rows

    @staticmethod
    def get_optional_env(key, default):
        """
        Return the value of an optional environment variable, and use
        the provided default if it's not set.
        """
        if not os.environ.get(key):
            logging.warning(
                "The optional environment variable %s is not set, using '%s' as default", key, default)

        return os.environ.get(key, default)

    @staticmethod
    def get_mandatory_env(key):

        if not os.environ.get(key):
            msg = "The mandatory environment variable {} is not set".format(
                key)
            logging.error(msg)
            raise Exception(msg)

        return os.environ.get(key)

    @staticmethod
    def set_logging_config(args):
        """
        Set logging with the 'good' level
        """
        level = logging.INFO

        if args['--quiet']:
            level = logging.WARNING
        elif args['--debug']:
            level = logging.DEBUG

        logging.basicConfig()
        logger = logging.getLogger()
        logger.setLevel(level)

        # set up logging to file
        fh = logging.FileHandler(Utils.get_optional_env(
            'LOGGING_FILE', 'jahia2wp.log'))
        fh.setLevel(level)
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)

        # add the handlers to the logger
        logger.addHandler(fh)

    @staticmethod
    def generate_random_b64(length):
        """
        Generate a random string encoded with base 64
        """
        return binascii.hexlify(os.urandom(int(length / 2))).decode("utf-8")

    @staticmethod
    def generate_password(length, symbols='!@#$%^&*()'):
        """
        Generate a random password
        """
        # the chars we are going to use. We don't use the plus sign (+) because
        # it's problematic in URLs
        chars = string.ascii_letters + string.digits + symbols
        random.seed = (os.urandom(1024))

        return ''.join(random.choice(chars) for i in range(length))
<|endoftext|>


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

from __future__ import print_function

import ast
import os
import re
import sys

import click
import pylint.lint

import travis_helpers
from getaddons import get_modules_changed, is_module
from git_run import GitRun

try:
    import ConfigParser
except ImportError:
    import configparser as ConfigParser

CLICK_DIR = click.Path(exists=True, dir_okay=True, resolve_path=True)

def get_extra_params(odoo_version):
    """Get extra pylint params by odoo version
    Transform a seudo-pylint-conf to params,
    to overwrite base-pylint-conf values.
    Use a seudo-inherit of configuration file.
    To avoid having 2 config files (stable and pr-conf) by each odoo-version
    Example:

        pylint_master.conf
        pylint_master_pr.conf
        pylint_90.conf
        pylint_90_pr.conf
        pylint_80.conf
        pylint_80_pr.conf
        pylint_70.conf
        pylint_70_pr.conf
        pylint_61.conf
        pylint_61_pr.conf
        ... and new future versions.

    If you need to add new conventions in all versions,
    you will need to change all pr files or stable files.

    With this method you can use:

        pylint_lastest.conf
        pylint_lastest_pr.conf
        pylint_disabling_70.conf <- Overwrite params of pylint_lastest*.conf
        pylint_disabling_61.conf <- Overwrite params of pylint_lastest*.conf

    If you need to add new conventions in all versions, you will only need to
    change pylint_lastest_pr.conf or pylint_lastest.conf, similar to inherit.

    :param version: String to specify an Odoo's name or versio
    :return: List of extra pylint params
    """
    is_version_number = re.match(r'\d+\.\d+', odoo_version)
    beta_msgs = get_beta_msgs()
    extra_params_cmd = [
        '--sys-paths', os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'pylint_deprecated_modules'),
        '--extra-params', '--load-plugins=pylint_odoo']

    extra_params = list(extra_params_cmd)
    if is_version_number:
        extra_params.extend([
            '--extra-params', '--valid_odoo_versions=%s' % odoo_version])

    odoo_version = odoo_version.replace('.', '')
    version_cfg = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        'cfg/travis_run_pylint_exclude_%s.cfg' % (odoo_version))
    params = []
    if os.path.isfile(version_cfg):
        config = ConfigParser.ConfigParser()
        config.readfp(open(version_cfg))
        for section in config.sections():
            for option, value in config.items(section):
                params.extend(['--' + option, value])

    for param in params:
        extra_params.extend(['--extra-params', param])
    for beta_msg in beta_msgs:
        extra_params.extend(['--msgs-no-count', beta_msg,
                             '--extra-params', '--enable=%s' % beta_msg])
    return extra_params

def get_beta_msgs():
    """Get beta msgs from beta.cfg file
    :return: List of strings with beta message names"""
    beta_cfg = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        'cfg/travis_run_pylint_beta.cfg')
    if not os.path.isfile(beta_cfg):
        return []
    config = ConfigParser.ConfigParser()
    config.readfp(open(beta_cfg))
    return [
        msg.strip()
        for msg in config.get('MESSAGES CONTROL', 'enable').split(',')
        if msg.strip()]

def get_modules_cmd(dir):
    modules_cmd = []
    include_lint = os.environ.get('INCLUDE_LINT')
    if include_lint:
        for path in include_lint.split(' '):
            modules_cmd.extend(['--path', path])
    else:
        modules_cmd.extend(["--path", dir])
    return modules_cmd

def version_validate(version, dir):
    if not version and dir:
        repo_path = os.path.join(dir, '.git')
        branch_name = GitRun(repo_path).get_branch_name()
        version = (branch_name.replace('_', '-').split('-')[:1]
                   if branch_name else False)
        version = version[0] if version else None
    if not version:
        print (travis_helpers.yellow(
            'Undefined environment variable'
            ' `VERSION`.\nSet `VERSION` for '
            'compatibility with guidelines by version.'))
    return version

def get_branch_base():
    branch_base = os.environ.get('TRAVIS_BRANCH') or os.environ.get('VERSION')
    if branch_base != 'HEAD':
        branch_base = 'origin/' + (branch_base and branch_base or '')
    return branch_base

def pylint_run(is_pr, version, dir):
    # Look for an environment variable
    # whose value is the name of a proper configuration file for pylint
    # (this file will then be expected to be found in the 'cfg/' folder).
    # If such an environment variable is not found,
    # it defaults to the standard configuration file.
    pylint_config_file = os.environ.get(
        'PYLINT_CONFIG_FILE', 'travis_run_pylint.cfg')
    pylint_rcfile = os.path.join(
        os.path.dirname(os.path.realpath(__file__)), 'cfg', pylint_config_file)
    pylint_rcfile_pr = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        'cfg', "travis_run_pylint_pr.cfg")
    odoo_version = version_validate(version, dir)
    modules_cmd = get_modules_cmd(dir)
    beta_msgs = get_beta_msgs()
    branch_base = get_branch_base()
    extra_params_cmd = get_extra_params(odoo_version)
    extra_info = "extra_params_cmd %s " % extra_params_cmd
    print (extra_info)
    conf = ["--config-file=%s" % (pylint_rcfile)]
    cmd = conf + modules_cmd + extra_params_cmd

    real_errors = main(cmd, standalone_mode=False)
    res = dict(
        (key, value) for key, value in (real_errors.get(
            'by_msg') or {}).items() if key not in beta_msgs)
    count_errors = get_count_fails(real_errors, list(beta_msgs))
    count_info = "count_errors %s" % count_errors
    print (count_info)
    if is_pr:
        print(travis_helpers.green(
            'Starting lint check only for modules changed'))
        modules_changed = get_modules_changed(dir, branch_base)
        if not modules_changed:
            print(travis_helpers.green(
                'There are not modules changed from '
                '"git --git-dir=%s diff ..%s"' % (dir, branch_base)))
            return res
        modules_changed_cmd = []
        for module_changed in modules_changed:
            modules_changed_cmd.extend(['--path', module_changed])
        conf = ["--config-file=%s" % (pylint_rcfile_pr)]
        cmd = conf + modules_changed_cmd + extra_params_cmd
        pr_real_errors = main(cmd, standalone_mode=False)
        pr_stats = dict(
            (key, value) for key, value in (pr_real_errors.get(
                'by_msg') or {}).items() if key not in beta_msgs)
        if pr_stats:
            pr_errors = get_count_fails(pr_real_errors, list(beta_msgs))
            print (travis_helpers.yellow(
                "Found %s errors in modules changed." % (pr_errors)))
            if pr_errors < 0:
                res = pr_stats
            else:
                new_dict = {}
                for val in res:
                    new_dict[val] = (new_dict.get(val, 0) + res[val])
                for val in pr_stats:
                    new_dict[val] = (new_dict.get(val, 0) + pr_stats[val])
                res = new_dict
    return res

def get_count_fails(linter_stats, msgs_no_count=None):
    """Verify the dictionary statistics to get number of errors.
    :param linter_stats: Dict of type pylint.lint.Run().linter.stats
    :param no_count: List of messages that will not add to the failure count.
    :return: Integer with quantity of fails found.
    """
    return sum([
        linter_stats['by_msg'][msg]
        for msg in (linter_stats.get('by_msg') or {})
        if msg not in msgs_no_count])

def is_installable_module(path):
    """return False if the path doesn't contain an installable odoo module,
    otherwise the full path to the module's manifest"""
    manifest_path = is_module(path)
    if manifest_path:
        manifest = ast.literal_eval(open(manifest_path).read())
        if manifest.get('installable', True):
            return manifest_path
    return False

def get_subpaths(paths, depth=1):
    """Get list of subdirectories
    if `__init__.py` file doesn't exists in root path, then
    get subdirectories.
    Why? More info here:
        https://www.mail-archive.com/code-quality@python.org/msg00294.html
    :param paths: List of paths
    :param depth: How many folders can be opened in deep to find a module.
    :return: Return list of paths with subdirectories.
    """
    subpaths = []
    for path in paths:
        if depth < 0:
            continue
        if not os.path.isfile(os.path.join(path, '__init__.py')):
            new_subpaths = [os.path.join(path, item)
                            for item in os.listdir(path)
                            if os.path.isdir(os.path.join(path, item))]
            if new_subpaths:
                subpaths.extend(get_subpaths(new_subpaths, depth-1))
        else:
            if is_installable_module(path):
                subpaths.append(path)
    return subpaths

def run_pylint(paths, cfg, beta_msgs=None, sys_paths=None, extra_params=None):
    """Execute pylint command from original python library
    :param paths: List of paths of python modules to check with pylint
    :param cfg: String name of pylint configuration file
    :param sys_paths: List of paths to append to sys path
    :param extra_params: List of extra parameters to append
        in pylint command
    :return: Dict with python linter stats
    """
    if sys_paths is None:
        sys_paths = []
    if extra_params is None:
        extra_params = []
    sys.path.extend(sys_paths)
    cmd = ['--rcfile=' + cfg]
    cmd.extend(extra_params)
    subpaths = get_subpaths(paths)
    if not subpaths:
        raise UserWarning("Python modules not found in paths %s" % (paths))
    cmd.extend(subpaths)
    pylint_res = pylint.lint.Run(cmd, exit=False)
    return pylint_res.linter.stats

@click.command()
@click.option('paths', '--path', envvar='TRAVIS_BUILD_DIR',
              multiple=True, type=CLICK_DIR, required=True,
              default=[os.getcwd()],
              help="Addons paths to check pylint")
@click.option('--config-file', '-c',
              type=click.File('r', lazy=True), required=True,
              help="Pylint config file")
@click.option('--sys-paths', '-sys-path', envvar='PYTHONPATH',
              multiple=True, type=CLICK_DIR,
              help="Additional paths to append in sys path.")
@click.option('--extra-params', '-extra-param', multiple=True,
              help="Extra pylint params to append "
                   "in pylint command")
@click.option('--msgs-no-count', '-msgs-no-count', multiple=True,
              help="List of messages that will not add to the failure count.")
def main(paths, config_file, msgs_no_count=None,
         sys_paths=None, extra_params=None):
    """Script to run pylint command with additional params
    to check fails of odoo modules.
    If expected errors is equal to count fails found then
    this program exits with zero, otherwise exits with counted fails"""
    try:
        stats = run_pylint(
            list(paths), config_file.name,
            sys_paths=sys_paths,
            extra_params=extra_params)
    except UserWarning:
        stats = {'error': -1}
    return stats

if __name__ == '__main__':
    try:
        exit(main(standalone_mode=False))
    except click.ClickException as e:
        e.show()
        exit(e.exit_code)
<commit_msg>remove whitespace before ( for E211<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function

import ast
import os
import re
import sys

import click
import pylint.lint

import travis_helpers
from getaddons import get_modules_changed, is_module
from git_run import GitRun

try:
    import ConfigParser
except ImportError:
    import configparser as ConfigParser

CLICK_DIR = click.Path(exists=True, dir_okay=True, resolve_path=True)

def get_extra_params(odoo_version):
    """Get extra pylint params by odoo version
    Transform a seudo-pylint-conf to params,
    to overwrite base-pylint-conf values.
    Use a seudo-inherit of configuration file.
    To avoid having 2 config files (stable and pr-conf) by each odoo-version
    Example:

        pylint_master.conf
        pylint_master_pr.conf
        pylint_90.conf
        pylint_90_pr.conf
        pylint_80.conf
        pylint_80_pr.conf
        pylint_70.conf
        pylint_70_pr.conf
        pylint_61.conf
        pylint_61_pr.conf
        ... and new future versions.

    If you need to add new conventions in all versions,
    you will need to change all pr files or stable files.

    With this method you can use:

        pylint_lastest.conf
        pylint_lastest_pr.conf
        pylint_disabling_70.conf <- Overwrite params of pylint_lastest*.conf
        pylint_disabling_61.conf <- Overwrite params of pylint_lastest*.conf

    If you need to add new conventions in all versions, you will only need to
    change pylint_lastest_pr.conf or pylint_lastest.conf, similar to inherit.

    :param version: String to specify an Odoo's name or versio
    :return: List of extra pylint params
    """
    is_version_number = re.match(r'\d+\.\d+', odoo_version)
    beta_msgs = get_beta_msgs()
    extra_params_cmd = [
        '--sys-paths', os.path.join(
            os.path.dirname(os.path.realpath(__file__)),
            'pylint_deprecated_modules'),
        '--extra-params', '--load-plugins=pylint_odoo']

    extra_params = list(extra_params_cmd)
    if is_version_number:
        extra_params.extend([
            '--extra-params', '--valid_odoo_versions=%s' % odoo_version])

    odoo_version = odoo_version.replace('.', '')
    version_cfg = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        'cfg/travis_run_pylint_exclude_%s.cfg' % (odoo_version))
    params = []
    if os.path.isfile(version_cfg):
        config = ConfigParser.ConfigParser()
        config.readfp(open(version_cfg))
        for section in config.sections():
            for option, value in config.items(section):
                params.extend(['--' + option, value])

    for param in params:
        extra_params.extend(['--extra-params', param])
    for beta_msg in beta_msgs:
        extra_params.extend(['--msgs-no-count', beta_msg,
                             '--extra-params', '--enable=%s' % beta_msg])
    return extra_params

def get_beta_msgs():
    """Get beta msgs from beta.cfg file
    :return: List of strings with beta message names"""
    beta_cfg = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        'cfg/travis_run_pylint_beta.cfg')
    if not os.path.isfile(beta_cfg):
        return []
    config = ConfigParser.ConfigParser()
    config.readfp(open(beta_cfg))
    return [
        msg.strip()
        for msg in config.get('MESSAGES CONTROL', 'enable').split(',')
        if msg.strip()]

def get_modules_cmd(dir):
    modules_cmd = []
    include_lint = os.environ.get('INCLUDE_LINT')
    if include_lint:
        for path in include_lint.split(' '):
            modules_cmd.extend(['--path', path])
    else:
        modules_cmd.extend(["--path", dir])
    return modules_cmd

def version_validate(version, dir):
    if not version and dir:
        repo_path = os.path.join(dir, '.git')
        branch_name = GitRun(repo_path).get_branch_name()
        version = (branch_name.replace('_', '-').split('-')[:1]
                   if branch_name else False)
        version = version[0] if version else None
    if not version:
        print(travis_helpers.yellow(
            'Undefined environment variable'
            ' `VERSION`.\nSet `VERSION` for '
            'compatibility with guidelines by version.'))
    return version

def get_branch_base():
    branch_base = os.environ.get('TRAVIS_BRANCH') or os.environ.get('VERSION')
    if branch_base != 'HEAD':
        branch_base = 'origin/' + (branch_base and branch_base or '')
    return branch_base

def pylint_run(is_pr, version, dir):
    # Look for an environment variable
    # whose value is the name of a proper configuration file for pylint
    # (this file will then be expected to be found in the 'cfg/' folder).
    # If such an environment variable is not found,
    # it defaults to the standard configuration file.
    pylint_config_file = os.environ.get(
        'PYLINT_CONFIG_FILE', 'travis_run_pylint.cfg')
    pylint_rcfile = os.path.join(
        os.path.dirname(os.path.realpath(__file__)), 'cfg', pylint_config_file)
    pylint_rcfile_pr = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        'cfg', "travis_run_pylint_pr.cfg")
    odoo_version = version_validate(version, dir)
    modules_cmd = get_modules_cmd(dir)
    beta_msgs = get_beta_msgs()
    branch_base = get_branch_base()
    extra_params_cmd = get_extra_params(odoo_version)
    extra_info = "extra_params_cmd %s " % extra_params_cmd
    print(extra_info)
    conf = ["--config-file=%s" % (pylint_rcfile)]
    cmd = conf + modules_cmd + extra_params_cmd

    real_errors = main(cmd, standalone_mode=False)
    res = dict(
        (key, value) for key, value in (real_errors.get(
            'by_msg') or {}).items() if key not in beta_msgs)
    count_errors = get_count_fails(real_errors, list(beta_msgs))
    count_info = "count_errors %s" % count_errors
    print(count_info)
    if is_pr:
        print(travis_helpers.green(
            'Starting lint check only for modules changed'))
        modules_changed = get_modules_changed(dir, branch_base)
        if not modules_changed:
            print(travis_helpers.green(
                'There are not modules changed from '
                '"git --git-dir=%s diff ..%s"' % (dir, branch_base)))
            return res
        modules_changed_cmd = []
        for module_changed in modules_changed:
            modules_changed_cmd.extend(['--path', module_changed])
        conf = ["--config-file=%s" % (pylint_rcfile_pr)]
        cmd = conf + modules_changed_cmd + extra_params_cmd
        pr_real_errors = main(cmd, standalone_mode=False)
        pr_stats = dict(
            (key, value) for key, value in (pr_real_errors.get(
                'by_msg') or {}).items() if key not in beta_msgs)
        if pr_stats:
            pr_errors = get_count_fails(pr_real_errors, list(beta_msgs))
            print(travis_helpers.yellow(
                "Found %s errors in modules changed." % (pr_errors)))
            if pr_errors < 0:
                res = pr_stats
            else:
                new_dict = {}
                for val in res:
                    new_dict[val] = (new_dict.get(val, 0) + res[val])
                for val in pr_stats:
                    new_dict[val] = (new_dict.get(val, 0) + pr_stats[val])
                res = new_dict
    return res

def get_count_fails(linter_stats, msgs_no_count=None):
    """Verify the dictionary statistics to get number of errors.
    :param linter_stats: Dict of type pylint.lint.Run().linter.stats
    :param no_count: List of messages that will not add to the failure count.
    :return: Integer with quantity of fails found.
    """
    return sum([
        linter_stats['by_msg'][msg]
        for msg in (linter_stats.get('by_msg') or {})
        if msg not in msgs_no_count])

def is_installable_module(path):
    """return False if the path doesn't contain an installable odoo module,
    otherwise the full path to the module's manifest"""
    manifest_path = is_module(path)
    if manifest_path:
        manifest = ast.literal_eval(open(manifest_path).read())
        if manifest.get('installable', True):
            return manifest_path
    return False

def get_subpaths(paths, depth=1):
    """Get list of subdirectories
    if `__init__.py` file doesn't exists in root path, then
    get subdirectories.
    Why? More info here:
        https://www.mail-archive.com/code-quality@python.org/msg00294.html
    :param paths: List of paths
    :param depth: How many folders can be opened in deep to find a module.
    :return: Return list of paths with subdirectories.
    """
    subpaths = []
    for path in paths:
        if depth < 0:
            continue
        if not os.path.isfile(os.path.join(path, '__init__.py')):
            new_subpaths = [os.path.join(path, item)
                            for item in os.listdir(path)
                            if os.path.isdir(os.path.join(path, item))]
            if new_subpaths:
                subpaths.extend(get_subpaths(new_subpaths, depth-1))
        else:
            if is_installable_module(path):
                subpaths.append(path)
    return subpaths

def run_pylint(paths, cfg, beta_msgs=None, sys_paths=None, extra_params=None):
    """Execute pylint command from original python library
    :param paths: List of paths of python modules to check with pylint
    :param cfg: String name of pylint configuration file
    :param sys_paths: List of paths to append to sys path
    :param extra_params: List of extra parameters to append
        in pylint command
    :return: Dict with python linter stats
    """
    if sys_paths is None:
        sys_paths = []
    if extra_params is None:
        extra_params = []
    sys.path.extend(sys_paths)
    cmd = ['--rcfile=' + cfg]
    cmd.extend(extra_params)
    subpaths = get_subpaths(paths)
    if not subpaths:
        raise UserWarning("Python modules not found in paths %s" % (paths))
    cmd.extend(subpaths)
    pylint_res = pylint.lint.Run(cmd, exit=False)
    return pylint_res.linter.stats

@click.command()
@click.option('paths', '--path', envvar='TRAVIS_BUILD_DIR',
              multiple=True, type=CLICK_DIR, required=True,
              default=[os.getcwd()],
              help="Addons paths to check pylint")
@click.option('--config-file', '-c',
              type=click.File('r', lazy=True), required=True,
              help="Pylint config file")
@click.option('--sys-paths', '-sys-path', envvar='PYTHONPATH',
              multiple=True, type=CLICK_DIR,
              help="Additional paths to append in sys path.")
@click.option('--extra-params', '-extra-param', multiple=True,
              help="Extra pylint params to append "
                   "in pylint command")
@click.option('--msgs-no-count', '-msgs-no-count', multiple=True,
              help="List of messages that will not add to the failure count.")
def main(paths, config_file, msgs_no_count=None,
         sys_paths=None, extra_params=None):
    """Script to run pylint command with additional params
    to check fails of odoo modules.
    If expected errors is equal to count fails found then
    this program exits with zero, otherwise exits with counted fails"""
    try:
        stats = run_pylint(
            list(paths), config_file.name,
            sys_paths=sys_paths,
            extra_params=extra_params)
    except UserWarning:
        stats = {'error': -1}
    return stats

if __name__ == '__main__':
    try:
        exit(main(standalone_mode=False))
    except click.ClickException as e:
        e.show()
        exit(e.exit_code)
<|endoftext|>


<commit_before>from __future__ import print_function, division, absolute_import
from .treeanc import TreeAnc
from .treetime import TreeTime, plot_vs_years
from .clock_tree import ClockTree
from .treetime import ttconf as treetime_conf
from .gtr import GTR
from .merger_models import Coalescent
from .treeregression import TreeRegression
version="0.5.4"
<commit_msg>version bump<commit_after>from __future__ import print_function, division, absolute_import
from .treeanc import TreeAnc
from .treetime import TreeTime, plot_vs_years
from .clock_tree import ClockTree
from .treetime import ttconf as treetime_conf
from .gtr import GTR
from .merger_models import Coalescent
from .treeregression import TreeRegression
version="0.5.5"
<|endoftext|>


<commit_before>import numpy as np

try:
    from scipy.sparse.linalg import spsolve
    from scipy.sparse import coo_matrix, eye
except ImportError:
    pass

from . import triangles
from .util import unitize
from .geometry import index_sparse
from .triangles import mass_properties

def filter_laplacian(mesh,
                     lamb=0.5,
                     iterations=10,
                     implicit_time_integration=False,
                     volume_constraint=True,
                     laplacian_operator=None):
    """
    Smooth a mesh in-place using laplacian smoothing.
    Articles
    1 - "Improved Laplacian Smoothing of Noisy Surface Meshes"
       J. Vollmer, R. Mencl, and H. Muller
    2 - "Implicit Fairing of Irregular Meshes using Diffusion
       and Curvature Flow". M. Desbrun,  M. Meyer,
       P. Schroder, A.H.B. Caltech
    Parameters
    ------------
    mesh : trimesh.Trimesh
    Mesh to be smoothed in place
    lamb : float
    Diffusion speed constant
    If   0.0, no diffusion
    If > 0.0, diffusion occurs
    implicit_time_integration: boolean
    if False: explicit time integration
        -lamb <= 1.0 - Stability Limit (Article 1)
    if True: implicit time integration
        -lamb no limit (Article 2)
    iterations : int
    Number of passes to run filter
    laplacian_operator : None or scipy.sparse.coo.coo_matrix
    Sparse matrix laplacian operator
    Will be autogenerated if None
    """

    # if the laplacian operator was not passed create it here
    if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

    # save initial volume
    if volume_constraint:
        vol_ini = mesh.volume

    # get mesh vertices and faces as vanilla numpy array
    vertices = mesh.vertices.copy().view(np.ndarray)
    faces = mesh.faces.copy().view(np.ndarray)

    # Set matrix for linear system of equations
    if implicit_time_integration:
        dlap = laplacian_operator.shape[0]
        AA = eye(dlap) + lamb * (eye(dlap) - laplacian_operator)

    # Number of passes
    for _index in range(iterations):
        # Classic Explicit Time Integration - Article 1
        if not implicit_time_integration:
            dot = laplacian_operator.dot(vertices) - vertices
            vertices += lamb * dot

        # Implicit Time Integration - Article 2
        else:
            vertices = spsolve(AA, vertices)

        # volume constraint
        if volume_constraint:
            # find the volume with new vertex positions
            vol_new = triangles.mass_properties(
                vertices[faces], skip_inertia=True)["volume"]
            # scale by volume ratio
            vertices *= ((vol_ini / vol_new) ** (1.0 / 3.0))

    # assign modified vertices back to mesh
    mesh.vertices = vertices
    return mesh

def filter_humphrey(mesh,
                    alpha=0.1,
                    beta=0.5,
                    iterations=10,
                    laplacian_operator=None):
    """
    Smooth a mesh in-place using laplacian smoothing
    and Humphrey filtering.
    Articles
    "Improved Laplacian Smoothing of Noisy Surface Meshes"
    J. Vollmer, R. Mencl, and H. Muller
    Parameters
    ------------
    mesh : trimesh.Trimesh
      Mesh to be smoothed in place
    alpha : float
      Controls shrinkage, range is 0.0 - 1.0
      If 0.0, not considered
      If 1.0, no smoothing
    beta : float
      Controls how aggressive smoothing is
      If 0.0, no smoothing
      If 1.0, full aggressiveness
    iterations : int
      Number of passes to run filter
    laplacian_operator : None or scipy.sparse.coo.coo_matrix
      Sparse matrix laplacian operator
      Will be autogenerated if None
    """
    # if the laplacian operator was not passed create it here
    if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

    # get mesh vertices as vanilla numpy array
    vertices = mesh.vertices.copy().view(np.ndarray)
    # save original unmodified vertices
    original = vertices.copy()

    # run through iterations of filter
    for _index in range(iterations):
        vert_q = vertices.copy()
        vertices = laplacian_operator.dot(vertices)
        vert_b = vertices - (alpha * original + (1.0 - alpha) * vert_q)
        vertices -= (beta * vert_b + (1.0 - beta) *
                     laplacian_operator.dot(vert_b))

    # assign modified vertices back to mesh
    mesh.vertices = vertices
    return mesh

def filter_taubin(mesh,
                  lamb=0.5,
                  nu=0.5,
                  iterations=10,
                  laplacian_operator=None):
    """
    Smooth a mesh in-place using laplacian smoothing
    and taubin filtering.
    Articles
    "Improved Laplacian Smoothing of Noisy Surface Meshes"
    J. Vollmer, R. Mencl, and H. Muller
    Parameters
    ------------
    mesh : trimesh.Trimesh
      Mesh to be smoothed in place.
    lamb : float
      Controls shrinkage, range is 0.0 - 1.0
    nu : float
      Controls dilation, range is 0.0 - 1.0
      Nu shall be between 0.0 < 1.0/lambda - 1.0/nu < 0.1
    iterations : int
      Number of passes to run the filter
    laplacian_operator : None or scipy.sparse.coo.coo_matrix
      Sparse matrix laplacian operator
      Will be autogenerated if None
    """
    # if the laplacian operator was not passed create it here
    if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

    # get mesh vertices as vanilla numpy array
    vertices = mesh.vertices.copy().view(np.ndarray)

    # run through multiple passes of the filter
    for index in range(iterations):
        # do a sparse dot product on the vertices
        dot = laplacian_operator.dot(vertices) - vertices
        # alternate shrinkage and dilation
        if index % 2 == 0:
            vertices += lamb * dot
        else:
            vertices -= nu * dot

    # assign updated vertices back to mesh
    mesh.vertices = vertices
    return mesh

def filter_mut_dif_laplacian(mesh,
                            lamb=0.5,
                            iterations=10,
                            volume_constraint=True,
                            laplacian_operator=None):
  """
  Smooth a mesh in-place using laplacian smoothing using a mutable difusion laplacian
  Articles
    Barroqueiro, B., Andrade-Campos, A., Dias-de-Oliveira, J., and Valente, R. (January 21, 2021).
    "Bridging between topology optimization and additive manufacturing via Laplacian smoothing." ASME. J. Mech. Des.
  Parameters
  ------------
  mesh : trimesh.Trimesh
  Mesh to be smoothed in place
  lamb : float
  Diffusion speed constant
  If   0.0, no diffusion
  If > 0.0, diffusion occours
  iterations : int
  Number of passes to run filter
  laplacian_operator : None or scipy.sparse.coo.coo_matrix
  Sparse matrix laplacian operator
  Will be autogenerated if None
  """
  # if the laplacian operator was not passed create it here
  if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

  # Set volume constraint
  if volume_constraint==True:
        v_ini=mesh.volume

  # get mesh vertices as vanilla numpy array
  vertices = mesh.vertices.copy().view(np.ndarray)
  faces    = mesh.faces.copy().view(np.ndarray)
  #neigh    = mesh.vertex_neighbors.copy().view(np.ndarray)
  #nearby_faces = trimesh.proximity.nearby_faces(mesh,mesh.vertices)
  #centers=mesh.triangles_center.copy().view(np.ndarray)
  eps=0.01*(np.max(mesh.area_faces)**0.5)

  # Number of passes
  for _index in range(iterations):

    # Compute normals
    normals=get_vertices_normals(mesh)

    # Filter
    qi=laplacian_operator.dot(vertices)
    pi_qi = vertices-qi
    adil = (normals*pi_qi).dot(np.ones((3,1)))

    vertices -= lamb*normals*adil

    # Volume constraint
    if volume_constraint==True:
          vol=mass_properties(vertices[faces],skip_inertia=True)["volume"]
          if _index ==0:
                slope=dilate_slope(vertices,faces,normals,vol,eps)
          vertices += normals*slope*(v_ini-vol)

  # Set Volume Residual to zero
  if volume_constraint==True:
        vol2=mass_properties(vertices[faces],skip_inertia=True)["volume"]
        vertices *= ((v_ini/vol2)**(1./3.))

  # assign modified vertices back to mesh
  mesh.vertices = vertices

  return mesh

def laplacian_calculation(mesh, equal_weight=True,pinned_vertices=[]):
    """
    Calculate a sparse matrix for laplacian operations.
    Parameters
    -------------
    mesh : trimesh.Trimesh
      Input geometry
    equal_weight : bool
      If True, all neighbors will be considered equally
      If False, all neighbors will be weighted by inverse distance
    Returns
    ----------
    laplacian : scipy.sparse.coo.coo_matrix
      Laplacian operator
    """
    # get the vertex neighbors from the cache
    neighbors = mesh.vertex_neighbors

    # if a node is pinned, it will average his coordinates by himself
    # in practice it will not move
    for i in  pinned_vertices:
      neighbors[i]=[i]

    # avoid hitting crc checks in loops
    vertices = mesh.vertices.view(np.ndarray)

    # stack neighbors to 1D arrays
    col = np.concatenate(neighbors)
    row = np.concatenate([[i] * len(n)
                          for i, n in enumerate(neighbors)])

    if equal_weight:
        # equal weights for each neighbor
        data = np.concatenate([[1.0 / len(n)] * len(n)
                               for n in neighbors])
    else:
        # umbrella weights, distance-weighted
        # use dot product of ones to replace array.sum(axis=1)
        ones = np.ones(3)
        # the distance from verticesex to neighbors
        norms = [1.0 / np.maximum(1e-6, np.sqrt(np.dot((vertices[i] - vertices[n]) ** 2, ones))) for i, n in enumerate(neighbors)]
        # normalize group and stack into single array
        data = np.concatenate([i / i.sum() for i in norms])

    # create the sparse matrix
    matrix = coo_matrix((data, (row, col)),
                        shape=[len(vertices)] * 2)

    return matrix

def get_vertices_normals(mesh):
  """
  Compute Vertex normals using equal weighting of neighbors faces.
  Parameters
    -------------
    mesh : trimesh.Trimesh
      Input geometry
    Returns
    ----------
    vertices_normals: array
      Vertices normals
  """

  # get mesh vertices and faces
  vertices=mesh.vertices
  faces=mesh.faces

  # get face normals
  face_normals=mesh.face_normals

  # Compute Vert normals
  vert_normals = index_sparse(len(vertices),faces).dot(face_normals)

  return unitize(vert_normals)

def dilate_slope(vertices,faces,normals,v,eps):
  """
  Get de derivate of dilation scalar by the volume variation by finite diferences
  Thus, Vertices += vertex_normals*dilate_slope*(Initial_Volume - Srinked_Volume)
  Parameters
    -------------
    mesh : trimesh.Trimesh
      Input geometry
    vertices: mesh.vertices
    faces: mesh.faces
    normals: array
      vertices normals
    Returns
    ----------
    dilate_slope: float
      derivative
  """

  #finite diference derivative
  vertices2 = vertices + normals*eps
  v2=mass_properties(vertices2[faces],skip_inertia=True)["volume"]

  return (eps)/(v2-v)<commit_msg>Update smoothing.py<commit_after>import numpy as np

try:
    from scipy.sparse.linalg import spsolve
    from scipy.sparse import coo_matrix, eye
except ImportError:
    pass

from . import triangles
from .util import unitize
from .geometry import index_sparse
from .triangles import mass_properties

def filter_laplacian(mesh,
                     lamb=0.5,
                     iterations=10,
                     implicit_time_integration=False,
                     volume_constraint=True,
                     laplacian_operator=None):
    """
    Smooth a mesh in-place using laplacian smoothing.
    Articles
    1 - "Improved Laplacian Smoothing of Noisy Surface Meshes"
       J. Vollmer, R. Mencl, and H. Muller
    2 - "Implicit Fairing of Irregular Meshes using Diffusion
       and Curvature Flow". M. Desbrun,  M. Meyer,
       P. Schroder, A.H.B. Caltech
    Parameters
    ------------
    mesh : trimesh.Trimesh
    Mesh to be smoothed in place
    lamb : float
    Diffusion speed constant
    If   0.0, no diffusion
    If > 0.0, diffusion occurs
    implicit_time_integration: boolean
    if False: explicit time integration
        -lamb <= 1.0 - Stability Limit (Article 1)
    if True: implicit time integration
        -lamb no limit (Article 2)
    iterations : int
    Number of passes to run filter
    laplacian_operator : None or scipy.sparse.coo.coo_matrix
    Sparse matrix laplacian operator
    Will be autogenerated if None
    """

    # if the laplacian operator was not passed create it here
    if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

    # save initial volume
    if volume_constraint:
        vol_ini = mesh.volume

    # get mesh vertices and faces as vanilla numpy array
    vertices = mesh.vertices.copy().view(np.ndarray)
    faces = mesh.faces.copy().view(np.ndarray)

    # Set matrix for linear system of equations
    if implicit_time_integration:
        dlap = laplacian_operator.shape[0]
        AA = eye(dlap) + lamb * (eye(dlap) - laplacian_operator)

    # Number of passes
    for _index in range(iterations):
        # Classic Explicit Time Integration - Article 1
        if not implicit_time_integration:
            dot = laplacian_operator.dot(vertices) - vertices
            vertices += lamb * dot

        # Implicit Time Integration - Article 2
        else:
            vertices = spsolve(AA, vertices)

        # volume constraint
        if volume_constraint:
            # find the volume with new vertex positions
            vol_new = triangles.mass_properties(
                vertices[faces], skip_inertia=True)["volume"]
            # scale by volume ratio
            vertices *= ((vol_ini / vol_new) ** (1.0 / 3.0))

    # assign modified vertices back to mesh
    mesh.vertices = vertices
    return mesh

def filter_humphrey(mesh,
                    alpha=0.1,
                    beta=0.5,
                    iterations=10,
                    laplacian_operator=None):
    """
    Smooth a mesh in-place using laplacian smoothing
    and Humphrey filtering.
    Articles
    "Improved Laplacian Smoothing of Noisy Surface Meshes"
    J. Vollmer, R. Mencl, and H. Muller
    Parameters
    ------------
    mesh : trimesh.Trimesh
      Mesh to be smoothed in place
    alpha : float
      Controls shrinkage, range is 0.0 - 1.0
      If 0.0, not considered
      If 1.0, no smoothing
    beta : float
      Controls how aggressive smoothing is
      If 0.0, no smoothing
      If 1.0, full aggressiveness
    iterations : int
      Number of passes to run filter
    laplacian_operator : None or scipy.sparse.coo.coo_matrix
      Sparse matrix laplacian operator
      Will be autogenerated if None
    """
    # if the laplacian operator was not passed create it here
    if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

    # get mesh vertices as vanilla numpy array
    vertices = mesh.vertices.copy().view(np.ndarray)
    # save original unmodified vertices
    original = vertices.copy()

    # run through iterations of filter
    for _index in range(iterations):
        vert_q = vertices.copy()
        vertices = laplacian_operator.dot(vertices)
        vert_b = vertices - (alpha * original + (1.0 - alpha) * vert_q)
        vertices -= (beta * vert_b + (1.0 - beta) *
                     laplacian_operator.dot(vert_b))

    # assign modified vertices back to mesh
    mesh.vertices = vertices
    return mesh

def filter_taubin(mesh,
                  lamb=0.5,
                  nu=0.5,
                  iterations=10,
                  laplacian_operator=None):
    """
    Smooth a mesh in-place using laplacian smoothing
    and taubin filtering.
    Articles
    "Improved Laplacian Smoothing of Noisy Surface Meshes"
    J. Vollmer, R. Mencl, and H. Muller
    Parameters
    ------------
    mesh : trimesh.Trimesh
      Mesh to be smoothed in place.
    lamb : float
      Controls shrinkage, range is 0.0 - 1.0
    nu : float
      Controls dilation, range is 0.0 - 1.0
      Nu shall be between 0.0 < 1.0/lambda - 1.0/nu < 0.1
    iterations : int
      Number of passes to run the filter
    laplacian_operator : None or scipy.sparse.coo.coo_matrix
      Sparse matrix laplacian operator
      Will be autogenerated if None
    """
    # if the laplacian operator was not passed create it here
    if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

    # get mesh vertices as vanilla numpy array
    vertices = mesh.vertices.copy().view(np.ndarray)

    # run through multiple passes of the filter
    for index in range(iterations):
        # do a sparse dot product on the vertices
        dot = laplacian_operator.dot(vertices) - vertices
        # alternate shrinkage and dilation
        if index % 2 == 0:
            vertices += lamb * dot
        else:
            vertices -= nu * dot

    # assign updated vertices back to mesh
    mesh.vertices = vertices
    return mesh

def filter_mut_dif_laplacian(mesh,
                            lamb=0.5,
                            iterations=10,
                            volume_constraint=True,
                            laplacian_operator=None):
  """
  Smooth a mesh in-place using laplacian smoothing using a mutable difusion laplacian
  Articles
    Barroqueiro, B., Andrade-Campos, A., Dias-de-Oliveira, J., and Valente, R. (January 21, 2021).
    "Bridging between topology optimization and additive manufacturing via Laplacian smoothing." ASME. J. Mech. Des.
  Parameters
  ------------
  mesh : trimesh.Trimesh
  Mesh to be smoothed in place
  lamb : float
  Diffusion speed constant
  If   0.0, no diffusion
  If > 0.0, diffusion occours
  iterations : int
  Number of passes to run filter
  laplacian_operator : None or scipy.sparse.coo.coo_matrix
  Sparse matrix laplacian operator
  Will be autogenerated if None
  """

  # if the laplacian operator was not passed create it here
  if laplacian_operator is None:
        laplacian_operator = laplacian_calculation(mesh)

  # Set volume constraint
  if volume_constraint==True:
        v_ini=mesh.volume

  # get mesh vertices as vanilla numpy array
  vertices = mesh.vertices.copy().view(np.ndarray)
  faces    = mesh.faces.copy().view(np.ndarray)
  eps=0.01*(np.max(mesh.area_faces)**0.5)

  # Number of passes
  for _index in range(iterations):

    # Mutable difusion
    normals=get_vertices_normals(mesh)
    qi=laplacian_operator.dot(vertices)
    pi_qi = vertices-qi
    adil = np.abs((normals*pi_qi).dot(np.ones((3,1))))
    adil=1.0/np.maximum(1e-12,adil)
    lamber=np.maximum(0.2*lamb, np.minimum(1.0,lamb*adil/np.mean(adil)))

    #Filter
    dot = laplacian_operator.dot(vertices) - vertices
    vertices += lamber * dot

    # Volume constraint
    if volume_constraint==True:
          vol=mass_properties(vertices[faces],skip_inertia=True)["volume"]
          if _index ==0:
                slope=dilate_slope(vertices,faces,normals,vol,eps)
          vertices += normals*slope*(v_ini-vol)

  # assign modified vertices back to mesh
  mesh.vertices = vertices

  return mesh

def laplacian_calculation(mesh, equal_weight=True,pinned_vertices=[]):
    """
    Calculate a sparse matrix for laplacian operations.
    Parameters
    -------------
    mesh : trimesh.Trimesh
      Input geometry
    equal_weight : bool
      If True, all neighbors will be considered equally
      If False, all neighbors will be weighted by inverse distance
    Returns
    ----------
    laplacian : scipy.sparse.coo.coo_matrix
      Laplacian operator
    """
    # get the vertex neighbors from the cache
    neighbors = mesh.vertex_neighbors

    # if a node is pinned, it will average his coordinates by himself
    # in practice it will not move
    for i in  pinned_vertices:
      neighbors[i]=[i]

    # avoid hitting crc checks in loops
    vertices = mesh.vertices.view(np.ndarray)

    # stack neighbors to 1D arrays
    col = np.concatenate(neighbors)
    row = np.concatenate([[i] * len(n)
                          for i, n in enumerate(neighbors)])

    if equal_weight:
        # equal weights for each neighbor
        data = np.concatenate([[1.0 / len(n)] * len(n)
                               for n in neighbors])
    else:
        # umbrella weights, distance-weighted
        # use dot product of ones to replace array.sum(axis=1)
        ones = np.ones(3)
        # the distance from verticesex to neighbors
        norms = [1.0 / np.maximum(1e-6, np.sqrt(np.dot((vertices[i] - vertices[n]) ** 2, ones))) for i, n in enumerate(neighbors)]
        # normalize group and stack into single array
        data = np.concatenate([i / i.sum() for i in norms])

    # create the sparse matrix
    matrix = coo_matrix((data, (row, col)),
                        shape=[len(vertices)] * 2)

    return matrix

def get_vertices_normals(mesh):
  """
  Compute Vertex normals using equal weighting of neighbors faces.
  Parameters
    -------------
    mesh : trimesh.Trimesh
      Input geometry
    Returns
    ----------
    vertices_normals: array
      Vertices normals
  """

  # get mesh vertices and faces
  vertices=mesh.vertices
  faces=mesh.faces

  # get face normals
  face_normals=mesh.face_normals

  # Compute Vert normals
  vert_normals = index_sparse(len(vertices),faces).dot(face_normals)

  return unitize(vert_normals)

def dilate_slope(vertices,faces,normals,v,eps):
  """
  Get de derivate of dilation scalar by the volume variation by finite diferences
  Thus, Vertices += vertex_normals*dilate_slope*(Initial_Volume - Srinked_Volume)
  Parameters
    -------------
    mesh : trimesh.Trimesh
      Input geometry
    vertices: mesh.vertices
    faces: mesh.faces
    normals: array
      vertices normals
    Returns
    ----------
    dilate_slope: float
      derivative
  """

  #finite diference derivative
  vertices2 = vertices + normals*eps
  v2=mass_properties(vertices2[faces],skip_inertia=True)["volume"]

  return (eps)/(v2-v)
<|endoftext|>


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

import pygame
import random

# создадим окно (высота, ширина)
window = pygame.display.set_mode((400, 400))
pygame.display.set_caption('Game!')

#игровой экран
screen = pygame.Surface((400, 400))

#вводим класс для героя
class Sprite:
    def __init__ (self,xpos,ypos,filename):
        self.x=xpos
        self.y=ypos
        self.bitmap=pygame.image.load(filename)
# фон делаем прозрачным
        self.bitmap.set_colorkey((255,25,255))
# отображаем обьект на игровой экран
    def render(self):
        screen.blit(self.bitmap,(self.x, self.y))

# создаем героев
leo = Sprite(200,0, 'face1.png')
# новый атрибут герою - рычаг управления_1
leo_go_right = True
leo_go = True

ian = Sprite(200,360, 'face2.png')
# новый атрибут герою - рычаг управления_2
ian_go_right = True
ian_go = True

x_b = random.randint(100, 300)
y_b = random.randint(100, 300)
ball = Sprite(x_b,y_b, 'bb1.png')
ball_go = True

# придумаем скорость
speed = 2

# функция проверки пересечения объектов. 40 - величина ширины объектов
def Intersect(x1, x2, y1, y2, db1, db2):
    if ((x1 > x2-db1) and (x1 < x2+db2) and (y1 > y2-db1) and (y1 < y2+db2)) :
        return 1
    else:
        return 0

done = True
while done:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            done = False

# красим окно , цвета в RGB
    screen.fill((15, 106, 15))
    '''
    if leo_go == True:
        leo.y += 1
        if leo.y > 360:
            leo_go = False
    else:
        leo.y -= 1
        if leo.y < 0:
            leo_go = True
    '''
    # событие - нажатие клавиш
    if e.type == pygame.KEYDOWN:
        # перемещение героя
        if e.key == pygame.K_a:
            if leo.x > 0:
                leo.x -= 1
        if e.key == pygame.K_d:
            if leo.x < 360:
                leo.x += 1
        if e.key == pygame.K_w:
            if leo.y > 0:
                leo.y -= 1
        if e.key == pygame.K_s:
            if leo.y < 160:
                leo.y += 1

        # перемещение героя 2
        if e.key == pygame.K_LEFT:
            if ian.x > 0:
                ian.x -= 1
        if e.key == pygame.K_RIGHT:
            if ian.x < 360:
                ian.x += 1
        if e.key == pygame.K_UP:
            if ian.y > 200:
                ian.y -= 1
        if e.key == pygame.K_DOWN:
            if ian.y < 360:
                ian.y += 1

                '''
    if ian_go == True:
        ian.y -= 1
        if ian.y < 0:
            ian_go = False
    else:
        ian.y += 1
        if ian.y > 360:
            ian_go = True
               '''

    if ball_go == True:
        ball.x += speed
        if ball.x > (385 - speed):
            ball_go = False
    else:
        ball.x -= speed
        if ball.x < 0:
            ball_go = True

    if ball_go == True:
        ball.y += speed
        if ball.y > (385 - speed):
            ball_go = False
    else:
        ball.y -= speed
        if ball.y < 0:
            ball_go = True

    if Intersect (leo.x, ball.x, leo.y, ball.y, 40, 15) == 1:
        '''
        if leo_go == True:
            leo_go = False
        else:
            leo_go = True
        '''
        if ball_go == True:
            ball_go = False
        else:
            ball_go = True
    if Intersect (ian.x, ball.x, ian.y, ball.y, 40, 15) == 1:
        if ball_go == True:
            ball_go = False
        else:
            ball_go = True

# отобразим обьекты
    leo.render()
    ian.render()
    ball.render()

    window.blit(screen,  (0, 0))
    pygame.display.flip()
    # делаем задержку
    pygame.time.delay(15)
<commit_msg>bad commit<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
import random

# создадим окно (высота, ширина)
window = pygame.display.set_mode((400, 400))
pygame.display.set_caption('Game!')

#игровой экран
screen = pygame.Surface((400, 400))

#вводим класс для героя
class Sprite:
    def __init__ (self,xpos,ypos,filename):
        self.x=xpos
        self.y=ypos
        self.bitmap=pygame.image.load(filename)
# фон делаем прозрачным
        self.bitmap.set_colorkey((255,25,255))
# отображаем обьект на игровой экран
    def render(self):
        screen.blit(self.bitmap,(self.x, self.y))

# создаем героев
leo = Sprite(200,0, 'face1.png')
# новый атрибут герою - рычаг управления_1
leo_go_right = True
leo_go = True

ian = Sprite(200,360, 'face2.png')
# новый атрибут герою - рычаг управления_2
ian_go_right = True
ian_go = True

x_b = random.randint(100, 300)
y_b = random.randint(100, 300)
ball = Sprite(x_b,y_b, 'bb1.png')
ball_go_r = True
ball_go_d = True

# придумаем скорость
speed = 2

# функция проверки пересечения объектов. 40 - величина ширины объектов
def Intersect(x1, x2, y1, y2, db1, db2):
    if ((x1 > x2-db1) and (x1 < x2+db2) and (y1 > y2-db1) and (y1 < y2+db2)) :
        return 1
    else:
        return 0

done = True
while done:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            done = False

# красим окно , цвета в RGB
    screen.fill((15, 106, 15))
    '''
    if leo_go == True:
        leo.y += 1
        if leo.y > 360:
            leo_go = False
    else:
        leo.y -= 1
        if leo.y < 0:
            leo_go = True
    '''
    # событие - нажатие клавиш
    if e.type == pygame.KEYDOWN:
        # перемещение героя
        if e.key == pygame.K_a:
            if leo.x > 0:
                leo.x -= 1
        if e.key == pygame.K_d:
            if leo.x < 360:
                leo.x += 1
        if e.key == pygame.K_w:
            if leo.y > 0:
                leo.y -= 1
        if e.key == pygame.K_s:
            if leo.y < 160:
                leo.y += 1

        # перемещение героя 2
        if e.key == pygame.K_LEFT:
            if ian.x > 0:
                ian.x -= 1
        if e.key == pygame.K_RIGHT:
            if ian.x < 360:
                ian.x += 1
        if e.key == pygame.K_UP:
            if ian.y > 200:
                ian.y -= 1
        if e.key == pygame.K_DOWN:
            if ian.y < 360:
                ian.y += 1

                '''
    if ian_go == True:
        ian.y -= 1
        if ian.y < 0:
            ian_go = False
    else:
        ian.y += 1
        if ian.y > 360:
            ian_go = True
               '''

    if ball_go_r == True:
        ball.x += speed
        if ball.x > (385 - speed):
            ball_go_r = False
    else:
        ball.x -= speed
        if ball.x < 0:
            ball_go_r = True

    if ball_go_d == True:
        ball.y += speed
        if ball.y > (385 - speed):
            ball_go_d = False
    else:
        ball.y -= speed
        if ball.y < 0:
            ball_go_d = True

    if Intersect (leo.x, ball.x, leo.y, ball.y, 40, 15) == 1:
        if ball_go_r == True:
            ball_go_r = False
        if ball_go_d == True:
            ball_go_d = False
        if ball_go_r == False:
            ball_go_r = True
        if ball_go_d == False:
            ball_go_d = True

#    if Intersect (ian.x, ball.x, ian.y, ball.y, 40, 15) == 1:
    if Intersect (ball.x, ian.x, ball.y, ian.y, 15, 40) == 1:
        if ball_go_r == True:
            ball_go_r = False
        if ball_go_d == True:
            ball_go_d = False
        if ball_go_r == False:
            ball_go_r = True
        if ball_go_d == False:
            ball_go_d = True

# отобразим обьекты
    leo.render()
    ian.render()
    ball.render()

    window.blit(screen,  (0, 0))
    pygame.display.flip()
    # делаем задержку
    pygame.time.delay(15)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# tslearn documentation build configuration file, created by
# sphinx-quickstart on Mon May  8 21:34:49 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys
import os

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('../../'))
#sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../..'))

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.doctest',
    'sphinx.ext.coverage',
    'sphinx.ext.mathjax',
    'sphinx.ext.viewcode',
    'sphinx.ext.napoleon'
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'tslearn'
copyright = u'2017, Romain Tavenard'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.0.1'
# The full version, including alpha/beta/rc tags.
release = '0.0.1'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']

# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False

# -- Options for HTML output ----------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = 'default'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'tslearndoc'

# -- Options for LaTeX output ---------------------------------------------

latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',

# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',

# Additional stuff for the LaTeX preamble.
#'preamble': '',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
#  author, documentclass [howto, manual, or own class]).
latex_documents = [
  ('index', 'tslearn.tex', u'tslearn Documentation',
   u'Romain Tavenard', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'tslearn', u'tslearn Documentation',
     [u'Romain Tavenard'], 1)
]

# If true, show URL addresses after external links.
#man_show_urls = False

# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
  ('index', 'tslearn', u'tslearn Documentation',
   u'Romain Tavenard', 'tslearn', 'One line description of project.',
   'Miscellaneous'),
]

# Documents to append as an appendix to all manuals.
#texinfo_appendices = []

# If false, no module index is generated.
#texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
<commit_msg>Cython modules for RTD<commit_after># -*- coding: utf-8 -*-
#
# tslearn documentation build configuration file, created by
# sphinx-quickstart on Mon May  8 21:34:49 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys
import os

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
on_rtd = os.environ.get('READTHEDOCS') == 'True'
if on_rtd:
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../..'))
else:  #locally
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../..'))

# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.doctest',
    'sphinx.ext.coverage',
    'sphinx.ext.mathjax',
    'sphinx.ext.viewcode',
    'sphinx.ext.napoleon'
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'tslearn'
copyright = u'2017, Romain Tavenard'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.0.1'
# The full version, including alpha/beta/rc tags.
release = '0.0.1'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']

# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False

# -- Options for HTML output ----------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = 'default'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'tslearndoc'

# -- Options for LaTeX output ---------------------------------------------

latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',

# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',

# Additional stuff for the LaTeX preamble.
#'preamble': '',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
#  author, documentclass [howto, manual, or own class]).
latex_documents = [
  ('index', 'tslearn.tex', u'tslearn Documentation',
   u'Romain Tavenard', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output ---------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'tslearn', u'tslearn Documentation',
     [u'Romain Tavenard'], 1)
]

# If true, show URL addresses after external links.
#man_show_urls = False

# -- Options for Texinfo output -------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
  ('index', 'tslearn', u'tslearn Documentation',
   u'Romain Tavenard', 'tslearn', 'One line description of project.',
   'Miscellaneous'),
]

# Documents to append as an appendix to all manuals.
#texinfo_appendices = []

# If false, no module index is generated.
#texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
<|endoftext|>


<commit_before>import codecs
import re
import time
import warnings

import six

import requests

# Technically, we should support streams that mix line endings.  This regex,
# however, assumes that a system will provide consistent line endings.
end_of_field = re.compile(r'\r\n\r\n|\r\r|\n\n')

class SSEClient(object):
    def __init__(self, url, last_id=None, retry=3000, session=None, chunk_size=1024, **kwargs):
        self.url = url
        self.last_id = last_id
        self.retry = retry
        self.chunk_size = chunk_size

        # Optional support for passing in a requests.Session()
        self.session = session

        # Any extra kwargs will be fed into the requests.get call later.
        self.requests_kwargs = kwargs

        # The SSE spec requires making requests with Cache-Control: nocache
        if 'headers' not in self.requests_kwargs:
            self.requests_kwargs['headers'] = {}
        self.requests_kwargs['headers']['Cache-Control'] = 'no-cache'

        # The 'Accept' header is not required, but explicit > implicit
        self.requests_kwargs['headers']['Accept'] = 'text/event-stream'

        # Keep data here as it streams in
        self.buf = u''

        self._connect()

    def _connect(self):
        if self.last_id:
            self.requests_kwargs['headers']['Last-Event-ID'] = self.last_id

        # Use session if set.  Otherwise fall back to requests module.
        requester = self.session or requests
        self.resp = requester.get(self.url, stream=True, **self.requests_kwargs)
        self.resp_iterator = self.resp.iter_content(chunk_size=self.chunk_size)

        # TODO: Ensure we're handling redirects.  Might also stick the 'origin'
        # attribute on Events like the Javascript spec requires.
        self.resp.raise_for_status()

    def _event_complete(self):
        return re.search(end_of_field, self.buf) is not None

    def __iter__(self):
        return self

    def __next__(self):
        decoder = codecs.getincrementaldecoder(
            self.resp.encoding)(errors='replace')
        while not self._event_complete():
            try:
                next_chunk = self.resp_iterator.next()
                if not next_chunk:
                    raise EOFError()
                self.buf += decoder.decode(next_chunk)
            except (StopIteration, requests.RequestException, EOFError) as e:
                time.sleep(self.retry / 1000.0)
                self._connect()

                # The SSE spec only supports resuming from a whole message, so
                # if we have half a message we should throw it out.
                head, sep, tail = self.buf.rpartition('\n')
                self.buf = head + sep
                continue

        split = re.split(end_of_field, self.buf)
        head = split[0]
        tail = "".join(split[1:])

        self.buf = tail
        msg = Event.parse(head)

        # If the server requests a specific retry delay, we need to honor it.
        if msg.retry:
            self.retry = msg.retry

        # last_id should only be set if included in the message.  It's not
        # forgotten if a message omits it.
        if msg.id:
            self.last_id = msg.id

        return msg

    if six.PY2:
        next = __next__

class Event(object):

    sse_line_pattern = re.compile('(?P<name>[^:]*):?( ?(?P<value>.*))?')

    def __init__(self, data='', event='message', id=None, retry=None):
        self.data = data
        self.event = event
        self.id = id
        self.retry = retry

    def dump(self):
        lines = []
        if self.id:
            lines.append('id: %s' % self.id)

        # Only include an event line if it's not the default already.
        if self.event != 'message':
            lines.append('event: %s' % self.event)

        if self.retry:
            lines.append('retry: %s' % self.retry)

        lines.extend('data: %s' % d for d in self.data.split('\n'))
        return '\n'.join(lines) + '\n\n'

    @classmethod
    def parse(cls, raw):
        """
        Given a possibly-multiline string representing an SSE message, parse it
        and return a Event object.
        """
        msg = cls()
        for line in raw.splitlines():
            m = cls.sse_line_pattern.match(line)
            if m is None:
                # Malformed line.  Discard but warn.
                warnings.warn('Invalid SSE line: "%s"' % line, SyntaxWarning)
                continue

            name = m.group('name')
            if name == '':
                # line began with a ":", so is a comment.  Ignore
                continue
            value = m.group('value')

            if name == 'data':
                # If we already have some data, then join to it with a newline.
                # Else this is it.
                if msg.data:
                    msg.data = '%s\n%s' % (msg.data, value)
                else:
                    msg.data = value
            elif name == 'event':
                msg.event = value
            elif name == 'id':
                msg.id = value
            elif name == 'retry':
                msg.retry = int(value)

        return msg

    def __str__(self):
        return self.data
<commit_msg>Use next(iter) instead of iter.next<commit_after>import codecs
import re
import time
import warnings

import six

import requests

# Technically, we should support streams that mix line endings.  This regex,
# however, assumes that a system will provide consistent line endings.
end_of_field = re.compile(r'\r\n\r\n|\r\r|\n\n')

class SSEClient(object):
    def __init__(self, url, last_id=None, retry=3000, session=None, chunk_size=1024, **kwargs):
        self.url = url
        self.last_id = last_id
        self.retry = retry
        self.chunk_size = chunk_size

        # Optional support for passing in a requests.Session()
        self.session = session

        # Any extra kwargs will be fed into the requests.get call later.
        self.requests_kwargs = kwargs

        # The SSE spec requires making requests with Cache-Control: nocache
        if 'headers' not in self.requests_kwargs:
            self.requests_kwargs['headers'] = {}
        self.requests_kwargs['headers']['Cache-Control'] = 'no-cache'

        # The 'Accept' header is not required, but explicit > implicit
        self.requests_kwargs['headers']['Accept'] = 'text/event-stream'

        # Keep data here as it streams in
        self.buf = u''

        self._connect()

    def _connect(self):
        if self.last_id:
            self.requests_kwargs['headers']['Last-Event-ID'] = self.last_id

        # Use session if set.  Otherwise fall back to requests module.
        requester = self.session or requests
        self.resp = requester.get(self.url, stream=True, **self.requests_kwargs)
        self.resp_iterator = self.resp.iter_content(chunk_size=self.chunk_size)

        # TODO: Ensure we're handling redirects.  Might also stick the 'origin'
        # attribute on Events like the Javascript spec requires.
        self.resp.raise_for_status()

    def _event_complete(self):
        return re.search(end_of_field, self.buf) is not None

    def __iter__(self):
        return self

    def __next__(self):
        decoder = codecs.getincrementaldecoder(
            self.resp.encoding)(errors='replace')
        while not self._event_complete():
            try:
                next_chunk = next(self.resp_iterator)
                if not next_chunk:
                    raise EOFError()
                self.buf += decoder.decode(next_chunk)
            except (StopIteration, requests.RequestException, EOFError) as e:
                time.sleep(self.retry / 1000.0)
                self._connect()

                # The SSE spec only supports resuming from a whole message, so
                # if we have half a message we should throw it out.
                head, sep, tail = self.buf.rpartition('\n')
                self.buf = head + sep
                continue

        split = re.split(end_of_field, self.buf)
        head = split[0]
        tail = "".join(split[1:])

        self.buf = tail
        msg = Event.parse(head)

        # If the server requests a specific retry delay, we need to honor it.
        if msg.retry:
            self.retry = msg.retry

        # last_id should only be set if included in the message.  It's not
        # forgotten if a message omits it.
        if msg.id:
            self.last_id = msg.id

        return msg

    if six.PY2:
        next = __next__

class Event(object):

    sse_line_pattern = re.compile('(?P<name>[^:]*):?( ?(?P<value>.*))?')

    def __init__(self, data='', event='message', id=None, retry=None):
        self.data = data
        self.event = event
        self.id = id
        self.retry = retry

    def dump(self):
        lines = []
        if self.id:
            lines.append('id: %s' % self.id)

        # Only include an event line if it's not the default already.
        if self.event != 'message':
            lines.append('event: %s' % self.event)

        if self.retry:
            lines.append('retry: %s' % self.retry)

        lines.extend('data: %s' % d for d in self.data.split('\n'))
        return '\n'.join(lines) + '\n\n'

    @classmethod
    def parse(cls, raw):
        """
        Given a possibly-multiline string representing an SSE message, parse it
        and return a Event object.
        """
        msg = cls()
        for line in raw.splitlines():
            m = cls.sse_line_pattern.match(line)
            if m is None:
                # Malformed line.  Discard but warn.
                warnings.warn('Invalid SSE line: "%s"' % line, SyntaxWarning)
                continue

            name = m.group('name')
            if name == '':
                # line began with a ":", so is a comment.  Ignore
                continue
            value = m.group('value')

            if name == 'data':
                # If we already have some data, then join to it with a newline.
                # Else this is it.
                if msg.data:
                    msg.data = '%s\n%s' % (msg.data, value)
                else:
                    msg.data = value
            elif name == 'event':
                msg.event = value
            elif name == 'id':
                msg.id = value
            elif name == 'retry':
                msg.retry = int(value)

        return msg

    def __str__(self):
        return self.data
<|endoftext|>