<commit_before>""" Provides classes to run TankCore from console environment """
import ConfigParser
import datetime
import fnmatch
import glob
import logging
import os
import sys
import time
import traceback
import signal
from optparse import OptionParser

import yaml
from pkg_resources import resource_filename
from ..config_converter.converter import convert_ini, old_section_name_mapper, option_converter, guess_plugin
from .tankcore import TankCore, LockError
from ..common.resource import manager as resource_manager

class RealConsoleMarkup(object):
    '''
    Took colors from here: https://www.siafoo.net/snippet/88
    '''
    WHITE_ON_BLACK = '\033[37;40m'
    TOTAL_RESET = '\033[0m'
    clear = "\x1b[2J\x1b[H"
    new_line = u"\n"

    YELLOW = '\033[1;33m'
    RED = '\033[1;31m'
    RED_DARK = '\033[31;3m'
    RESET = '\033[1;m'
    CYAN = "\033[1;36m"
    GREEN = "\033[1;32m"
    WHITE = "\033[1;37m"
    MAGENTA = '\033[1;35m'
    BG_MAGENTA = '\033[1;45m'
    BG_GREEN = '\033[1;42m'
    BG_BROWN = '\033[1;43m'
    BG_CYAN = '\033[1;46m'

    def clean_markup(self, orig_str):
        ''' clean markup from string '''
        for val in [
            self.YELLOW, self.RED, self.RESET, self.CYAN, self.BG_MAGENTA,
            self.WHITE, self.BG_GREEN, self.GREEN, self.BG_BROWN,
            self.RED_DARK, self.MAGENTA, self.BG_CYAN
        ]:
            orig_str = orig_str.replace(val, '')
        return orig_str

class SingleLevelFilter(logging.Filter):
    """Exclude or approve one msg type at a time.    """

    def __init__(self, passlevel, reject):
        logging.Filter.__init__(self)
        self.passlevel = passlevel
        self.reject = reject

    def filter(self, record):
        if self.reject:
            return record.levelno != self.passlevel
        else:
            return record.levelno == self.passlevel

def signal_handler(sig, frame):
    """ required for non-tty python runs to interrupt """
    raise KeyboardInterrupt()

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

def load_cfg(cfg_filename):
    """

    :type cfg_filename: str
    """
    if cfg_filename.endswith('.yaml'):
        with open(cfg_filename) as f:
            cfg = yaml.load(f)
    else:
        cfg = convert_ini(cfg_filename)
    return cfg

def cfg_folder_loader(path):
    """
    :type path: str
    """
    CFG_WILDCARD = '*.yaml'
    return [load_cfg(filename) for filename in sorted(glob.glob(os.path.join(path, CFG_WILDCARD)))]

def load_core_base_cfg():
    return load_cfg(resource_filename(__name__, 'config/00-base.yaml'))

def load_local_base_cfg():
    return cfg_folder_loader('/etc/yandex-tank')

def parse_option(key, value):
    # type: (str, str) -> {str: dict}
    section_name, option_name = key.strip().split('.')
    return {old_section_name_mapper(section_name):
            dict([option_converter(guess_plugin(section_name), (option_name, value))])
            }

def parse_options(options):
    """
    :type options: list of str
    :rtype: list of dict
    """
    if options is None:
        return []
    else:
        return [
            parse_option(key, value.strip())
            for key, value
            in [option.split('=') for option in options]
        ]

def apply_shorthand_options(config, options, default_section='DEFAULT'):
    """

    :type config: ConfigParser.ConfigParser

    """
    for option_str in options:
        key, value = option_str.split('=')
        try:
            section, option = key.split('.')
        except ValueError:
            section = default_section
            option = key
        if not config.has_section(section):
            config.add_section(section)
        config.set(section, option, value)
    return config
#
#
# def override_config_from_cmdline(options, config):
#     """ override config options from command line"""
#     if options:
#         return apply_shorthand_options(config, options.option)
#     else:
#         return config

def load_ini_cfgs(config_files):
    config_filenames = [resource_manager.resource_filename(config) for config in config_files]
    cfg = ConfigParser.ConfigParser()
    cfg.read(config_filenames)

    dotted_options = []
    for option, value in cfg.items('tank'):
        if '.' in option:
            dotted_options += [option + '=' + value]

    cfg = apply_shorthand_options(cfg, dotted_options)
    cfg.set('tank', 'pid', str(os.getpid()))
    return cfg

def get_default_configs():
    """ returns default configs list, from /etc and home dir """
    # initialize basic defaults
    configs = [resource_filename(__name__, 'config/00-base.ini')]
    baseconfigs_location = '/etc/yandex-tank'
    try:
        conf_files = sorted(os.listdir(baseconfigs_location))
        for filename in conf_files:
            if fnmatch.fnmatch(filename, '*.ini'):
                configs += [
                    os.path.realpath(
                        baseconfigs_location + os.sep + filename)
                ]
    except OSError:
        logging.warn(
            baseconfigs_location +
            ' is not accessible to get configs list')

    configs += [os.path.expanduser('~/.yandex-tank')]
    return configs

def get_depr_cfg(config_files, no_rc, cmd_options):
    try:
        all_config_files = []

        if not no_rc:
            all_config_files = get_default_configs()

        if not config_files:
            if os.path.exists(os.path.realpath('load.ini')):
                all_config_files += [os.path.realpath('load.ini')]
            elif os.path.exists(os.path.realpath('load.conf')):
                # just for old 'lunapark' compatibility
                conf_file = os.path.realpath('load.conf')
                all_config_files += [conf_file]
        else:
            for config_file in config_files:
                all_config_files.append(config_file)

        cfg_ini = load_ini_cfgs([cfg_file for cfg_file in all_config_files if cfg_file.endswith('.ini')])
        return apply_shorthand_options(cfg_ini, cmd_options)
    except Exception as ex:
        sys.stderr.write(RealConsoleMarkup.RED)
        sys.stderr.write(RealConsoleMarkup.RESET)
        sys.stderr.write(RealConsoleMarkup.TOTAL_RESET)
        raise ex

def load_tank_core(config_files, cmd_options, no_rc, *other_opts):
    other_opts = list(other_opts) if other_opts else []
    cmd_options = cmd_options if cmd_options else []
    return TankCore([load_core_base_cfg()] +
                    load_local_base_cfg() +
                    [load_cfg(cfg) for cfg in config_files] +
                    list(other_opts) +
                    parse_options(cmd_options),
                    cfg_depr=get_depr_cfg(config_files, no_rc, cmd_options))

class ConsoleTank:
    """    Worker class that runs tank core accepting cmdline params    """

    IGNORE_LOCKS = "ignore_locks"

    def __init__(self, options, ammofile):
        lock_cfg = {'core': {'lock_dir': options.lock_dir}} if options.lock_dir else {}
        self.options = options

        self.baseconfigs_location = '/etc/yandex-tank'

        self.init_logging()
        self.log = logging.getLogger(__name__)

        self.core = load_tank_core(options.config, options.option, options.no_rc, lock_cfg)

        self.ammofile = ammofile

        self.core.add_artifact_file(options.log)

        self.signal_count = 0
        self.scheduled_start = None

    def set_baseconfigs_dir(self, directory):
        """        Set directory where to read configs set        """
        self.baseconfigs_location = directory

    def init_logging(self):
        """ Set up logging, as it is very important for console tool """
        logger = logging.getLogger('')
        logger.setLevel(logging.DEBUG)
        log_filename = self.options.log
        # create file handler which logs even debug messages
        if log_filename:
            file_handler = logging.FileHandler(log_filename)
            file_handler.setLevel(logging.DEBUG)
            file_handler.setFormatter(
                logging.Formatter(
                    "%(asctime)s [%(levelname)s] %(name)s %(filename)s:%(lineno)d\t%(message)s"
                ))
            logger.addHandler(file_handler)

        # create console handler with a higher log level
        console_handler = logging.StreamHandler(sys.stdout)
        stderr_hdl = logging.StreamHandler(sys.stderr)

        fmt_verbose = logging.Formatter(
            "%(asctime)s [%(levelname)s] %(name)s %(filename)s:%(lineno)d\t%(message)s"
        )
        fmt_regular = logging.Formatter(
            "%(asctime)s [%(levelname)s] %(message)s", "%H:%M:%S")

        if self.options.verbose:
            console_handler.setLevel(logging.DEBUG)
            console_handler.setFormatter(fmt_verbose)
            stderr_hdl.setFormatter(fmt_verbose)
        elif self.options.quiet:
            console_handler.setLevel(logging.WARNING)
            console_handler.setFormatter(fmt_regular)
            stderr_hdl.setFormatter(fmt_regular)
        else:
            console_handler.setLevel(logging.INFO)
            console_handler.setFormatter(fmt_regular)
            stderr_hdl.setFormatter(fmt_regular)

        f_err = SingleLevelFilter(logging.ERROR, True)
        f_warn = SingleLevelFilter(logging.WARNING, True)
        f_crit = SingleLevelFilter(logging.CRITICAL, True)
        console_handler.addFilter(f_err)
        console_handler.addFilter(f_warn)
        console_handler.addFilter(f_crit)
        logger.addHandler(console_handler)

        f_info = SingleLevelFilter(logging.INFO, True)
        f_debug = SingleLevelFilter(logging.DEBUG, True)
        stderr_hdl.addFilter(f_info)
        stderr_hdl.addFilter(f_debug)
        logger.addHandler(stderr_hdl)

    def configure(self):
        while True:
            try:
                self.core.get_lock(self.options.ignore_lock)
                break
            except LockError:
                if self.options.lock_fail:
                    raise RuntimeError("Lock file present, cannot continue")
                self.log.exception(
                    "Couldn't get lock. Will retry in 5 seconds...")
                time.sleep(5)

        if self.ammofile:
            self.log.debug("Ammofile: %s", self.ammofile)
            self.core.set_option("phantom", 'ammofile', self.ammofile[0])

        try:
            self.core.load_plugins()

            if self.options.scheduled_start:
                try:
                    self.scheduled_start = datetime.datetime.strptime(
                        self.options.scheduled_start, '%Y-%m-%d %H:%M:%S')
                except ValueError:
                    self.scheduled_start = datetime.datetime.strptime(
                        datetime.datetime.now().strftime('%Y-%m-%d ') +
                        self.options.scheduled_start, '%Y-%m-%d %H:%M:%S')

        except Exception as ex:
            self.log.info("Exception: %s", traceback.format_exc(ex))
            sys.stderr.write(RealConsoleMarkup.RED)
            self.log.error("%s", ex)
            sys.stderr.write(RealConsoleMarkup.RESET)
            sys.stderr.write(RealConsoleMarkup.TOTAL_RESET)
            self.core.release_lock()
            raise ex

    def __graceful_shutdown(self):
        """ call shutdown routines """
        retcode = 1
        self.log.info("Trying to shutdown gracefully...")
        retcode = self.core.plugins_end_test(retcode)
        retcode = self.core.plugins_post_process(retcode)
        self.log.info("Done graceful shutdown")
        return retcode

    def perform_test(self):
        """
        Run the test sequence via Tank Core
        """
        self.log.info("Performing test")
        retcode = 1
        try:
            self.core.plugins_configure()
            self.core.plugins_prepare_test()
            if self.scheduled_start:
                self.log.info(
                    "Waiting scheduled time: %s...", self.scheduled_start)
                while datetime.datetime.now() < self.scheduled_start:
                    self.log.debug(
                        "Not yet: %s < %s",
                        datetime.datetime.now(), self.scheduled_start)
                    time.sleep(1)
                self.log.info("Time has come: %s", datetime.datetime.now())

            if self.options.manual_start:
                raw_input("Press Enter key to start test:")

            self.core.plugins_start_test()
            retcode = self.core.wait_for_finish()
            retcode = self.core.plugins_end_test(retcode)
            retcode = self.core.plugins_post_process(retcode)

        except KeyboardInterrupt as ex:
            sys.stdout.write(RealConsoleMarkup.YELLOW)
            self.log.info(
                "Do not press Ctrl+C again, the test will be broken otherwise")
            sys.stdout.write(RealConsoleMarkup.RESET)
            sys.stdout.write(RealConsoleMarkup.TOTAL_RESET)
            self.signal_count += 1
            self.log.debug(
                "Caught KeyboardInterrupt: %s", traceback.format_exc(ex))
            try:
                retcode = self.__graceful_shutdown()
            except KeyboardInterrupt as ex:
                self.log.debug(
                    "Caught KeyboardInterrupt again: %s",
                    traceback.format_exc(ex))
                self.log.info(
                    "User insists on exiting, aborting graceful shutdown...")
                retcode = 1

        except Exception as ex:
            self.log.info("Exception: %s", traceback.format_exc(ex))
            sys.stderr.write(RealConsoleMarkup.RED)
            self.log.error("%s", ex)
            sys.stderr.write(RealConsoleMarkup.RESET)
            sys.stderr.write(RealConsoleMarkup.TOTAL_RESET)
            retcode = self.__graceful_shutdown()
            self.core.release_lock()
        finally:
            self.core.close()

        self.log.info("Done performing test with code %s", retcode)
        return retcode

class DevNullOpts:
    def __init__(self):
        pass

    log = "/dev/null"

class CompletionHelperOptionParser(OptionParser):
    def __init__(self):
        OptionParser.__init__(self, add_help_option=False)
        self.add_option(
            '--bash-switches-list',
            action='store_true',
            dest="list_switches",
            help="Options list")
        self.add_option(
            '--bash-options-prev',
            action='store',
            dest="list_options_prev",
            help="Options list")
        self.add_option(
            '--bash-options-cur',
            action='store',
            dest="list_options_cur",
            help="Options list")

    def error(self, msg):
        pass

    def exit(self, status=0, msg=None):
        pass

    def handle_request(self, parser):
        options = self.parse_args()[0]
        if options.list_switches:
            opts = []
            for option in parser.option_list:
                if "--bash" not in option.get_opt_string():
                    opts.append(option.get_opt_string())
            print ' '.join(opts)
            exit(0)

        if options.list_options_cur or options.list_options_prev:
            cmdtank = ConsoleTank(DevNullOpts(), None)
            cmdtank.core.load_configs(get_default_configs(cmdtank.baseconfigs_location, cmdtank.log))
            cmdtank.core.load_plugins()

            opts = []
            for option in cmdtank.core.get_available_options():
                opts.append(cmdtank.core.SECTION + '.' + option + '=')

            plugin_keys = cmdtank.core.config.get_options(
                cmdtank.core.SECTION, cmdtank.core.PLUGIN_PREFIX)
            for (plugin_name, plugin_path) in plugin_keys:
                opts.append(
                    cmdtank.core.SECTION + '.' + cmdtank.core.PLUGIN_PREFIX +
                    plugin_name + '=')

            for plugin in cmdtank.core.plugins:
                for option in plugin.get_available_options():
                    opts.append(plugin.SECTION + '.' + option + '=')
            print ' '.join(sorted(opts))
            exit(0)
<commit_msg>removed commented code<commit_after>""" Provides classes to run TankCore from console environment """
import ConfigParser
import datetime
import fnmatch
import glob
import logging
import os
import sys
import time
import traceback
import signal
from optparse import OptionParser

import yaml
from pkg_resources import resource_filename
from ..config_converter.converter import convert_ini, old_section_name_mapper, option_converter, guess_plugin
from .tankcore import TankCore, LockError
from ..common.resource import manager as resource_manager

class RealConsoleMarkup(object):
    '''
    Took colors from here: https://www.siafoo.net/snippet/88
    '''
    WHITE_ON_BLACK = '\033[37;40m'
    TOTAL_RESET = '\033[0m'
    clear = "\x1b[2J\x1b[H"
    new_line = u"\n"

    YELLOW = '\033[1;33m'
    RED = '\033[1;31m'
    RED_DARK = '\033[31;3m'
    RESET = '\033[1;m'
    CYAN = "\033[1;36m"
    GREEN = "\033[1;32m"
    WHITE = "\033[1;37m"
    MAGENTA = '\033[1;35m'
    BG_MAGENTA = '\033[1;45m'
    BG_GREEN = '\033[1;42m'
    BG_BROWN = '\033[1;43m'
    BG_CYAN = '\033[1;46m'

    def clean_markup(self, orig_str):
        ''' clean markup from string '''
        for val in [
            self.YELLOW, self.RED, self.RESET, self.CYAN, self.BG_MAGENTA,
            self.WHITE, self.BG_GREEN, self.GREEN, self.BG_BROWN,
            self.RED_DARK, self.MAGENTA, self.BG_CYAN
        ]:
            orig_str = orig_str.replace(val, '')
        return orig_str

class SingleLevelFilter(logging.Filter):
    """Exclude or approve one msg type at a time.    """

    def __init__(self, passlevel, reject):
        logging.Filter.__init__(self)
        self.passlevel = passlevel
        self.reject = reject

    def filter(self, record):
        if self.reject:
            return record.levelno != self.passlevel
        else:
            return record.levelno == self.passlevel

def signal_handler(sig, frame):
    """ required for non-tty python runs to interrupt """
    raise KeyboardInterrupt()

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

def load_cfg(cfg_filename):
    """

    :type cfg_filename: str
    """
    if cfg_filename.endswith('.yaml'):
        with open(cfg_filename) as f:
            cfg = yaml.load(f)
    else:
        cfg = convert_ini(cfg_filename)
    return cfg

def cfg_folder_loader(path):
    """
    :type path: str
    """
    CFG_WILDCARD = '*.yaml'
    return [load_cfg(filename) for filename in sorted(glob.glob(os.path.join(path, CFG_WILDCARD)))]

def load_core_base_cfg():
    return load_cfg(resource_filename(__name__, 'config/00-base.yaml'))

def load_local_base_cfg():
    return cfg_folder_loader('/etc/yandex-tank')

def parse_option(key, value):
    # type: (str, str) -> {str: dict}
    section_name, option_name = key.strip().split('.')
    return {old_section_name_mapper(section_name):
            dict([option_converter(guess_plugin(section_name), (option_name, value))])
            }

def parse_options(options):
    """
    :type options: list of str
    :rtype: list of dict
    """
    if options is None:
        return []
    else:
        return [
            parse_option(key, value.strip())
            for key, value
            in [option.split('=') for option in options]
        ]

def apply_shorthand_options(config, options, default_section='DEFAULT'):
    """

    :type config: ConfigParser.ConfigParser
    """
    for option_str in options:
        key, value = option_str.split('=')
        try:
            section, option = key.split('.')
        except ValueError:
            section = default_section
            option = key
        if not config.has_section(section):
            config.add_section(section)
        config.set(section, option, value)
    return config

def load_ini_cfgs(config_files):
    config_filenames = [resource_manager.resource_filename(config) for config in config_files]
    cfg = ConfigParser.ConfigParser()
    cfg.read(config_filenames)

    dotted_options = []
    for option, value in cfg.items('tank'):
        if '.' in option:
            dotted_options += [option + '=' + value]

    cfg = apply_shorthand_options(cfg, dotted_options)
    cfg.set('tank', 'pid', str(os.getpid()))
    return cfg

def get_default_configs():
    """ returns default configs list, from /etc and home dir """
    # initialize basic defaults
    configs = [resource_filename(__name__, 'config/00-base.ini')]
    baseconfigs_location = '/etc/yandex-tank'
    try:
        conf_files = sorted(os.listdir(baseconfigs_location))
        for filename in conf_files:
            if fnmatch.fnmatch(filename, '*.ini'):
                configs += [
                    os.path.realpath(
                        baseconfigs_location + os.sep + filename)
                ]
    except OSError:
        logging.warn(
            baseconfigs_location +
            ' is not accessible to get configs list')

    configs += [os.path.expanduser('~/.yandex-tank')]
    return configs

def get_depr_cfg(config_files, no_rc, cmd_options):
    try:
        all_config_files = []

        if not no_rc:
            all_config_files = get_default_configs()

        if not config_files:
            if os.path.exists(os.path.realpath('load.ini')):
                all_config_files += [os.path.realpath('load.ini')]
            elif os.path.exists(os.path.realpath('load.conf')):
                # just for old 'lunapark' compatibility
                conf_file = os.path.realpath('load.conf')
                all_config_files += [conf_file]
        else:
            for config_file in config_files:
                all_config_files.append(config_file)

        cfg_ini = load_ini_cfgs([cfg_file for cfg_file in all_config_files if cfg_file.endswith('.ini')])
        return apply_shorthand_options(cfg_ini, cmd_options)
    except Exception as ex:
        sys.stderr.write(RealConsoleMarkup.RED)
        sys.stderr.write(RealConsoleMarkup.RESET)
        sys.stderr.write(RealConsoleMarkup.TOTAL_RESET)
        raise ex

def load_tank_core(config_files, cmd_options, no_rc, *other_opts):
    other_opts = list(other_opts) if other_opts else []
    cmd_options = cmd_options if cmd_options else []
    return TankCore([load_core_base_cfg()] +
                    load_local_base_cfg() +
                    [load_cfg(cfg) for cfg in config_files] +
                    list(other_opts) +
                    parse_options(cmd_options),
                    cfg_depr=get_depr_cfg(config_files, no_rc, cmd_options))

class ConsoleTank:
    """    Worker class that runs tank core accepting cmdline params    """

    IGNORE_LOCKS = "ignore_locks"

    def __init__(self, options, ammofile):
        lock_cfg = {'core': {'lock_dir': options.lock_dir}} if options.lock_dir else {}
        self.options = options

        self.baseconfigs_location = '/etc/yandex-tank'

        self.init_logging()
        self.log = logging.getLogger(__name__)

        self.core = load_tank_core(options.config, options.option, options.no_rc, lock_cfg)

        self.ammofile = ammofile

        self.core.add_artifact_file(options.log)

        self.signal_count = 0
        self.scheduled_start = None

    def set_baseconfigs_dir(self, directory):
        """        Set directory where to read configs set        """
        self.baseconfigs_location = directory

    def init_logging(self):
        """ Set up logging, as it is very important for console tool """
        logger = logging.getLogger('')
        logger.setLevel(logging.DEBUG)
        log_filename = self.options.log
        # create file handler which logs even debug messages
        if log_filename:
            file_handler = logging.FileHandler(log_filename)
            file_handler.setLevel(logging.DEBUG)
            file_handler.setFormatter(
                logging.Formatter(
                    "%(asctime)s [%(levelname)s] %(name)s %(filename)s:%(lineno)d\t%(message)s"
                ))
            logger.addHandler(file_handler)

        # create console handler with a higher log level
        console_handler = logging.StreamHandler(sys.stdout)
        stderr_hdl = logging.StreamHandler(sys.stderr)

        fmt_verbose = logging.Formatter(
            "%(asctime)s [%(levelname)s] %(name)s %(filename)s:%(lineno)d\t%(message)s"
        )
        fmt_regular = logging.Formatter(
            "%(asctime)s [%(levelname)s] %(message)s", "%H:%M:%S")

        if self.options.verbose:
            console_handler.setLevel(logging.DEBUG)
            console_handler.setFormatter(fmt_verbose)
            stderr_hdl.setFormatter(fmt_verbose)
        elif self.options.quiet:
            console_handler.setLevel(logging.WARNING)
            console_handler.setFormatter(fmt_regular)
            stderr_hdl.setFormatter(fmt_regular)
        else:
            console_handler.setLevel(logging.INFO)
            console_handler.setFormatter(fmt_regular)
            stderr_hdl.setFormatter(fmt_regular)

        f_err = SingleLevelFilter(logging.ERROR, True)
        f_warn = SingleLevelFilter(logging.WARNING, True)
        f_crit = SingleLevelFilter(logging.CRITICAL, True)
        console_handler.addFilter(f_err)
        console_handler.addFilter(f_warn)
        console_handler.addFilter(f_crit)
        logger.addHandler(console_handler)

        f_info = SingleLevelFilter(logging.INFO, True)
        f_debug = SingleLevelFilter(logging.DEBUG, True)
        stderr_hdl.addFilter(f_info)
        stderr_hdl.addFilter(f_debug)
        logger.addHandler(stderr_hdl)

    def configure(self):
        while True:
            try:
                self.core.get_lock(self.options.ignore_lock)
                break
            except LockError:
                if self.options.lock_fail:
                    raise RuntimeError("Lock file present, cannot continue")
                self.log.exception(
                    "Couldn't get lock. Will retry in 5 seconds...")
                time.sleep(5)

        if self.ammofile:
            self.log.debug("Ammofile: %s", self.ammofile)
            self.core.set_option("phantom", 'ammofile', self.ammofile[0])

        try:
            self.core.load_plugins()

            if self.options.scheduled_start:
                try:
                    self.scheduled_start = datetime.datetime.strptime(
                        self.options.scheduled_start, '%Y-%m-%d %H:%M:%S')
                except ValueError:
                    self.scheduled_start = datetime.datetime.strptime(
                        datetime.datetime.now().strftime('%Y-%m-%d ') +
                        self.options.scheduled_start, '%Y-%m-%d %H:%M:%S')

        except Exception as ex:
            self.log.info("Exception: %s", traceback.format_exc(ex))
            sys.stderr.write(RealConsoleMarkup.RED)
            self.log.error("%s", ex)
            sys.stderr.write(RealConsoleMarkup.RESET)
            sys.stderr.write(RealConsoleMarkup.TOTAL_RESET)
            self.core.release_lock()
            raise ex

    def __graceful_shutdown(self):
        """ call shutdown routines """
        retcode = 1
        self.log.info("Trying to shutdown gracefully...")
        retcode = self.core.plugins_end_test(retcode)
        retcode = self.core.plugins_post_process(retcode)
        self.log.info("Done graceful shutdown")
        return retcode

    def perform_test(self):
        """
        Run the test sequence via Tank Core
        """
        self.log.info("Performing test")
        retcode = 1
        try:
            self.core.plugins_configure()
            self.core.plugins_prepare_test()
            if self.scheduled_start:
                self.log.info(
                    "Waiting scheduled time: %s...", self.scheduled_start)
                while datetime.datetime.now() < self.scheduled_start:
                    self.log.debug(
                        "Not yet: %s < %s",
                        datetime.datetime.now(), self.scheduled_start)
                    time.sleep(1)
                self.log.info("Time has come: %s", datetime.datetime.now())

            if self.options.manual_start:
                raw_input("Press Enter key to start test:")

            self.core.plugins_start_test()
            retcode = self.core.wait_for_finish()
            retcode = self.core.plugins_end_test(retcode)
            retcode = self.core.plugins_post_process(retcode)

        except KeyboardInterrupt as ex:
            sys.stdout.write(RealConsoleMarkup.YELLOW)
            self.log.info(
                "Do not press Ctrl+C again, the test will be broken otherwise")
            sys.stdout.write(RealConsoleMarkup.RESET)
            sys.stdout.write(RealConsoleMarkup.TOTAL_RESET)
            self.signal_count += 1
            self.log.debug(
                "Caught KeyboardInterrupt: %s", traceback.format_exc(ex))
            try:
                retcode = self.__graceful_shutdown()
            except KeyboardInterrupt as ex:
                self.log.debug(
                    "Caught KeyboardInterrupt again: %s",
                    traceback.format_exc(ex))
                self.log.info(
                    "User insists on exiting, aborting graceful shutdown...")
                retcode = 1

        except Exception as ex:
            self.log.info("Exception: %s", traceback.format_exc(ex))
            sys.stderr.write(RealConsoleMarkup.RED)
            self.log.error("%s", ex)
            sys.stderr.write(RealConsoleMarkup.RESET)
            sys.stderr.write(RealConsoleMarkup.TOTAL_RESET)
            retcode = self.__graceful_shutdown()
            self.core.release_lock()
        finally:
            self.core.close()

        self.log.info("Done performing test with code %s", retcode)
        return retcode

class DevNullOpts:
    def __init__(self):
        pass

    log = "/dev/null"

class CompletionHelperOptionParser(OptionParser):
    def __init__(self):
        OptionParser.__init__(self, add_help_option=False)
        self.add_option(
            '--bash-switches-list',
            action='store_true',
            dest="list_switches",
            help="Options list")
        self.add_option(
            '--bash-options-prev',
            action='store',
            dest="list_options_prev",
            help="Options list")
        self.add_option(
            '--bash-options-cur',
            action='store',
            dest="list_options_cur",
            help="Options list")

    def error(self, msg):
        pass

    def exit(self, status=0, msg=None):
        pass

    def handle_request(self, parser):
        options = self.parse_args()[0]
        if options.list_switches:
            opts = []
            for option in parser.option_list:
                if "--bash" not in option.get_opt_string():
                    opts.append(option.get_opt_string())
            print ' '.join(opts)
            exit(0)

        if options.list_options_cur or options.list_options_prev:
            cmdtank = ConsoleTank(DevNullOpts(), None)
            cmdtank.core.load_configs(get_default_configs(cmdtank.baseconfigs_location, cmdtank.log))
            cmdtank.core.load_plugins()

            opts = []
            for option in cmdtank.core.get_available_options():
                opts.append(cmdtank.core.SECTION + '.' + option + '=')

            plugin_keys = cmdtank.core.config.get_options(
                cmdtank.core.SECTION, cmdtank.core.PLUGIN_PREFIX)
            for (plugin_name, plugin_path) in plugin_keys:
                opts.append(
                    cmdtank.core.SECTION + '.' + cmdtank.core.PLUGIN_PREFIX +
                    plugin_name + '=')

            for plugin in cmdtank.core.plugins:
                for option in plugin.get_available_options():
                    opts.append(plugin.SECTION + '.' + option + '=')
            print ' '.join(sorted(opts))
            exit(0)
<|endoftext|>


<commit_before>import string
import random
import inspect
import visitor
import astnode as ast
from codegen import calvin_astgen, calvin_components, query, PortlistRewrite
from parser import calvin_parse
from calvin.actorstore.store import DocumentationStore

_docstore = DocumentationStore()

def _refname(name):
   return name.replace(':', '_')

def _lookup_definition(actor_type, root):
    if '.' in actor_type:
        doc = _docstore.metadata(actor_type)
        if not doc['is_known']:
            return ([], [], '')
        return (doc['inputs'], doc['outputs'], doc['type'])
    comps = query(root, kind=ast.Component, attributes={'name':actor_type}, maxdepth=2)
    if not comps:
        return ([], [], '')
    return (comps[0].inports, comps[0].outports, 'component')

class BaseRenderer(object):
    """docstring for BaseRenderer"""
    def __init__(self, debug=False):
        super(BaseRenderer, self).__init__()
        self.debug = debug

    def _default(self, node, order):
        if self.debug:
            print "Not handling: {} ({})".format(node.__class__.__name__, order)
        return ''

    def _add(self, stmt):
        if stmt:
            self.statements.append(stmt)

    def render(self, node, order='preorder'):
        handler = getattr(self, node.__class__.__name__, self._default)
        args, _, _, _ = inspect.getargspec(handler)
        if len(args) == 3:
            self._add(handler(node, order))
        elif order == 'preorder':
            self._add(handler(node))

    def begin(self):
        self.statements = []
        self._add(self.preamble())

    def end(self):
        self._add(self.postamble())

    def result(self):
        return ''.join(self.statements)

    def preamble(self):
        return ''

    def postamble(self):
        return ''

# FIXME: PortList with TransformedPort breaks graphviz
class DotRenderer(BaseRenderer):

    def __init__(self, show_args=False, debug=False):
        super(DotRenderer, self).__init__()
        self.debug = debug
        self.show_args = show_args

    def _random_id(self):
        return ''.join(random.choice(string.ascii_uppercase) for x in range(8))

    def _truncate_label(self, label, maxlen=16):
        if len(label) > maxlen:
            label = label[:maxlen/2-2] + " ... " + label[-maxlen/2-2:]
        return label

    def preamble(self):
        return 'digraph structs { node [shape=plaintext]; rankdir=LR;\n'

    def postamble(self):
        return '}\n'

    def Assignment(self, node, order):
        # ident, actor_type, args
        root = node
        while root.parent:
            root = root.parent
        _inports, _outports, _type = _lookup_definition(node.actor_type, root)
        inlen = len(_inports)
        outlen = len(_outports)
        portrows = max(inlen, outlen)
        inports = _inports + ['']*(portrows - inlen)
        outports = _outports + ['']*(portrows - outlen)
        hdrcolor = {
            'actor': 'lightblue',
            'component': 'lightyellow'
        }.get(_type, 'tomato')
        show_args = self.show_args and node.children

        if order == 'preorder':
            lines = []
            lines.append('{} [label=<'.format(_refname(node.ident)))
            lines.append('
')
            # Name
            lines.append('
{0}
'.format(node.ident, hdrcolor))
            # Class
            lines.append('
{}
'.format(node.actor_type))
            # Skipping arguments arriving inorder by commenting them out for now
            lines.append('
' if show_args else '/* ')
            return '\n'.join(lines)

        if order == 'inorder':
            return '
\n
' if show_args else ', '

        if order == 'postorder':
            # Close comment
            lines = ['
'if show_args else ' */']
            is_first=True
            for inport, outport in zip(inports, outports):
                inref = ' bgcolor="lightgrey" PORT="{}_in"'.format(inport) if inport else ''
                outref = ' bgcolor="lightgrey" PORT="{}_out"'.format(outport) if outport else ''
                if is_first:
                    is_first = False
                    middle = '    	'.format(portrows)
                else:
                    middle = ''
                lines.append('
{1}	{4}{3}
'.format(inref, inport, outref, outport, middle))
            lines.append('
>];\n')

            return '\n'.join(lines)

    def OutPort(self, node):
        return "{}:{}_out:e".format(_refname(node.actor), node.port)

    def InPort(self, node):
        return "{}:{}_in:w".format(_refname(node.actor), node.port)

    def InternalOutPort(self, node):
        return "{}_out:e".format(node.port)

    def InternalInPort(self, node):
        return "{}_in:w".format(node.port)

    def ImplicitPort(self, node, order):
        if order == 'preorder':
            return '{{{} [label="'.format(self._random_id())
        if order == 'postorder':
            return '" shape=box]}'
        # return "{}".format(node.arg)

    def TransformedPort(self, node):
        # N.B. port and value are properties of node, not children
        self.render(node.port)
        return ' [label=<

/{}/

>]'.format(self.Value(node.value))

    def Void(self, node):
        return '{{{} [label=""]}} [arrowhead=tee]'.format(self._random_id())

    def Value(self, node):
        fmt = "'{}'" if type(node.value) is str else '{}'
        return self._truncate_label(fmt.format(node.value))

    def NamedArg(self, node, order):
        if order == 'inorder':
            return " = "

    def Id(self, node):
        return "{}".format(node.ident)

    def Link(self, node, order):
        if order == 'inorder' : return ' -> '
        if order == 'postorder' : return ';\n'

    def Component(self, node, order):
        if order == 'preorder':
            lines = ['subgraph {']
            for p in node.inports:
                lines.append('{{rank="source" {0}_out [shape="cds" style="filled" fillcolor="lightgrey" label="{0}"]}};'.format(p))
            for p in node.outports:
                lines.append('{{rank="sink" {0}_in [shape="cds" style="filled" fillcolor="lightgrey" label="{0}"]}};'.format(p))
            return '\n'.join(lines)

        if order == 'postorder':
            return '}\n'

class Visualize(object):
   """docstring for VizPrinter"""
   def __init__(self, renderer=None):
       super(Visualize, self).__init__()
       self.renderer = renderer or DotRenderer()

   def process(self, root):
       self.renderer.begin()
       self.visit(root)
       self.renderer.end()
       return self.renderer.result()

   @visitor.on('node')
   def visit(self, node):
       pass

   @visitor.when(ast.Node)
   def visit(self, node):
       self.renderer.render(node, order='preorder')
       if not node.children:
           self.renderer.render(node, order='postorder')
       for n in node.children or []:
           self.visit(n)
           self.renderer.render(node, order='postorder' if n is node.children[-1] else 'inorder')

def visualize_script(source_text, show_args=False):
    """Process script and return graphviz (dot) source representing application."""
    # Here we need the unprocessed tree ...
    ir, issuetracker = calvin_parse(source_text)
    # ... but expand portlists to simplify rendering
    rw = PortlistRewrite(issuetracker)
    rw.visit(ir)
    r = DotRenderer(show_args, debug=False)
    v = Visualize(renderer = r)
    dot_source = v.process(ir)
    return dot_source, issuetracker

def visualize_deployment(source_text, show_args=False):
    ast_root, issuetracker = calvin_astgen(source_text, 'visualizer')
    # Here we need the processed tree
    r = DotRenderer(show_args, debug=False)
    v = Visualize(renderer = r)
    dot_source = v.process(ast_root)
    return dot_source, issuetracker

def visualize_component(source_text, name, show_args=False):
    # STUB
    ir_list, issuetracker = calvin_components(source_text, names=[name])
    r = DotRenderer(show_args, debug=False)
    v = Visualize(renderer = r)
    dot_source = v.process(ir_list[0])
    return dot_source, issuetracker

if __name__ == '__main__':
    source_text = """
    component FilterUnchanged() string -> string {
      iip : std.Init(data="nothing")
      cmp : std.Compare(op="=")
      sel : std.Select()

      .string > cmp.a
      iip.out > cmp.b
      cmp.result > sel.select
      .string > sel.data
      sel.case_true > voidport
      sel.case_false > iip.in
      sel.case_false > .string
    }

    /* Actors */
    src : std.CountTimer()
    snk : io.Print()
    /* Connections */
    src.integer > snk.token
    """

    dot_src, it =  visualize_script(source_text)
    print dot_src

    dot_src, it =  visualize_deployment(source_text)
    print dot_src

    dot_src, it =  visualize_component(source_text, "FilterUnchanged")
    print dot_src

<commit_msg>Minor changes<commit_after>import string
import random
import inspect
import visitor
import astnode as ast
from codegen import calvin_astgen, calvin_components, query, PortlistRewrite
from parser import calvin_parse
from calvin.actorstore.store import DocumentationStore

_docstore = DocumentationStore()

def _refname(name):
   return name.replace(':', '_')

def _lookup_definition(actor_type, root):
    if '.' in actor_type:
        doc = _docstore.metadata(actor_type)
        if not doc['is_known']:
            return ([], [], '')
        return (doc['inputs'], doc['outputs'], doc['type'])
    comps = query(root, kind=ast.Component, attributes={'name':actor_type}, maxdepth=2)
    if not comps:
        return ([], [], '')
    return (comps[0].inports, comps[0].outports, 'component')

class BaseRenderer(object):
    """docstring for BaseRenderer"""
    def __init__(self, debug=False):
        super(BaseRenderer, self).__init__()
        self.debug = debug

    def _default(self, node, order):
        if self.debug:
            print "Not handling: {} ({})".format(node.__class__.__name__, order)
        return ''

    def _add(self, stmt):
        if stmt:
            self.statements.append(stmt)

    def render(self, node, order='preorder'):
        handler = getattr(self, node.__class__.__name__, self._default)
        args, _, _, _ = inspect.getargspec(handler)
        if len(args) == 3:
            self._add(handler(node, order))
        elif order == 'preorder':
            self._add(handler(node))

    def begin(self):
        self.statements = []
        self._add(self.preamble())

    def end(self):
        self._add(self.postamble())

    def result(self):
        return ''.join(self.statements)

    def preamble(self):
        return ''

    def postamble(self):
        return ''

# FIXME: PortList with TransformedPort breaks graphviz
class DotRenderer(BaseRenderer):

    def __init__(self, show_args=False, debug=False):
        super(DotRenderer, self).__init__()
        self.debug = debug
        self.show_args = show_args

    def _random_id(self):
        return ''.join(random.choice(string.ascii_uppercase) for x in range(8))

    def _truncate_label(self, label, maxlen=16):
        if len(label) > maxlen:
            label = label[:maxlen/2-2] + " ... " + label[-maxlen/2-2:]
        return label

    def preamble(self):
        return 'digraph structs { node [shape=plaintext]; rankdir=LR splines=spline;\n'

    def postamble(self):
        return '}\n'

    def Assignment(self, node, order):
        # ident, actor_type, args
        root = node
        while root.parent:
            root = root.parent
        _inports, _outports, _type = _lookup_definition(node.actor_type, root)
        inlen = len(_inports)
        outlen = len(_outports)
        portrows = max(inlen, outlen)
        inports = _inports + ['']*(portrows - inlen)
        outports = _outports + ['']*(portrows - outlen)
        hdrcolor = {
            'actor': 'lightblue',
            'component': 'lightyellow'
        }.get(_type, 'tomato')
        show_args = self.show_args and node.children

        if order == 'preorder':
            lines = []
            lines.append('{} [label=<'.format(_refname(node.ident)))
            lines.append('
')
            # Name
            lines.append('
{0}
'.format(node.ident, hdrcolor))
            # Class
            lines.append('
{}
'.format(node.actor_type))
            # Skipping arguments arriving inorder by commenting them out for now
            lines.append('
' if show_args else '/* ')
            return '\n'.join(lines)

        if order == 'inorder':
            return '
\n
' if show_args else ', '

        if order == 'postorder':
            # Close comment
            lines = ['
'if show_args else ' */']
            is_first=True
            for inport, outport in zip(inports, outports):
                inref = ' bgcolor="lightgrey" PORT="{}_in"'.format(inport) if inport else ''
                outref = ' bgcolor="lightgrey" PORT="{}_out"'.format(outport) if outport else ''
                if is_first:
                    is_first = False
                    middle = '    	'.format(portrows)
                else:
                    middle = ''
                lines.append('
{1}	{4}{3}
'.format(inref, inport, outref, outport, middle))
            lines.append('
>];\n')

            return '\n'.join(lines)

    def OutPort(self, node):
        return "{}:{}_out:e".format(_refname(node.actor), node.port)

    def InPort(self, node):
        return "{}:{}_in:w".format(_refname(node.actor), node.port)

    def InternalOutPort(self, node):
        return "{}_out:e".format(node.port)

    def InternalInPort(self, node):
        return "{}_in:w".format(node.port)

    def ImplicitPort(self, node, order):
        if order == 'preorder':
            return '{{{} [label="'.format(self._random_id())
        if order == 'postorder':
            return '" shape=box]}'

    def TransformedPort(self, node):
        # N.B. port and value are properties of node, not children
        self.render(node.port)
        return ' [label=<

/{}/

>]'.format(self.Value(node.value))

    def Void(self, node):
        return '{{{} [label=""]}} [arrowhead=tee]'.format(self._random_id())

    def Value(self, node):
        fmt = "'{}'" if type(node.value) is str else '{}'
        return self._truncate_label(fmt.format(node.value))

    def NamedArg(self, node, order):
        if order == 'inorder':
            return " = "

    def Id(self, node):
        return "{}".format(node.ident)

    def Link(self, node, order):
        if order == 'inorder' : return ' -> '
        if order == 'postorder' : return ';\n'

    def Component(self, node, order):
        if order == 'preorder':
            lines = ['subgraph {']
            for p in node.inports:
                lines.append('{{rank="source" {0}_out [shape="cds" style="filled" fillcolor="lightgrey" label="{0}"]}};'.format(p))
            for p in node.outports:
                lines.append('{{rank="sink" {0}_in [shape="cds" style="filled" fillcolor="lightgrey" label="{0}"]}};'.format(p))
            return '\n'.join(lines)

        if order == 'postorder':
            return '}\n'

class Visualize(object):
   """docstring for VizPrinter"""
   def __init__(self, renderer=None):
       super(Visualize, self).__init__()
       self.renderer = renderer or DotRenderer()

   def process(self, root):
       self.renderer.begin()
       self.visit(root)
       self.renderer.end()
       return self.renderer.result()

   @visitor.on('node')
   def visit(self, node):
       pass

   @visitor.when(ast.Node)
   def visit(self, node):
       self.renderer.render(node, order='preorder')
       if not node.children:
           self.renderer.render(node, order='postorder')
       for n in node.children or []:
           self.visit(n)
           self.renderer.render(node, order='postorder' if n is node.children[-1] else 'inorder')

def visualize_script(source_text, show_args=False):
    """Process script and return graphviz (dot) source representing application."""
    # Here we need the unprocessed tree ...
    ir, issuetracker = calvin_parse(source_text)
    # ... but expand portlists to simplify rendering
    rw = PortlistRewrite(issuetracker)
    rw.visit(ir)
    r = DotRenderer(show_args, debug=False)
    v = Visualize(renderer = r)
    dot_source = v.process(ir)
    return dot_source, issuetracker

def visualize_deployment(source_text, show_args=False):
    ast_root, issuetracker = calvin_astgen(source_text, 'visualizer')
    # Here we need the processed tree
    r = DotRenderer(show_args, debug=False)
    v = Visualize(renderer = r)
    dot_source = v.process(ast_root)
    return dot_source, issuetracker

def visualize_component(source_text, name, show_args=False):
    # STUB
    ir_list, issuetracker = calvin_components(source_text, names=[name])
    r = DotRenderer(show_args, debug=False)
    v = Visualize(renderer = r)
    dot_source = v.process(ir_list[0])
    return dot_source, issuetracker

if __name__ == '__main__':
    source_text = """
    component FilterUnchanged() string -> string {
      iip : std.Init(data="nothing")
      cmp : std.Compare(op="=")
      sel : std.Select()

      .string > cmp.a
      iip.out > cmp.b
      cmp.result > sel.select
      .string > sel.data
      sel.case_true > voidport
      sel.case_false > iip.in
      sel.case_false > .string
    }

    /* Actors */
    src : std.CountTimer()
    snk : io.Print()
    /* Connections */
    src.integer > snk.token
    """

    dot_src, it =  visualize_script(source_text)
    print dot_src

    dot_src, it =  visualize_deployment(source_text)
    print dot_src

    dot_src, it =  visualize_component(source_text, "FilterUnchanged")
    print dot_src

<|endoftext|>


<commit_before>"""
An example script of adding an observers and do *something*

It draws a simple unicode reference of an existing installed font.
"""

from mojo.events import addObserver
from mojo.drawingTools import *

class DrawReferenceGlyph(object):

    def __init__(self):
        addObserver(self, "drawReferenceGlyph", "draw")

    def drawReferenceGlyph(self, info):

        glyph = info["glyph"]

        r = 0
        g = 0
        b = 0
        a = .5

        if glyph is not None and glyph.unicode is not None:
            t = unichr(glyph.unicode)

            font("Georgia", 100)
            stroke(None)
            fill(r, g, b, a)
            text(t, (glyph.width + 10, 10))

DrawReferenceGlyph()<commit_msg>check if the glyph is not outside 0xFFFF unicode range<commit_after>"""
An example script of adding an observers and do *something*

It draws a simple unicode reference of an existing installed font.
"""

from mojo.events import addObserver
from mojo.drawingTools import *

class DrawReferenceGlyph(object):

    def __init__(self):
        addObserver(self, "drawReferenceGlyph", "draw")

    def drawReferenceGlyph(self, info):

        glyph = info["glyph"]

        r = 0
        g = 0
        b = 0
        a = .5

        if glyph is not None and glyph.unicode is not None and glyph.unicode < 0xFFFF:
            t = unichr(glyph.unicode)

            font("Georgia", 20)
            stroke(None)
            fill(r, g, b, a)
            text(t, (glyph.width + 10, 10))

DrawReferenceGlyph()<|endoftext|>


<commit_before># coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor

class Formula1IE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?formula1\.com/(?:content/fom-website/)?en/video/\d{4}/\d{1,2}/(?P<id>.+?)\.html'
    _TESTS = [{
        'url': 'http://www.formula1.com/content/fom-website/en/video/2016/5/Race_highlights_-_Spain_2016.html',
        'md5': '8c79e54be72078b26b89e0e111c0502b',
        'info_dict': {
            'id': 'JvYXJpMzE6pArfHWm5ARp5AiUmD-gibV',
            'ext': 'mp4',
            'title': 'Race highlights - Spain 2016',
        },
        'params': {
            # m3u8 download
            'skip_download': True,
        },
        'add_ie': ['Ooyala'],
    }, {
        'url': 'http://www.formula1.com/en/video/2016/5/Race_highlights_-_Spain_2016.html',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        display_id = self._match_id(url)
        webpage = self._download_webpage(url, display_id)
        ooyala_embed_code = self._search_regex(
            r'data-videoid="([^"]+)"', webpage, 'ooyala embed code')
        return self.url_result(
            'ooyala:%s' % ooyala_embed_code, 'Ooyala', ooyala_embed_code)
<commit_msg>[formula1] fix extraction(closes #29206)<commit_after># coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor

class Formula1IE(InfoExtractor):
    _VALID_URL = r'https?://(?:www\.)?formula1\.com/en/latest/video\.[^.]+\.(?P<id>\d+)\.html'
    _TEST = {
        'url': 'https://www.formula1.com/en/latest/video.race-highlights-spain-2016.6060988138001.html',
        'md5': 'be7d3a8c2f804eb2ab2aa5d941c359f8',
        'info_dict': {
            'id': '6060988138001',
            'ext': 'mp4',
            'title': 'Race highlights - Spain 2016',
            'timestamp': 1463332814,
            'upload_date': '20160515',
            'uploader_id': '6057949432001',
        },
        'add_ie': ['BrightcoveNew'],
    }
    BRIGHTCOVE_URL_TEMPLATE = 'http://players.brightcove.net/6057949432001/S1WMrhjlh_default/index.html?videoId=%s'

    def _real_extract(self, url):
        bc_id = self._match_id(url)
        return self.url_result(
            self.BRIGHTCOVE_URL_TEMPLATE % bc_id, 'BrightcoveNew', bc_id)
<|endoftext|>


<commit_before>__author__ = 'matt'
__date__ = '11/19/13'
__version__ = '0.1'
"""
POST GeoJSON or TopoJSON features from PostGIS to a Github Gist.

Example usage: python pgsql2gist.py --host localhost --user matt tilestache \
               "SELECT name, ST_AsGeoJSON(geom) AS geometry FROM neighborhoods LIMIT 5;"

Current SELECT Statement Requirements:
 - Geometry must be in EPSG:4326 WGS84 coordinate system
 - Geometry must be wrapped in ST_AsGeoJSON(), ST_AsTopoJSON()

usage: pgsql2gist.py [-f FILE] [-d DESCRIPTION] [-h HOST] [-p PORT]
                     [-P PASSWORD] [-u USER] [-g GEOM_COL] [-?]
                     database SELECT

positional arguments:
  database              PostGIS database name.
  SELECT                SELECT Statement. NOTE: Geometry must be GeoJSON
                        stored in WGS84.

optional arguments:
  -f FILE, --file FILE  Filename. NOTE: Must end in 'geosjon' or 'topojson'
                        extension. (default: upload.geojson)
  -d DESCRIPTION, --description DESCRIPTION
                        Description of upload (default: File uploaded using
                        pgsql2gist.)
  -h HOST, --host HOST  PostGIS database hostname. (default: localhost)
  -p PORT, --port PORT  PostGIS database port. (default: 5432)
  -P PASSWORD, --password PASSWORD
                        PostGIS user password. (default: None)
  -u USER, --user USER  PostGIS database user. (default: postgres)
  -g GEOM_COL, --geom-col GEOM_COL
                        Geometry Column. (default: geometry)
  -?, --help
"""

from psycopg2.extras import RealDictCursor
from psycopg2 import connect, Error
import argparse
import json
import time
import urllib2
import sys

class PostGISConnection(object):
    """
    Ripped from TileStache.
    Context manager for Postgres connections.
    See http://www.python.org/dev/peps/pep-0343/
    and http://effbot.org/zone/python-with-statement.htm
    """
    def __init__(self, **kwargs):
        self.kwargs = kwargs

    def __enter__(self):
        """
        Extract relevant connection details from command line arguments.
        Create database connection.
        """
        dbconnkeys = ['host','port','user','password','database']
        dbinfo = {}
        for key, value in self.kwargs.iteritems():
            if key in dbconnkeys and value:
                dbinfo[key] = value

        try:
            self.db = connect(**dbinfo).cursor(cursor_factory=RealDictCursor)
        except Error as e:
            print "PostGIS Connection Error: ", e.message
            print 'Terminating Script'
            raise SystemExit
        return self.db

    def __exit__(self, type, value, traceback):
        self.db.connection.close()

class GistAPI_Interface(object):
    """
    Provides functions for interacting with the github gist API.

    Required parameters:
    description (STRING) - A brief description of the gist contents
    file (STRING) - File name. Required to be in extension '.geojson' OR '.topojson'
    content (STRING) - Required to be Valid GeoJSON or TopoJSON
    """
    def __init__(self, file, description, content):
        self.content = content
        self.description = description
        self.file = file
        self.public = "false"
        self.response_content = None
        self.response_headers = None
        self.url = 'https://api.github.com/gists'

    def _build_request(self):
        """
        Given instance attributes, generate a properly formatted
        JSON request for the gist API.
        """
        data = {
            "description": self.description,
            "public": self.public,
            "files": {
                self.file: {
                    "content": self.content
                }
            }
        }
        return json.dumps(data)

    def _submit_request(self, json_data):
        """
        Given a JSON object properly formatted for the gist API
        Submit via http POST.
        """
        request = urllib2.Request(self.url, json_data)
        try:
            response = urllib2.urlopen(request)
        # Catch URL/HTTP errors, then abort script.
        except urllib2.HTTPError as e:
            print 'ERROR: Server returned HTTP Error Code:', e.code
            print 'Terminating Script'
            raise SystemExit
        except urllib2.URLError as e:
            print 'ERROR: Server Could Not Be Reached.'
            print 'REASON: ', e.reason
            print 'Terminating Script'
            raise SystemExit
        else:
            return response

    def submit(self):
        """
        Execute a series of internal class methods responsible for processing
        the request/response interaction between the client and the github API.

        This method updates the class instance's response_content attribute, which
        contains the gist url.
        """

        data_as_json = self._build_request()
        response = self._submit_request(data_as_json)
        self.response_headers = response.headers.dict

        # Populate instance attribute with JSON response from github.
        if response.code == 201:
            self.response_content = json.loads(response.read())
            return True
        else:
            print "Gist creation failed. Server returned HTTP code: ", response.code
            raise SystemExit

class CLI_Interface(object):
    """
    Basic command line interface using argparse.
    Based on pgsql2shp.
    """
    def __init__(self):
        """
        Create parser and execute setup method.
        """
        self.parser = argparse.ArgumentParser(add_help=False,
                                              formatter_class=argparse.ArgumentDefaultsHelpFormatter)
        # Build Parser
        self.setup()

    def setup(self):
        # Add positional arguments first
        self.parser.add_argument("database", help="PostGIS database name.")
        self.parser.add_argument("SELECT",
                            help="SELECT Statement. NOTE: Geometry must be GeoJSON stored in WGS84.")
        # Add optional arguments.
        self.parser.add_argument("-f", "--file",
                            help="Filename. NOTE: Must end in 'geosjon' or 'topojson' extension.",
                            default="upload.geojson")
        self.parser.add_argument("-d", "--description",
                                 help="Description of upload",
                                 default="File uploaded using pgsql2gist.")
        self.parser.add_argument("-h", "--host", help="PostGIS database hostname.", default="localhost")
        self.parser.add_argument("-p", "--port", help="PostGIS database port.", type=int, default=5432)
        self.parser.add_argument("-P", "--password", help="PostGIS user password.")
        self.parser.add_argument("-u", "--user", help="PostGIS database user.", default="postgres")
        self.parser.add_argument("-g", "--geom-col", help="Geometry Column.", default="geometry")
        # Add custom help flag
        self.parser.add_argument("-?", "--help", action="help")

    def get_args_dict(self):
        """
        Given an argparse parser object, wrap in a call to vars(), returning dictionary.
        This method also calls the input validation method.
        """
        args = self.parser.parse_args()
        args_dict = vars(args)
        if self._validate_args_dict(args_dict):
            return args_dict

    def _validate_args_dict(self, args_dict):
        """
        Internal method to perform validation tasks against the argparse arguments (as dict).
        Each validation function should return True or raise an error with an error message.
        Each raised error will be caught by a generic Error exception, and will raise a
        SystemExit error, terminating the script.
        """
        validation_functions = [self._validate_file_ext]
        for func in validation_functions:
            try:
                func(args_dict)
            except Error as e:
                print "Terminating Script"
                raise SystemExit
        return True

    def _validate_file_ext(self, args_dict):
        """
        Validate that file extensions are either geojson or topojson.
        Required for data to render in mapping interface.
        """
        valid_extensions = ['.geojson','topojson']
        ext_is_valid = False
        for ext in valid_extensions:
            if args_dict['file'].endswith(ext):
                ext_is_valid  = True
        if ext_is_valid:
            return True
        else:
            print 'ERROR: File extension does not end in .geojson or .topojson'
            raise ValueError

def make_geojson_feature(row, geom_column):
    """
    Given a database row via Psycopg's RealDictCursor
    return back a completed GeoJSON feature containing
    properties and geometries.
    """
    geometry = json.loads(row.pop(geom_column))
    feature = dict(type='Feature', geometry=geometry, properties=row)
    encoded = json.dumps(feature)
    return encoded

def make_geojson_feature_collection(features_str):
    """
    Given a list containing GeoJSON features, return as a
    GeoJSON Feature Collection.
    """
    features_json = [json.loads(feature) for feature in features_str]
    feature_collection = dict(type='FeatureCollection', features=features_json)
    encoded_feature_collection = json.dumps(feature_collection)
    return encoded_feature_collection

if __name__ == '__main__':
    # Setup CLI; Parse User Input
    arg_parse = CLI_Interface()
    args = arg_parse.get_args_dict()

    # Open DB Connection; Execute Query
    with PostGISConnection(**args) as db:
        try:
            db.execute(args["SELECT"])
        except Error as e:
            print "PostGIS SQL Execution Error: ", e.message
            print 'Terminating Script'
            raise SystemExit

        # Create list of geojson features
        features = [make_geojson_feature(row, args["geom_col"]) for row in db.fetchall()]

    # Setup and submit request to gist API
    gist_handler = GistAPI_Interface(args["file"],
                                     args["description"],
                                     make_geojson_feature_collection(features))
    gist_handler.submit()

    # Return rate limit information to user.
    if "x-ratelimit-limit" in gist_handler.response_headers:
        req_remaining = gist_handler.response_headers["x-ratelimit-remaining"]
        req_limit = gist_handler.response_headers["x-ratelimit-limit"]
        reset_time_epoch = gist_handler.response_headers["x-ratelimit-reset"]
        reset_time_human = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(reset_time_epoch)))
        print "%s requests remaining of %s total. Reset in: %s" % (req_remaining, req_limit, reset_time_human)
    # The presence of an html_url attribute indicates success.
    # MK TODO: Is there a better way of indicating success?
    if "html_url" in gist_handler.response_content:
        print "Gist URL: ", gist_handler.response_content["html_url"]
<commit_msg>added validation function for call to ST_As[Geo|Topo]JSON<commit_after>__author__ = 'matt'
__date__ = '11/19/13'
__version__ = '0.1'
"""
POST GeoJSON or TopoJSON features from PostGIS to a Github Gist.

Example usage: python pgsql2gist.py --host localhost --user matt tilestache \
               "SELECT name, ST_AsGeoJSON(geom) AS geometry FROM neighborhoods LIMIT 5;"

Current SELECT Statement Requirements:
 - Geometry must be in EPSG:4326 WGS84 coordinate system
 - Geometry must be wrapped in ST_AsGeoJSON(), ST_AsTopoJSON()

usage: pgsql2gist.py [-f FILE] [-d DESCRIPTION] [-h HOST] [-p PORT]
                     [-P PASSWORD] [-u USER] [-g GEOM_COL] [-?]
                     database SELECT

positional arguments:
  database              PostGIS database name.
  SELECT                SELECT Statement. NOTE: Geometry must be GeoJSON
                        stored in WGS84.

optional arguments:
  -f FILE, --file FILE  Filename. NOTE: Must end in 'geosjon' or 'topojson'
                        extension. (default: upload.geojson)
  -d DESCRIPTION, --description DESCRIPTION
                        Description of upload (default: File uploaded using
                        pgsql2gist.)
  -h HOST, --host HOST  PostGIS database hostname. (default: localhost)
  -p PORT, --port PORT  PostGIS database port. (default: 5432)
  -P PASSWORD, --password PASSWORD
                        PostGIS user password. (default: None)
  -u USER, --user USER  PostGIS database user. (default: postgres)
  -g GEOM_COL, --geom-col GEOM_COL
                        Geometry Column. (default: geometry)
  -?, --help
"""

from psycopg2.extras import RealDictCursor
from psycopg2 import connect, Error
import argparse
import json
import time
import urllib2
import sys

class PostGISConnection(object):
    """
    Ripped from TileStache.
    Context manager for Postgres connections.
    See http://www.python.org/dev/peps/pep-0343/
    and http://effbot.org/zone/python-with-statement.htm
    """
    def __init__(self, **kwargs):
        self.kwargs = kwargs

    def __enter__(self):
        """
        Extract relevant connection details from command line arguments.
        Create database connection.
        """
        dbconnkeys = ['host','port','user','password','database']
        dbinfo = {}
        for key, value in self.kwargs.iteritems():
            if key in dbconnkeys and value:
                dbinfo[key] = value

        try:
            self.db = connect(**dbinfo).cursor(cursor_factory=RealDictCursor)
        except Error as e:
            print "PostGIS Connection Error: ", e.message
            print 'Terminating Script'
            raise SystemExit
        return self.db

    def __exit__(self, type, value, traceback):
        self.db.connection.close()

class GistAPI_Interface(object):
    """
    Provides functions for interacting with the github gist API.

    Required parameters:
    description (STRING) - A brief description of the gist contents
    file (STRING) - File name. Required to be in extension '.geojson' OR '.topojson'
    content (STRING) - Required to be Valid GeoJSON or TopoJSON
    """
    def __init__(self, file, description, content):
        self.content = content
        self.description = description
        self.file = file
        self.public = "false"
        self.response_content = None
        self.response_headers = None
        self.url = 'https://api.github.com/gists'

    def _build_request(self):
        """
        Given instance attributes, generate a properly formatted
        JSON request for the gist API.
        """
        data = {
            "description": self.description,
            "public": self.public,
            "files": {
                self.file: {
                    "content": self.content
                }
            }
        }
        return json.dumps(data)

    def _submit_request(self, json_data):
        """
        Given a JSON object properly formatted for the gist API
        Submit via http POST.
        """
        request = urllib2.Request(self.url, json_data)
        try:
            response = urllib2.urlopen(request)
        # Catch URL/HTTP errors, then abort script.
        except urllib2.HTTPError as e:
            print 'ERROR: Server returned HTTP Error Code:', e.code
            print 'Terminating Script'
            raise SystemExit
        except urllib2.URLError as e:
            print 'ERROR: Server Could Not Be Reached.'
            print 'REASON: ', e.reason
            print 'Terminating Script'
            raise SystemExit
        else:
            return response

    def submit(self):
        """
        Execute a series of internal class methods responsible for processing
        the request/response interaction between the client and the github API.

        This method updates the class instance's response_content attribute, which
        contains the gist url.
        """

        data_as_json = self._build_request()
        response = self._submit_request(data_as_json)
        self.response_headers = response.headers.dict

        # Populate instance attribute with JSON response from github.
        if response.code == 201:
            self.response_content = json.loads(response.read())
            return True
        else:
            print "Gist creation failed. Server returned HTTP code: ", response.code
            raise SystemExit

class CLI_Interface(object):
    """
    Basic command line interface using argparse.
    Based on pgsql2shp.
    """
    def __init__(self):
        """
        Create parser and execute setup method.
        """
        self.parser = argparse.ArgumentParser(add_help=False,
                                              formatter_class=argparse.ArgumentDefaultsHelpFormatter)
        # Build Parser
        self.setup()

    def setup(self):
        # Add positional arguments first
        self.parser.add_argument("database", help="PostGIS database name.")
        self.parser.add_argument("SELECT",
                            help="SELECT Statement. NOTE: Geometry must be GeoJSON stored in WGS84.")
        # Add optional arguments.
        self.parser.add_argument("-f", "--file",
                            help="Filename. NOTE: Must end in 'geosjon' or 'topojson' extension.",
                            default="upload.geojson")
        self.parser.add_argument("-d", "--description",
                                 help="Description of upload",
                                 default="File uploaded using pgsql2gist.")
        self.parser.add_argument("-h", "--host", help="PostGIS database hostname.", default="localhost")
        self.parser.add_argument("-p", "--port", help="PostGIS database port.", type=int, default=5432)
        self.parser.add_argument("-P", "--password", help="PostGIS user password.")
        self.parser.add_argument("-u", "--user", help="PostGIS database user.", default="postgres")
        self.parser.add_argument("-g", "--geom-col", help="Geometry Column.", default="geometry")
        # Add custom help flag
        self.parser.add_argument("-?", "--help", action="help")

    def get_args_dict(self):
        """
        Given an argparse parser object, wrap in a call to vars(), returning dictionary.
        This method also calls the input validation method.
        """
        args = self.parser.parse_args()
        args_dict = vars(args)
        if self._validate_args_dict(args_dict):
            return args_dict

    def _validate_args_dict(self, args_dict):
        """
        Internal method to perform validation tasks against the argparse arguments (as dict).
        Each validation function should return True or raise an error with an error message.
        Each raised error will be caught by a generic Error exception, and will raise a
        SystemExit error, terminating the script.
        """
        validation_functions = [self._validate_file_ext, self._validate_topojson_geojson_call]
        for func in validation_functions:
            try:
                func(args_dict)
            except Exception, e:
                print "Terminating Script"
                raise SystemExit
        return True

    def _validate_file_ext(self, args_dict):
        """
        Validate that file extensions are either geojson or topojson.
        Required for data to render in mapping interface.
        """
        valid_extensions = ['.geojson','topojson']
        ext_is_valid = False
        for ext in valid_extensions:
            if args_dict['file'].endswith(ext):
                ext_is_valid  = True
        if ext_is_valid:
            return True
        else:
            print 'ERROR: File extension does not end in .geojson or .topojson'
            raise ValueError

    def _validate_topojson_geojson_call(self, args_dict):
        """
        Validate that a user has invoked a call to ST_AsGeoJSON() or ST_AsTopoJSON()
        in their SELECT statement.
        """
        valid_calls = ['st_asgeojson', 'st_astopojson']
        call_is_valid = False
        for call in valid_calls:
            if call.lower() in args_dict['SELECT'].lower():
                call_is_valid = True
        if call_is_valid:
            return True
        else:
            print 'ERROR: SELECT statement does not contain call to ST_AsGeoJSON() or ST_AsTopoJSON()'
            raise ValueError

def make_geojson_feature(row, geom_column):
    """
    Given a database row via Psycopg's RealDictCursor
    return back a completed GeoJSON feature containing
    properties and geometries.
    """
    geometry = json.loads(row.pop(geom_column))
    feature = dict(type='Feature', geometry=geometry, properties=row)
    encoded = json.dumps(feature)
    return encoded

def make_geojson_feature_collection(features_str):
    """
    Given a list containing GeoJSON features, return as a
    GeoJSON Feature Collection.
    """
    features_json = [json.loads(feature) for feature in features_str]
    feature_collection = dict(type='FeatureCollection', features=features_json)
    encoded_feature_collection = json.dumps(feature_collection)
    return encoded_feature_collection

if __name__ == '__main__':
    # Setup CLI; Parse User Input
    arg_parse = CLI_Interface()
    args = arg_parse.get_args_dict()

    # Open DB Connection; Execute Query
    with PostGISConnection(**args) as db:
        try:
            db.execute(args["SELECT"])
        except Error as e:
            print "PostGIS SQL Execution Error: ", e.message
            print 'Terminating Script'
            raise SystemExit

        # Create list of geojson features
        features = [make_geojson_feature(row, args["geom_col"]) for row in db.fetchall()]

    # Setup and submit request to gist API
    gist_handler = GistAPI_Interface(args["file"],
                                     args["description"],
                                     make_geojson_feature_collection(features))
    gist_handler.submit()

    # Return rate limit information to user.
    if "x-ratelimit-limit" in gist_handler.response_headers:
        req_remaining = gist_handler.response_headers["x-ratelimit-remaining"]
        req_limit = gist_handler.response_headers["x-ratelimit-limit"]
        reset_time_epoch = gist_handler.response_headers["x-ratelimit-reset"]
        reset_time_human = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(reset_time_epoch)))
        print "%s requests remaining of %s total. Reset in: %s" % (req_remaining, req_limit, reset_time_human)
    # The presence of an html_url attribute indicates success.
    # MK TODO: Is there a better way of indicating success?
    if "html_url" in gist_handler.response_content:
        print "Gist URL: ", gist_handler.response_content["html_url"]
<|endoftext|>


<commit_before># Copyright (C) 2013  Renato Lima - Akretion
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

{
    "name": "Brazilian Fiscal",
    "summary": "Brazilian fiscal core module.",
    "category": "Localisation",
    "license": "AGPL-3",
    "author": "Akretion, Odoo Community Association (OCA)",
    "maintainers": ["renatonlima"],
    "website": "http://github.com/OCA/l10n-brazil",
    "version": "12.0.5.5.1",
    "depends": [
        "uom",
        "decimal_precision",
        "product",
        "l10n_br_base",
    ],
    "data": [
        # security
        "security/fiscal_security.xml",
        "security/ir.model.access.csv",

        # Data
        # Some data is being loaded via post_init_hook in hook file
        "data/l10n_br_fiscal_email_template.xml",
        "data/l10n_br_fiscal_data.xml",
        "data/uom_data.xml",
        "data/product_data.xml",
        "data/l10n_br_fiscal.tax.group.csv",
        "data/l10n_br_fiscal.icms.relief.csv",
        "data/l10n_br_fiscal.document.type.csv",
        "data/l10n_br_fiscal.product.genre.csv",
        "data/l10n_br_fiscal.cst.csv",
        "data/l10n_br_fiscal.tax.csv",
        "data/l10n_br_fiscal.tax.pis.cofins.csv",
        "data/partner_profile_data.xml",
        "data/l10n_br_fiscal_server_action.xml",
        "data/ir_cron.xml",
        "data/l10n_br_fiscal_comment_data.xml",

        # Views
        "views/cnae_view.xml",
        "views/cfop_view.xml",
        "views/comment_view.xml",
        "views/cst_view.xml",
        "views/tax_group_view.xml",
        "views/tax_view.xml",
        "views/tax_definition_view.xml",
        "views/icms_regulation_view.xml",
        'views/icms_relief_view.xml',
        "views/tax_pis_cofins_view.xml",
        "views/tax_pis_cofins_base_view.xml",
        "views/tax_pis_cofins_credit_view.xml",
        "views/tax_ipi_control_seal_view.xml",
        "views/tax_ipi_guideline_view.xml",
        "views/tax_ipi_guideline_class_view.xml",
        "views/ncm_view.xml",
        "views/nbm_view.xml",
        "views/nbs_view.xml",
        "views/service_type_view.xml",
        "views/cest_view.xml",
        "views/product_genre_view.xml",
        "views/document_type_view.xml",
        "views/document_serie_view.xml",
        "views/document_email_view.xml",
        "views/certificate_view.xml",
        "views/simplified_tax_view.xml",
        "views/simplified_tax_range_view.xml",
        "views/operation_view.xml",
        "views/operation_line_view.xml",
        "views/product_template_view.xml",
        "views/product_product_view.xml",
        "views/tax_estimate_view.xml",
        "views/partner_profile_view.xml",
        "views/res_partner_view.xml",
        "views/res_company_view.xml",
        "views/document_view.xml",
        "views/document_related_view.xml",
        "views/document_line_view.xml",
        "views/document_fiscal_mixin_view.xml",
        "views/document_fiscal_line_mixin_view.xml",
        "views/res_config_settings_view.xml",
        "views/subsequent_operation_view.xml",
        "views/subsequent_document_view.xml",
        "views/uom_uom.xml",
        "views/closing.xml",
        "views/document_invalidate_number.xml",
        "views/document_cancel.xml",
        "views/document_correction.xml",
        "views/city_taxation_code.xml",
        'views/mdfe/mdfe_views.xml',
        'views/dfe/dfe_views.xml',
        "views/operation_dashboard_view.xml",
        "views/document_event_view.xml",

        # Wizards
        "wizards/wizard_document_cancel_view.xml",
        "wizards/wizard_document_correction_view.xml",
        "wizards/wizard_document_invalidate_view.xml",
        "wizards/wizard_document_status_view.xml",

        # Actions
        "views/l10n_br_fiscal_action.xml",

        # Menus
        "views/l10n_br_fiscal_menu.xml",
    ],
    "demo": [
        # Some demo data is being loaded via post_init_hook in hook file
    ],
    "post_init_hook": "post_init_hook",
    "installable": True,
    "application": True,
    "auto_install": False,
    "external_dependencies": {"python": [
        "erpbrasil.base",
        "erpbrasil.assinatura",
    ]},
}
<commit_msg>l10n_br_fiscal 12.0.5.6.0<commit_after># Copyright (C) 2013  Renato Lima - Akretion
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

{
    "name": "Brazilian Fiscal",
    "summary": "Brazilian fiscal core module.",
    "category": "Localisation",
    "license": "AGPL-3",
    "author": "Akretion, Odoo Community Association (OCA)",
    "maintainers": ["renatonlima"],
    "website": "http://github.com/OCA/l10n-brazil",
    "version": "12.0.5.6.0",
    "depends": [
        "uom",
        "decimal_precision",
        "product",
        "l10n_br_base",
    ],
    "data": [
        # security
        "security/fiscal_security.xml",
        "security/ir.model.access.csv",

        # Data
        # Some data is being loaded via post_init_hook in hook file
        "data/l10n_br_fiscal_email_template.xml",
        "data/l10n_br_fiscal_data.xml",
        "data/uom_data.xml",
        "data/product_data.xml",
        "data/l10n_br_fiscal.tax.group.csv",
        "data/l10n_br_fiscal.icms.relief.csv",
        "data/l10n_br_fiscal.document.type.csv",
        "data/l10n_br_fiscal.product.genre.csv",
        "data/l10n_br_fiscal.cst.csv",
        "data/l10n_br_fiscal.tax.csv",
        "data/l10n_br_fiscal.tax.pis.cofins.csv",
        "data/partner_profile_data.xml",
        "data/l10n_br_fiscal_server_action.xml",
        "data/ir_cron.xml",
        "data/l10n_br_fiscal_comment_data.xml",

        # Views
        "views/cnae_view.xml",
        "views/cfop_view.xml",
        "views/comment_view.xml",
        "views/cst_view.xml",
        "views/tax_group_view.xml",
        "views/tax_view.xml",
        "views/tax_definition_view.xml",
        "views/icms_regulation_view.xml",
        'views/icms_relief_view.xml',
        "views/tax_pis_cofins_view.xml",
        "views/tax_pis_cofins_base_view.xml",
        "views/tax_pis_cofins_credit_view.xml",
        "views/tax_ipi_control_seal_view.xml",
        "views/tax_ipi_guideline_view.xml",
        "views/tax_ipi_guideline_class_view.xml",
        "views/ncm_view.xml",
        "views/nbm_view.xml",
        "views/nbs_view.xml",
        "views/service_type_view.xml",
        "views/cest_view.xml",
        "views/product_genre_view.xml",
        "views/document_type_view.xml",
        "views/document_serie_view.xml",
        "views/document_email_view.xml",
        "views/certificate_view.xml",
        "views/simplified_tax_view.xml",
        "views/simplified_tax_range_view.xml",
        "views/operation_view.xml",
        "views/operation_line_view.xml",
        "views/product_template_view.xml",
        "views/product_product_view.xml",
        "views/tax_estimate_view.xml",
        "views/partner_profile_view.xml",
        "views/res_partner_view.xml",
        "views/res_company_view.xml",
        "views/document_view.xml",
        "views/document_related_view.xml",
        "views/document_line_view.xml",
        "views/document_fiscal_mixin_view.xml",
        "views/document_fiscal_line_mixin_view.xml",
        "views/res_config_settings_view.xml",
        "views/subsequent_operation_view.xml",
        "views/subsequent_document_view.xml",
        "views/uom_uom.xml",
        "views/closing.xml",
        "views/document_invalidate_number.xml",
        "views/document_cancel.xml",
        "views/document_correction.xml",
        "views/city_taxation_code.xml",
        'views/mdfe/mdfe_views.xml',
        'views/dfe/dfe_views.xml',
        "views/operation_dashboard_view.xml",
        "views/document_event_view.xml",

        # Wizards
        "wizards/wizard_document_cancel_view.xml",
        "wizards/wizard_document_correction_view.xml",
        "wizards/wizard_document_invalidate_view.xml",
        "wizards/wizard_document_status_view.xml",

        # Actions
        "views/l10n_br_fiscal_action.xml",

        # Menus
        "views/l10n_br_fiscal_menu.xml",
    ],
    "demo": [
        # Some demo data is being loaded via post_init_hook in hook file
    ],
    "post_init_hook": "post_init_hook",
    "installable": True,
    "application": True,
    "auto_install": False,
    "external_dependencies": {"python": [
        "erpbrasil.base",
        "erpbrasil.assinatura",
    ]},
}
<|endoftext|>


<commit_before># Copyright (C) 2013  Renato Lima - Akretion
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

{
    "name": "Módulo fiscal brasileiro",
    "summary": "Brazilian fiscal core module.",
    "category": "Localisation",
    "license": "AGPL-3",
    "author": "Akretion, Odoo Community Association (OCA)",
    "maintainers": ["renatonlima"],
    "website": "https://github.com/OCA/l10n-brazil",
    "development_status": "Production/Stable",
    "version": "14.0.4.12.0",
    "depends": [
        "uom",
        "product",
        "l10n_br_base",
    ],
    "data": [
        # security
        "security/fiscal_security.xml",
        "security/ir.model.access.csv",
        # Data
        # Some data is being loaded via post_init_hook in hook file
        "data/l10n_br_fiscal_email_template.xml",
        "data/l10n_br_fiscal_data.xml",
        "data/uom_data.xml",
        "data/product_data.xml",
        "data/partner_profile_data.xml",
        "data/res_partner_data.xml",
        "data/l10n_br_fiscal.tax.group.csv",
        "data/l10n_br_fiscal.icms.relief.csv",
        "data/l10n_br_fiscal.document.type.csv",
        "data/l10n_br_fiscal.product.genre.csv",
        "data/l10n_br_fiscal.cst.csv",
        "data/l10n_br_fiscal.tax.csv",
        "data/l10n_br_fiscal.tax.pis.cofins.csv",
        "data/l10n_br_fiscal_server_action.xml",
        "data/ir_cron.xml",
        "data/l10n_br_fiscal_comment_data.xml",
        # Views
        "views/cnae_view.xml",
        "views/cfop_view.xml",
        "views/comment_view.xml",
        "views/cst_view.xml",
        "views/tax_group_view.xml",
        "views/tax_view.xml",
        "views/tax_definition_view.xml",
        "views/icms_regulation_view.xml",
        "views/icms_relief_view.xml",
        "views/tax_pis_cofins_view.xml",
        "views/tax_pis_cofins_base_view.xml",
        "views/tax_pis_cofins_credit_view.xml",
        "views/tax_ipi_control_seal_view.xml",
        "views/tax_ipi_guideline_view.xml",
        "views/tax_ipi_guideline_class_view.xml",
        "views/ncm_view.xml",
        "views/nbm_view.xml",
        "views/nbs_view.xml",
        "views/service_type_view.xml",
        "views/cest_view.xml",
        "views/product_genre_view.xml",
        "views/document_type_view.xml",
        "views/document_serie_view.xml",
        "views/document_email_view.xml",
        "views/certificate_view.xml",
        "views/simplified_tax_view.xml",
        "views/simplified_tax_range_view.xml",
        "views/operation_view.xml",
        "views/operation_line_view.xml",
        "views/product_template_view.xml",
        "views/product_product_view.xml",
        "views/tax_estimate_view.xml",
        "views/partner_profile_view.xml",
        "views/res_partner_view.xml",
        "views/res_company_view.xml",
        "views/document_view.xml",
        "views/document_related_view.xml",
        "views/document_line_view.xml",
        "views/document_fiscal_line_mixin_view.xml",
        "views/res_config_settings_view.xml",
        "views/subsequent_operation_view.xml",
        "views/subsequent_document_view.xml",
        "views/uom_uom.xml",
        "views/closing.xml",
        "views/invalidate_number_view.xml",
        "views/city_taxation_code.xml",
        #        "views/mdfe/mdfe_views.xml",
        #        "views/dfe/dfe_views.xml",
        "views/operation_dashboard_view.xml",
        "views/document_event_view.xml",
        # Wizards
        "wizards/document_cancel_wizard.xml",
        "wizards/document_correction_wizard.xml",
        "wizards/document_status_wizard.xml",
        "wizards/invalidate_number_wizard.xml",
        # Actions
        "views/l10n_br_fiscal_action.xml",
        # Menus
        "views/l10n_br_fiscal_menu.xml",
    ],
    "demo": [
        # Some demo data is being loaded via post_init_hook in hook file
    ],
    "post_init_hook": "post_init_hook",
    "installable": True,
    "application": True,
    "auto_install": False,
    "external_dependencies": {
        "python": [
            "erpbrasil.base",
            "erpbrasil.assinatura-nopyopenssl",
        ]
    },
}
<commit_msg>l10n_br_fiscal 14.0.4.13.0<commit_after># Copyright (C) 2013  Renato Lima - Akretion
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

{
    "name": "Módulo fiscal brasileiro",
    "summary": "Brazilian fiscal core module.",
    "category": "Localisation",
    "license": "AGPL-3",
    "author": "Akretion, Odoo Community Association (OCA)",
    "maintainers": ["renatonlima"],
    "website": "https://github.com/OCA/l10n-brazil",
    "development_status": "Production/Stable",
    "version": "14.0.4.13.0",
    "depends": [
        "uom",
        "product",
        "l10n_br_base",
    ],
    "data": [
        # security
        "security/fiscal_security.xml",
        "security/ir.model.access.csv",
        # Data
        # Some data is being loaded via post_init_hook in hook file
        "data/l10n_br_fiscal_email_template.xml",
        "data/l10n_br_fiscal_data.xml",
        "data/uom_data.xml",
        "data/product_data.xml",
        "data/partner_profile_data.xml",
        "data/res_partner_data.xml",
        "data/l10n_br_fiscal.tax.group.csv",
        "data/l10n_br_fiscal.icms.relief.csv",
        "data/l10n_br_fiscal.document.type.csv",
        "data/l10n_br_fiscal.product.genre.csv",
        "data/l10n_br_fiscal.cst.csv",
        "data/l10n_br_fiscal.tax.csv",
        "data/l10n_br_fiscal.tax.pis.cofins.csv",
        "data/l10n_br_fiscal_server_action.xml",
        "data/ir_cron.xml",
        "data/l10n_br_fiscal_comment_data.xml",
        # Views
        "views/cnae_view.xml",
        "views/cfop_view.xml",
        "views/comment_view.xml",
        "views/cst_view.xml",
        "views/tax_group_view.xml",
        "views/tax_view.xml",
        "views/tax_definition_view.xml",
        "views/icms_regulation_view.xml",
        "views/icms_relief_view.xml",
        "views/tax_pis_cofins_view.xml",
        "views/tax_pis_cofins_base_view.xml",
        "views/tax_pis_cofins_credit_view.xml",
        "views/tax_ipi_control_seal_view.xml",
        "views/tax_ipi_guideline_view.xml",
        "views/tax_ipi_guideline_class_view.xml",
        "views/ncm_view.xml",
        "views/nbm_view.xml",
        "views/nbs_view.xml",
        "views/service_type_view.xml",
        "views/cest_view.xml",
        "views/product_genre_view.xml",
        "views/document_type_view.xml",
        "views/document_serie_view.xml",
        "views/document_email_view.xml",
        "views/certificate_view.xml",
        "views/simplified_tax_view.xml",
        "views/simplified_tax_range_view.xml",
        "views/operation_view.xml",
        "views/operation_line_view.xml",
        "views/product_template_view.xml",
        "views/product_product_view.xml",
        "views/tax_estimate_view.xml",
        "views/partner_profile_view.xml",
        "views/res_partner_view.xml",
        "views/res_company_view.xml",
        "views/document_view.xml",
        "views/document_related_view.xml",
        "views/document_line_view.xml",
        "views/document_fiscal_line_mixin_view.xml",
        "views/res_config_settings_view.xml",
        "views/subsequent_operation_view.xml",
        "views/subsequent_document_view.xml",
        "views/uom_uom.xml",
        "views/closing.xml",
        "views/invalidate_number_view.xml",
        "views/city_taxation_code.xml",
        #        "views/mdfe/mdfe_views.xml",
        #        "views/dfe/dfe_views.xml",
        "views/operation_dashboard_view.xml",
        "views/document_event_view.xml",
        # Wizards
        "wizards/document_cancel_wizard.xml",
        "wizards/document_correction_wizard.xml",
        "wizards/document_status_wizard.xml",
        "wizards/invalidate_number_wizard.xml",
        # Actions
        "views/l10n_br_fiscal_action.xml",
        # Menus
        "views/l10n_br_fiscal_menu.xml",
    ],
    "demo": [
        # Some demo data is being loaded via post_init_hook in hook file
    ],
    "post_init_hook": "post_init_hook",
    "installable": True,
    "application": True,
    "auto_install": False,
    "external_dependencies": {
        "python": [
            "erpbrasil.base",
            "erpbrasil.assinatura-nopyopenssl",
        ]
    },
}
<|endoftext|>