<commit_before>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import copy

from robot import utils
from robot.errors import FrameworkError, DataError
from robot.libraries import STDLIB_NAMES
from robot.variables import GLOBAL_VARIABLES
from robot.common import UserErrorHandler
from robot.output import LOGGER
import robot

from importer import Importer
from runkwregister import RUN_KW_REGISTER

IMPORTER = Importer()

class Namespace:
    """A database for keywords and variables.

    A new instance of this class is created for each test suite.
    """

    def __init__(self, suite, parent):
        if suite is not None:
            LOGGER.info("Initializing namespace for test suite '%s'" % suite.longname)
        self.variables = _VariableScopes(suite, parent)
        self.suite = suite
        self.test = None
        self.uk_handlers = []
        self.library_search_order = []
        self._testlibs = {}
        self._userlibs = []
        self._imported_resource_files = []
        self._imported_variable_files = []
        # suite is None only when used internally by copy
        if suite is not None:
            self.import_library('BuiltIn')
            self.import_library('Reserved')
            if suite.source is not None:
                self._handle_imports(suite.imports)
            robot.running.NAMESPACES.start_suite(self)

    def copy(self):
        # Namespace is copied by ParallelKeyword
        ns = Namespace(None, None)
        ns.variables = self.variables.copy_all()
        ns.suite = self.suite
        ns.test = self.test
        ns.uk_handlers = self.uk_handlers[:]
        ns.library_search_order = self.library_search_order[:]
        ns._testlibs = self._testlibs
        ns._userlibs = self._userlibs
        return ns

    def _handle_imports(self, import_settings):
        for item in import_settings:
            try:
                item.replace_variables(self.variables.current)
                if item.name == 'Library':
                    self.import_library(item.value[0], item.value[1:])
                elif item.name == 'Resource':
                    self._import_resource(item.value[0])
                elif item.name == 'Variables':
                    self.import_variables(item.value[0], item.value[1:])
                else:
                    raise FrameworkError("Invalid import setting: %s" % item)
            except:
                item.report_invalid_syntax()

    def _import_resource(self, path):
        if path not in self._imported_resource_files:
            self._imported_resource_files.append(path)
            resource = IMPORTER.import_resource(path)
            self.variables.set_from_variable_table(resource.variables)
            self._userlibs.append(resource.user_keywords)
            self._handle_imports(resource.imports)
        else:
            LOGGER.warn("Resource file '%s' already imported by suite '%s'"
                        % (path, self.suite.longname))

    def import_variables(self, path, args, overwrite=False):
        if (path,args) not in self._imported_variable_files:
            self._imported_variable_files.append((path,args))
            self.variables.set_from_file(path, args, overwrite)
        else:
            msg = "Variable file '%s'" % path
            if args:
                msg += " with arguments %s" % (utils.seq2str2(args))
            LOGGER.warn("%s already imported by suite '%s'"
                        % (msg, self.suite.longname))

    def import_library(self, name, args=None):
        lib = IMPORTER.import_library(name, args)
        if self._testlibs.has_key(lib.name):
            LOGGER.warn("Test library '%s' already imported by suite '%s'"
                        % (lib.name, self.suite.longname))
            return
        self._testlibs[lib.name] = lib
        lib.start_suite()
        if self.test:
            lib.start_test()
        self._import_deprecated_standard_libs(lib.name)

    def _import_deprecated_standard_libs(self, name):
        if name in ['BuiltIn', 'OperatingSystem']:
            self.import_library('Deprecated' + name)

    def start_test(self, test):
        self.variables.start_test(test)
        self.test = test
        for lib in self._testlibs.values():
            lib.start_test()

    def end_test(self):
        self.test = None
        self.variables.end_test()
        self.uk_handlers = []
        for lib in self._testlibs.values():
            lib.end_test()

    def end_suite(self):
        self.suite = None
        self.variables.end_suite()
        for lib in self._testlibs.values():
            lib.end_suite()
        robot.running.NAMESPACES.end_suite()

    def start_user_keyword(self, handler):
        self.variables.start_uk(handler)
        self.uk_handlers.append(handler)

    def end_user_keyword(self):
        self.variables.end_uk()
        self.uk_handlers.pop()

    def get_library_instance(self, libname):
        return self._testlibs[libname].get_instance()

    def get_handler(self, name):
        try:
            handler = self._get_handler(name)
            if handler is None:
                raise DataError("No keyword with name '%s' found." % name)
        except:
            error = utils.get_error_message()
            handler = UserErrorHandler(name, error)
        try:
            handler.replace_variables(self.variables)
        except AttributeError:  # only applicable for UserHandlers
            pass
        return handler

    def _get_handler(self, name):
        handler = None
        if '.' in name:
            handler = self._get_explicit_handler(name)
        if not handler:
            handler = self._get_implicit_handler(name)
        if not handler:
            handler = self._get_bdd_style_handler(name)
        return handler

    def _get_bdd_style_handler(self, name):
        for prefix in ['given ', 'when ', 'then ', 'and ']:
            if name.lower().startswith(prefix):
                handler = self._get_handler(name[len(prefix):])
                if handler:
                    handler = copy.copy(handler)
                    handler.name = name
                return handler
        return None

    def _get_implicit_handler(self, name):
        for method in [ self._get_handler_from_test_case_file_user_keywords,
                        self._get_handler_from_resource_file_user_keywords,
                        self._get_handler_from_library_keywords ]:
            handler = method(name)
            if handler:
                return handler
        return None

    def _get_handler_from_test_case_file_user_keywords(self, name):
        if self.suite.user_keywords.has_handler(name):
            return self.suite.user_keywords.get_handler(name)

    def _get_handler_from_resource_file_user_keywords(self, name):
        found = [ lib.get_handler(name)
                  for lib in self._userlibs if lib.has_handler(name) ]
        if not found:
            return None
        if len(found) == 1:
            return found[0]
        self._raise_multiple_keywords_found(name, found)

    def _get_handler_from_library_keywords(self, name):
        found = [ lib.get_handler(name)
                  for lib in self._testlibs.values() if lib.has_handler(name) ]
        if not found:
            return None
        if len(found) > 1:
            found = self._get_handler_based_on_library_search_order(found)
        if len(found) == 2:
            found = self._filter_stdlib_handler(found[0], found[1])
        if len(found) == 1:
            return found[0]
        self._raise_multiple_keywords_found(name, found)

    def _get_handler_based_on_library_search_order(self, handlers):
        for libname in self.library_search_order:
            for handler in handlers:
                if handler.library.name == libname:
                    return [handler]
        return handlers

    def _filter_stdlib_handler(self, hand1, hand2):
        if hand1.library.orig_name in STDLIB_NAMES:
            std_hand, ext_hand = hand1, hand2
        elif hand2.library.orig_name in STDLIB_NAMES:
            std_hand, ext_hand = hand2, hand1
        else:
            return [hand1, hand2]
        if not RUN_KW_REGISTER.is_run_keyword(ext_hand):
            LOGGER.warn(
                "Keyword '%s' found both from a user created test library "
                "'%s' and Robot Framework standard library '%s'. The user "
                "created keyword is used. To select explicitly, and to get "
                "rid of this warning, use full format i.e. either '%s' or '%s'."
                % (std_hand.name,
                   ext_hand.library.orig_name, std_hand.library.orig_name,
                   ext_hand.longname, std_hand.longname))
        return [ext_hand]

    def _get_explicit_handler(self, name):
        libname, kwname = self._split_keyword_name(name)
        # 1) Find matching lib(s)
        libs = [ lib for lib in self._userlibs + self._testlibs.values()
                 if utils.eq(lib.name, libname) ]
        if not libs:
            return None
        # 2) Find matching kw from found libs
        found = [ lib.get_handler(kwname)
                  for lib in libs if lib.has_handler(kwname) ]
        if len(found) > 1:
            self._raise_multiple_keywords_found(name, found, implicit=False)
        return found and found[0] or None

    def _split_keyword_name(self, name):
        parts = name.split('.')
        kwname = parts.pop()       # pop last part
        libname = '.'.join(parts)  # and rejoin rest
        return libname, kwname

    def _raise_multiple_keywords_found(self, name, found, implicit=True):
        error = "Multiple keywords with name '%s' found.\n" % name
        if implicit:
            error += "Give the full name of the keyword you want to use.\n"
        names = [ handler.longname for handler in found ]
        names.sort()
        error += "Found: %s" % utils.seq2str(names)
        raise DataError(error)

class _VariableScopes:

    def __init__(self, suite, parent):
        # suite and parent are None only when used by copy_all
        if suite is not None:
            suite.variables.update(GLOBAL_VARIABLES)
            self._suite = self.current = suite.variables
        self._parents = []
        if parent is not None:
            self._parents.append(parent.namespace.variables.current)
            self._parents.extend(parent.namespace.variables._parents)
        self._test = None
        self._uk_handlers = []

    def copy_all(self):
        vs = _VariableScopes(None, None)
        vs._suite = self._suite
        vs._test = self._test
        vs._uk_handlers = self._uk_handlers[:]
        vs._parents = self._parents[:]
        vs.current = self.current
        return vs

    def replace_list(self, items):
        return self.current.replace_list(items)

    def replace_scalar(self, items):
        return self.current.replace_scalar(items)

    def replace_string(self, string):
        return self.current.replace_string(string)

    def set_from_file(self, path, args, overwrite=False):
        variables = self._suite.set_from_file(path, args, overwrite)
        if self._test is not None:
            self._test._set_from_file(variables, overwrite=True)
        for varz in self._uk_handlers:
            varz._set_from_file(variables, overwrite=True)
        if self._uk_handlers:
            self.current._set_from_file(variables, overwrite=True)

    def set_from_variable_table(self, rawvariables):
        self._suite.set_from_variable_table(rawvariables)

    def replace_meta(self, name, item, errors):
        error = None
        for varz in [self.current] + self._parents:
            try:
                if name in ['Setup', 'Teardown']:
                    return varz.replace_list(item[:1]) + item[1:]
                if name == 'Documentation':
                    return varz.replace_string(item, ignore_errors=True)
                if utils.is_list(item):
                    return varz.replace_list(item)
                return varz.replace_string(item)
            except DataError, error:
                pass
        errors.append("Replacing variables from metadata '%s' failed: %s"
                      % (name, error))
        return utils.unescape(item)

    def __getitem__(self, name):
        return self.current[name]

    def __setitem__(self, name, value):
        self.current[name] = value

    def end_suite(self):
        self._suite = self._test = self.current = None

    def start_test(self, test):
        self._test = self.current = self._suite.copy()

    def end_test(self):
        self.current = self._suite

    def start_uk(self, handler):
        self._uk_handlers.append(self.current)
        self.current = self.current.copy()

    def end_uk(self):
        self.current = self._uk_handlers.pop()

    def set_global(self, name, value):
        GLOBAL_VARIABLES[name] = value
        for ns in robot.running.NAMESPACES:
            ns.variables.set_suite(name, value)

    def set_suite(self, name, value):
        self._suite[name] = value
        self.set_test(name, value, False)

    def set_test(self, name, value, fail_if_no_test=True):
        if self._test is not None:
            self._test[name] = value
        elif fail_if_no_test:
            raise DataError("Cannot set test variable when no test is started")
        for varz in self._uk_handlers:
            varz[name] = value
        self.current[name] = value # latest uk handler is not in self._uk_handlers

    def keys(self):
        return self.current.keys()

    def has_key(self, key):
        return self.current.has_key(key)
<commit_msg>Write message about importing libraries and resource/variable files into syslog using INFO level instead of WARN. Issue 407.<commit_after>#  Copyright 2008-2009 Nokia Siemens Networks Oyj
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import copy

from robot import utils
from robot.errors import FrameworkError, DataError
from robot.libraries import STDLIB_NAMES
from robot.variables import GLOBAL_VARIABLES
from robot.common import UserErrorHandler
from robot.output import LOGGER
import robot

from importer import Importer
from runkwregister import RUN_KW_REGISTER

IMPORTER = Importer()

class Namespace:
    """A database for keywords and variables.

    A new instance of this class is created for each test suite.
    """

    def __init__(self, suite, parent):
        if suite is not None:
            LOGGER.info("Initializing namespace for test suite '%s'" % suite.longname)
        self.variables = _VariableScopes(suite, parent)
        self.suite = suite
        self.test = None
        self.uk_handlers = []
        self.library_search_order = []
        self._testlibs = {}
        self._userlibs = []
        self._imported_resource_files = []
        self._imported_variable_files = []
        # suite is None only when used internally by copy
        if suite is not None:
            self.import_library('BuiltIn')
            self.import_library('Reserved')
            if suite.source is not None:
                self._handle_imports(suite.imports)
            robot.running.NAMESPACES.start_suite(self)

    def copy(self):
        # Namespace is copied by ParallelKeyword
        ns = Namespace(None, None)
        ns.variables = self.variables.copy_all()
        ns.suite = self.suite
        ns.test = self.test
        ns.uk_handlers = self.uk_handlers[:]
        ns.library_search_order = self.library_search_order[:]
        ns._testlibs = self._testlibs
        ns._userlibs = self._userlibs
        return ns

    def _handle_imports(self, import_settings):
        for item in import_settings:
            try:
                item.replace_variables(self.variables.current)
                if item.name == 'Library':
                    self.import_library(item.value[0], item.value[1:])
                elif item.name == 'Resource':
                    self._import_resource(item.value[0])
                elif item.name == 'Variables':
                    self.import_variables(item.value[0], item.value[1:])
                else:
                    raise FrameworkError("Invalid import setting: %s" % item)
            except:
                item.report_invalid_syntax()

    def _import_resource(self, path):
        if path not in self._imported_resource_files:
            self._imported_resource_files.append(path)
            resource = IMPORTER.import_resource(path)
            self.variables.set_from_variable_table(resource.variables)
            self._userlibs.append(resource.user_keywords)
            self._handle_imports(resource.imports)
        else:
            LOGGER.info("Resource file '%s' already imported by suite '%s'"
                        % (path, self.suite.longname))

    def import_variables(self, path, args, overwrite=False):
        if (path,args) not in self._imported_variable_files:
            self._imported_variable_files.append((path,args))
            self.variables.set_from_file(path, args, overwrite)
        else:
            msg = "Variable file '%s'" % path
            if args:
                msg += " with arguments %s" % utils.seq2str2(args)
            LOGGER.info("%s already imported by suite '%s'"
                        % (msg, self.suite.longname))

    def import_library(self, name, args=None):
        lib = IMPORTER.import_library(name, args)
        if self._testlibs.has_key(lib.name):
            LOGGER.info("Test library '%s' already imported by suite '%s'"
                        % (lib.name, self.suite.longname))
            return
        self._testlibs[lib.name] = lib
        lib.start_suite()
        if self.test:
            lib.start_test()
        self._import_deprecated_standard_libs(lib.name)

    def _import_deprecated_standard_libs(self, name):
        if name in ['BuiltIn', 'OperatingSystem']:
            self.import_library('Deprecated' + name)

    def start_test(self, test):
        self.variables.start_test(test)
        self.test = test
        for lib in self._testlibs.values():
            lib.start_test()

    def end_test(self):
        self.test = None
        self.variables.end_test()
        self.uk_handlers = []
        for lib in self._testlibs.values():
            lib.end_test()

    def end_suite(self):
        self.suite = None
        self.variables.end_suite()
        for lib in self._testlibs.values():
            lib.end_suite()
        robot.running.NAMESPACES.end_suite()

    def start_user_keyword(self, handler):
        self.variables.start_uk(handler)
        self.uk_handlers.append(handler)

    def end_user_keyword(self):
        self.variables.end_uk()
        self.uk_handlers.pop()

    def get_library_instance(self, libname):
        return self._testlibs[libname].get_instance()

    def get_handler(self, name):
        try:
            handler = self._get_handler(name)
            if handler is None:
                raise DataError("No keyword with name '%s' found." % name)
        except:
            error = utils.get_error_message()
            handler = UserErrorHandler(name, error)
        try:
            handler.replace_variables(self.variables)
        except AttributeError:  # only applicable for UserHandlers
            pass
        return handler

    def _get_handler(self, name):
        handler = None
        if '.' in name:
            handler = self._get_explicit_handler(name)
        if not handler:
            handler = self._get_implicit_handler(name)
        if not handler:
            handler = self._get_bdd_style_handler(name)
        return handler

    def _get_bdd_style_handler(self, name):
        for prefix in ['given ', 'when ', 'then ', 'and ']:
            if name.lower().startswith(prefix):
                handler = self._get_handler(name[len(prefix):])
                if handler:
                    handler = copy.copy(handler)
                    handler.name = name
                return handler
        return None

    def _get_implicit_handler(self, name):
        for method in [ self._get_handler_from_test_case_file_user_keywords,
                        self._get_handler_from_resource_file_user_keywords,
                        self._get_handler_from_library_keywords ]:
            handler = method(name)
            if handler:
                return handler
        return None

    def _get_handler_from_test_case_file_user_keywords(self, name):
        if self.suite.user_keywords.has_handler(name):
            return self.suite.user_keywords.get_handler(name)

    def _get_handler_from_resource_file_user_keywords(self, name):
        found = [ lib.get_handler(name)
                  for lib in self._userlibs if lib.has_handler(name) ]
        if not found:
            return None
        if len(found) == 1:
            return found[0]
        self._raise_multiple_keywords_found(name, found)

    def _get_handler_from_library_keywords(self, name):
        found = [ lib.get_handler(name)
                  for lib in self._testlibs.values() if lib.has_handler(name) ]
        if not found:
            return None
        if len(found) > 1:
            found = self._get_handler_based_on_library_search_order(found)
        if len(found) == 2:
            found = self._filter_stdlib_handler(found[0], found[1])
        if len(found) == 1:
            return found[0]
        self._raise_multiple_keywords_found(name, found)

    def _get_handler_based_on_library_search_order(self, handlers):
        for libname in self.library_search_order:
            for handler in handlers:
                if handler.library.name == libname:
                    return [handler]
        return handlers

    def _filter_stdlib_handler(self, hand1, hand2):
        if hand1.library.orig_name in STDLIB_NAMES:
            std_hand, ext_hand = hand1, hand2
        elif hand2.library.orig_name in STDLIB_NAMES:
            std_hand, ext_hand = hand2, hand1
        else:
            return [hand1, hand2]
        if not RUN_KW_REGISTER.is_run_keyword(ext_hand):
            LOGGER.warn(
                "Keyword '%s' found both from a user created test library "
                "'%s' and Robot Framework standard library '%s'. The user "
                "created keyword is used. To select explicitly, and to get "
                "rid of this warning, use full format i.e. either '%s' or '%s'."
                % (std_hand.name,
                   ext_hand.library.orig_name, std_hand.library.orig_name,
                   ext_hand.longname, std_hand.longname))
        return [ext_hand]

    def _get_explicit_handler(self, name):
        libname, kwname = self._split_keyword_name(name)
        # 1) Find matching lib(s)
        libs = [ lib for lib in self._userlibs + self._testlibs.values()
                 if utils.eq(lib.name, libname) ]
        if not libs:
            return None
        # 2) Find matching kw from found libs
        found = [ lib.get_handler(kwname)
                  for lib in libs if lib.has_handler(kwname) ]
        if len(found) > 1:
            self._raise_multiple_keywords_found(name, found, implicit=False)
        return found and found[0] or None

    def _split_keyword_name(self, name):
        parts = name.split('.')
        kwname = parts.pop()       # pop last part
        libname = '.'.join(parts)  # and rejoin rest
        return libname, kwname

    def _raise_multiple_keywords_found(self, name, found, implicit=True):
        error = "Multiple keywords with name '%s' found.\n" % name
        if implicit:
            error += "Give the full name of the keyword you want to use.\n"
        names = [ handler.longname for handler in found ]
        names.sort()
        error += "Found: %s" % utils.seq2str(names)
        raise DataError(error)

class _VariableScopes:

    def __init__(self, suite, parent):
        # suite and parent are None only when used by copy_all
        if suite is not None:
            suite.variables.update(GLOBAL_VARIABLES)
            self._suite = self.current = suite.variables
        self._parents = []
        if parent is not None:
            self._parents.append(parent.namespace.variables.current)
            self._parents.extend(parent.namespace.variables._parents)
        self._test = None
        self._uk_handlers = []

    def copy_all(self):
        vs = _VariableScopes(None, None)
        vs._suite = self._suite
        vs._test = self._test
        vs._uk_handlers = self._uk_handlers[:]
        vs._parents = self._parents[:]
        vs.current = self.current
        return vs

    def replace_list(self, items):
        return self.current.replace_list(items)

    def replace_scalar(self, items):
        return self.current.replace_scalar(items)

    def replace_string(self, string):
        return self.current.replace_string(string)

    def set_from_file(self, path, args, overwrite=False):
        variables = self._suite.set_from_file(path, args, overwrite)
        if self._test is not None:
            self._test._set_from_file(variables, overwrite=True)
        for varz in self._uk_handlers:
            varz._set_from_file(variables, overwrite=True)
        if self._uk_handlers:
            self.current._set_from_file(variables, overwrite=True)

    def set_from_variable_table(self, rawvariables):
        self._suite.set_from_variable_table(rawvariables)

    def replace_meta(self, name, item, errors):
        error = None
        for varz in [self.current] + self._parents:
            try:
                if name in ['Setup', 'Teardown']:
                    return varz.replace_list(item[:1]) + item[1:]
                if name == 'Documentation':
                    return varz.replace_string(item, ignore_errors=True)
                if utils.is_list(item):
                    return varz.replace_list(item)
                return varz.replace_string(item)
            except DataError, error:
                pass
        errors.append("Replacing variables from metadata '%s' failed: %s"
                      % (name, error))
        return utils.unescape(item)

    def __getitem__(self, name):
        return self.current[name]

    def __setitem__(self, name, value):
        self.current[name] = value

    def end_suite(self):
        self._suite = self._test = self.current = None

    def start_test(self, test):
        self._test = self.current = self._suite.copy()

    def end_test(self):
        self.current = self._suite

    def start_uk(self, handler):
        self._uk_handlers.append(self.current)
        self.current = self.current.copy()

    def end_uk(self):
        self.current = self._uk_handlers.pop()

    def set_global(self, name, value):
        GLOBAL_VARIABLES[name] = value
        for ns in robot.running.NAMESPACES:
            ns.variables.set_suite(name, value)

    def set_suite(self, name, value):
        self._suite[name] = value
        self.set_test(name, value, False)

    def set_test(self, name, value, fail_if_no_test=True):
        if self._test is not None:
            self._test[name] = value
        elif fail_if_no_test:
            raise DataError("Cannot set test variable when no test is started")
        for varz in self._uk_handlers:
            varz[name] = value
        self.current[name] = value # latest uk handler is not in self._uk_handlers

    def keys(self):
        return self.current.keys()

    def has_key(self, key):
        return self.current.has_key(key)
<|endoftext|>


<commit_before>import base64
import datetime
import json
import logging
import re
import os.path
import urllib
import urlparse

import tornado.auth
import tornado.escape
import tornado.web

from base import BaseHandler
from logic import content as content_logic
from logic import content_remote
from logic import url_factory

# This monkeypatches tornado to do sync instead of async
class TumblrHandler(BaseHandler,
                    tornado.auth.OAuthMixin):
  _OAUTH_REQUEST_TOKEN_URL = "http://www.tumblr.com/oauth/request_token"
  _OAUTH_ACCESS_TOKEN_URL = "http://www.tumblr.com/oauth/access_token"
  _OAUTH_AUTHORIZE_URL = "http://www.tumblr.com/oauth/authorize"

  def get(self):
    if not self.authenticate(author=True):
      return

    if self.get_argument("get_feed", None):
      self.user = self.get_author_user()
      access_token, tumblr_info = self.get_tumblr_info()

      count = self.models.content_remote.get(to_username=self.user.username, type='tumblr').count()
      args = {}
      if count:
        jump = self.models.content_remote.get(to_username=self.user.username, type='tumblr')[count - 1:count]
        args['since_id'] = jump[0].post_id

      self.tumblr_request(
            "http://api.tumblr.com/v2/user/dashboard",
            self.timeline_result,
            access_token=access_token, **args)
      return
    elif self.get_argument("oauth_token", None):
      self.get_sync_authenticated_user(self._on_auth)
      return
    self.authorize_redirect()

  def post(self):
    if not self.authenticate(author=True):
      return

    op = self.get_argument('op', None)

    if op == 'favorite':
      self.favorite()
      return

    access_token, tumblr_info = self.get_tumblr_info()
    title = content_remote.strip_html(self.get_argument('title', ''))
    body = url_factory.add_base_uris(self, self.get_argument('view', '')) \
         + '\n' \
         + self.get_argument('url')

    # TODO, refactor out w FB logic
    thumb = self.get_argument('thumb', '')
    picture = None
    if thumb:
      thumb = url_factory.clean_filename(thumb)
      thumb = thumb[len(url_factory.resource_url(self)) + 1:]
      thumb = url_factory.resource_directory(self, thumb)
      picture = thumb

      basename = os.path.basename(thumb)
      dirname = os.path.dirname(thumb)
      if os.path.basename(dirname) == 'thumbs':
        parent_dir = os.path.dirname(dirname)
        original_dir = os.path.join(parent_dir, 'original')
        original_img = os.path.join(original_dir, basename)
        if os.path.exists(original_img):
          picture = original_img

      picture = picture[len(self.application.settings["static_path"]) + 1:]
      picture = self.static_url(picture, include_host=True)

    post_args = {"type": "text", "title": title, "body": body}
    video = re.search(r']*(youtube|vimeo)[^>]*>', body)
    if video:
      video = video.group(0)
      post_args["embed"] = video
      post_args["caption"] = body.replace(video, '
')
      post_args["type"] = "video"

    self.tumblr_request(
            "http://api.tumblr.com/v2/blog/" + tumblr_info['primary_blog'] + "/post",
            self.status_update_result,
            access_token=access_token,
            post_args=post_args,)

  # TODO XXX favoriting busted right now, need reblog key
  def favorite(self):
    # TODO, god this is confusing
    not_favorited = self.get_argument('not_favorited')
    operation = 'unlike' if not_favorited == '1' else 'like'
    post_id = self.get_argument('post_id', '')

    access_token, tumblr_info = self.get_tumblr_info()
    self.tumblr_request(
            "http://api.tumblr.com/v2/user/" + operation,
            self.favorite_result,
            access_token=access_token,
            post_args={ 'id': post_id })

  def get_tumblr_info(self):
    self.user = self.get_author_user()
    tumblr_info = json.loads(self.user.tumblr)
    access_token = {
      'key': tumblr_info['key'],
      'secret': tumblr_info['secret'],
    }

    return access_token, tumblr_info

  def status_update_result(self, response):
    pass

  def favorite_result(self, response):
    pass

  def timeline_result(self, response):
    posts = response['response']['posts']
    for post in posts:
      exists = self.models.content_remote.get(to_username=self.user.username, type='tumblr', post_id=str(post['id']))[0]

      if exists:
        continue
      else:
        new_post = self.models.content_remote()

      new_post.to_username = self.user.username
      new_post.username = post['blog_name']
      new_post.from_user = 'http://' + post['blog_name']
      #new_post.avatar = post['user']['profile_image_url']

      parsed_date = datetime.datetime.utcfromtimestamp(post['timestamp'])

      # we don't keep items that are over 30 days old
      if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(days=self.constants['feed_max_days_old']):
        continue

      new_post.date_created = parsed_date
      new_post.date_updated = None
      new_post.comments_count = post['note_count']
      new_post.comments_updated = None
      new_post.type = 'tumblr'
      new_post.post_id = str(post['id'])
      new_post.link = post['post_url']
      if post['type'] == 'text':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['body']))
      elif post['type'] == 'photo':
        new_post.title = post['caption']
        html = ""
        for photo in post['photos']:
          chosen_photo = None
          for size in photo['alt_sizes']:
            if not chosen_photo or (size['width'] <= 720 and chosen_photo['width'] < size['width']):
              chosen_photo = size
          html += ''
        new_post.view = html
      elif post['type'] == 'quote':
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['text'] + '
' + post['source']))
      elif post['type'] == 'link':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape('' + post['url'] + '
' + post['description']))
      elif post['type'] == 'chat':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['body'].replace('\r\n', '
')))
      elif post['type'] == 'audio':
        new_post.title = post['caption']
        # TODO XXX probably needs to be carefully escaped
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['player']))
      elif post['type'] == 'video':
        new_post.title = post['caption']
        chosen_video = None
        for video in post['player']:
          if not chosen_video or (video['width'] <= 720 and chosen_video['width'] < video['width']):
            chosen_video = video
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(chosen_video['embed_code']))
      elif post['type'] == 'answer':
        new_post.title = post['question']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['answer']))
      new_post.save()

    count = self.models.content_remote.get(to_username=self.user.username, type='tumblr', deleted=False).count()
    self.write(json.dumps({ 'count': count }))

  def tumblr_request(self, path, callback, access_token=None,
                      post_args=None, **args):
    #http://www.tumblr.com/docs/en/api/v2

    url = path
    # Add the OAuth resource request signature if we have credentials
    if access_token:
      all_args = {}
      all_args.update(args)
      all_args.update(post_args or {})
      method = "POST" if post_args is not None else "GET"
      oauth = self._oauth_request_parameters(
          url, access_token, all_args, method=method)
      args.update(oauth)
      if post_args:
        args.update(post_args)
    if args:
      url += "?" + urllib.urlencode(args)

    response = content_remote.get_url(url, post=(post_args is not None))
    self._on_tumblr_request(callback, response)

  def authorize_redirect(self, callback_uri=None, extra_params=None,
                         http_client=None):
    """Redirects the user to obtain OAuth authorization for this service.

    Twitter and FriendFeed both require that you register a Callback
    URL with your application. You should call this method to log the
    user in, and then call get_authenticated_user() in the handler
    you registered as your Callback URL to complete the authorization
    process.

    This method sets a cookie called _oauth_request_token which is
    subsequently used (and cleared) in get_authenticated_user for
    security purposes.
    """
    if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False):
      raise Exception("This service does not support oauth_callback")

    if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a":
      response = content_remote.get_url(self._oauth_request_token_url(callback_uri=callback_uri, extra_params=extra_params))
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)
    else:
      response = content_remote.get_url(self._oauth_request_token_url())
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)

  def get_sync_authenticated_user(self, callback, http_client=None):
    """Gets the OAuth authorized user and access token on callback.

    This method should be called from the handler for your registered
    OAuth Callback URL to complete the registration process. We call
    callback with the authenticated user, which in addition to standard
    attributes like 'name' includes the 'access_key' attribute, which
    contains the OAuth access you can use to make authorized requests
    to this service on behalf of the user.

    """
    request_key = tornado.escape.utf8(self.get_argument("oauth_token"))
    oauth_verifier = self.get_argument("oauth_verifier", None)
    request_cookie = self.get_cookie("_oauth_request_token")
    if not request_cookie:
      logging.warning("Missing OAuth request token cookie")
      callback(None)
      return
    self.clear_cookie("_oauth_request_token")
    cookie_key, cookie_secret = [base64.b64decode(tornado.escape.utf8(i)) for i in request_cookie.split("|")]
    if cookie_key != request_key:
      logging.info((cookie_key, request_key, request_cookie))
      logging.warning("Request token does not match cookie")
      callback(None)
      return
    token = dict(key=cookie_key, secret=cookie_secret)
    if oauth_verifier:
      token["verifier"] = oauth_verifier

    response = content_remote.get_url(self._oauth_access_token_url(token))
    self._on_access_token(callback, response)

  def _on_access_token(self, callback, response):
    if response.error:
      logging.warning("Could not fetch access token")
      callback(None)
      return

    access_token = tornado.auth._oauth_parse_response(response.body)
    callback(access_token)

  def _on_tumblr_request(self, callback, response):
    if response.error:
      logging.warning("Error response %s fetching %s", response.error,
                      response.request.url)
      callback(None)
      return
    callback(tornado.escape.json_decode(response.body))

  def _oauth_consumer_token(self):
    self.require_setting("tumblr_consumer_key", "Tumblr OAuth")
    self.require_setting("tumblr_consumer_secret", "Tumblr OAuth")
    return dict(
        key=self.settings["tumblr_consumer_key"],
        secret=self.settings["tumblr_consumer_secret"])

  def _on_auth(self, access_token):
    if not access_token:
      raise tornado.web.HTTPError(500, "Tumblr auth failed")

    user = self.get_author_user()
    user.tumblr = json.dumps(access_token)
    user.save()

    self.tumblr_request(
          "http://api.tumblr.com/v2/user/info",
          self.info_result,
          access_token=access_token)

  def info_result(self, response):
    blogs = response['response']['user']['blogs']
    for blog in blogs:
      if blog['primary']:
        user = self.get_author_user()
        access_token = json.loads(user.tumblr)
        access_token['primary_blog'] = urlparse.urlparse(blog['url']).netloc
        user.tumblr = json.dumps(access_token)
        user.save()

        self.redirect(self.nav_url(section='dashboard'))
        break

  def delete(self):
    if not self.authenticate(author=True):
      return
    user = self.get_author_user()
    user.tumblr = None
    user.save()
<commit_msg>fix bad parsing of videos<commit_after>import base64
import datetime
import json
import logging
import re
import os.path
import urllib
import urlparse

import tornado.auth
import tornado.escape
import tornado.web

from base import BaseHandler
from logic import content as content_logic
from logic import content_remote
from logic import url_factory

# This monkeypatches tornado to do sync instead of async
class TumblrHandler(BaseHandler,
                    tornado.auth.OAuthMixin):
  _OAUTH_REQUEST_TOKEN_URL = "http://www.tumblr.com/oauth/request_token"
  _OAUTH_ACCESS_TOKEN_URL = "http://www.tumblr.com/oauth/access_token"
  _OAUTH_AUTHORIZE_URL = "http://www.tumblr.com/oauth/authorize"

  def get(self):
    if not self.authenticate(author=True):
      return

    if self.get_argument("get_feed", None):
      self.user = self.get_author_user()
      access_token, tumblr_info = self.get_tumblr_info()

      count = self.models.content_remote.get(to_username=self.user.username, type='tumblr').count()
      args = {}
      if count:
        jump = self.models.content_remote.get(to_username=self.user.username, type='tumblr')[count - 1:count]
        args['since_id'] = jump[0].post_id

      self.tumblr_request(
            "http://api.tumblr.com/v2/user/dashboard",
            self.timeline_result,
            access_token=access_token, **args)
      return
    elif self.get_argument("oauth_token", None):
      self.get_sync_authenticated_user(self._on_auth)
      return
    self.authorize_redirect()

  def post(self):
    if not self.authenticate(author=True):
      return

    op = self.get_argument('op', None)

    if op == 'favorite':
      self.favorite()
      return

    access_token, tumblr_info = self.get_tumblr_info()
    title = content_remote.strip_html(self.get_argument('title', ''))
    body = url_factory.add_base_uris(self, self.get_argument('view', '')) \
         + '\n' \
         + self.get_argument('url')

    # TODO, refactor out w FB logic
    thumb = self.get_argument('thumb', '')
    picture = None
    if thumb:
      thumb = url_factory.clean_filename(thumb)
      thumb = thumb[len(url_factory.resource_url(self)) + 1:]
      thumb = url_factory.resource_directory(self, thumb)
      picture = thumb

      basename = os.path.basename(thumb)
      dirname = os.path.dirname(thumb)
      if os.path.basename(dirname) == 'thumbs':
        parent_dir = os.path.dirname(dirname)
        original_dir = os.path.join(parent_dir, 'original')
        original_img = os.path.join(original_dir, basename)
        if os.path.exists(original_img):
          picture = original_img

      picture = picture[len(self.application.settings["static_path"]) + 1:]
      picture = self.static_url(picture, include_host=True)

    post_args = {"type": "text", "title": title, "body": body}
    video = re.search(r']*(youtube|vimeo)[^>]*>', body)
    if video:
      video = video.group(0)
      post_args["embed"] = video
      post_args["caption"] = body.replace(video, '
')
      post_args["type"] = "video"

    self.tumblr_request(
            "http://api.tumblr.com/v2/blog/" + tumblr_info['primary_blog'] + "/post",
            self.status_update_result,
            access_token=access_token,
            post_args=post_args,)

  # TODO XXX favoriting busted right now, need reblog key
  def favorite(self):
    # TODO, god this is confusing
    not_favorited = self.get_argument('not_favorited')
    operation = 'unlike' if not_favorited == '1' else 'like'
    post_id = self.get_argument('post_id', '')

    access_token, tumblr_info = self.get_tumblr_info()
    self.tumblr_request(
            "http://api.tumblr.com/v2/user/" + operation,
            self.favorite_result,
            access_token=access_token,
            post_args={ 'id': post_id })

  def get_tumblr_info(self):
    self.user = self.get_author_user()
    tumblr_info = json.loads(self.user.tumblr)
    access_token = {
      'key': tumblr_info['key'],
      'secret': tumblr_info['secret'],
    }

    return access_token, tumblr_info

  def status_update_result(self, response):
    pass

  def favorite_result(self, response):
    pass

  def timeline_result(self, response):
    posts = response['response']['posts']
    for post in posts:
      exists = self.models.content_remote.get(to_username=self.user.username, type='tumblr', post_id=str(post['id']))[0]

      if exists:
        continue
      else:
        new_post = self.models.content_remote()

      new_post.to_username = self.user.username
      new_post.username = post['blog_name']
      new_post.from_user = 'http://' + post['blog_name']
      #new_post.avatar = post['user']['profile_image_url']

      parsed_date = datetime.datetime.utcfromtimestamp(post['timestamp'])

      # we don't keep items that are over 30 days old
      if parsed_date < datetime.datetime.utcnow() - datetime.timedelta(days=self.constants['feed_max_days_old']):
        continue

      new_post.date_created = parsed_date
      new_post.date_updated = None
      new_post.comments_count = post['note_count']
      new_post.comments_updated = None
      new_post.type = 'tumblr'
      new_post.post_id = str(post['id'])
      new_post.link = post['post_url']
      if post['type'] == 'text':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['body']))
      elif post['type'] == 'photo':
        html = ""
        for photo in post['photos']:
          chosen_photo = None
          for size in photo['alt_sizes']:
            if not chosen_photo or (size['width'] <= 720 and chosen_photo['width'] < size['width']):
              chosen_photo = size
          html += ''
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(post['caption']))
        new_post.view = html
      elif post['type'] == 'quote':
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['text'] + '
' + post['source']))
      elif post['type'] == 'link':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape('' + post['url'] + '
' + post['description']))
      elif post['type'] == 'chat':
        new_post.title = post['title']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['body'].replace('\r\n', '
')))
      elif post['type'] == 'audio':
        html = ""
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(post['caption']))
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(post['player']))
        new_post.view = html
      elif post['type'] == 'video':
        chosen_video = None
        for video in post['player']:
          if not chosen_video or (video['width'] <= 720 and chosen_video['width'] < video['width']):
            chosen_video = video
        html = ""
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(post['caption']))
        html += content_remote.sanitize(tornado.escape.xhtml_unescape(chosen_video['embed_code']))
        new_post.view =
      elif post['type'] == 'answer':
        new_post.title = post['question']
        new_post.view = content_remote.sanitize(tornado.escape.xhtml_unescape(post['answer']))
      new_post.save()

    count = self.models.content_remote.get(to_username=self.user.username, type='tumblr', deleted=False).count()
    self.write(json.dumps({ 'count': count }))

  def tumblr_request(self, path, callback, access_token=None,
                      post_args=None, **args):
    #http://www.tumblr.com/docs/en/api/v2

    url = path
    # Add the OAuth resource request signature if we have credentials
    if access_token:
      all_args = {}
      all_args.update(args)
      all_args.update(post_args or {})
      method = "POST" if post_args is not None else "GET"
      oauth = self._oauth_request_parameters(
          url, access_token, all_args, method=method)
      args.update(oauth)
      if post_args:
        args.update(post_args)
    if args:
      url += "?" + urllib.urlencode(args)

    response = content_remote.get_url(url, post=(post_args is not None))
    self._on_tumblr_request(callback, response)

  def authorize_redirect(self, callback_uri=None, extra_params=None,
                         http_client=None):
    """Redirects the user to obtain OAuth authorization for this service.

    Twitter and FriendFeed both require that you register a Callback
    URL with your application. You should call this method to log the
    user in, and then call get_authenticated_user() in the handler
    you registered as your Callback URL to complete the authorization
    process.

    This method sets a cookie called _oauth_request_token which is
    subsequently used (and cleared) in get_authenticated_user for
    security purposes.
    """
    if callback_uri and getattr(self, "_OAUTH_NO_CALLBACKS", False):
      raise Exception("This service does not support oauth_callback")

    if getattr(self, "_OAUTH_VERSION", "1.0a") == "1.0a":
      response = content_remote.get_url(self._oauth_request_token_url(callback_uri=callback_uri, extra_params=extra_params))
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)
    else:
      response = content_remote.get_url(self._oauth_request_token_url())
      self._on_request_token(self._OAUTH_AUTHORIZE_URL, callback_uri, response)

  def get_sync_authenticated_user(self, callback, http_client=None):
    """Gets the OAuth authorized user and access token on callback.

    This method should be called from the handler for your registered
    OAuth Callback URL to complete the registration process. We call
    callback with the authenticated user, which in addition to standard
    attributes like 'name' includes the 'access_key' attribute, which
    contains the OAuth access you can use to make authorized requests
    to this service on behalf of the user.

    """
    request_key = tornado.escape.utf8(self.get_argument("oauth_token"))
    oauth_verifier = self.get_argument("oauth_verifier", None)
    request_cookie = self.get_cookie("_oauth_request_token")
    if not request_cookie:
      logging.warning("Missing OAuth request token cookie")
      callback(None)
      return
    self.clear_cookie("_oauth_request_token")
    cookie_key, cookie_secret = [base64.b64decode(tornado.escape.utf8(i)) for i in request_cookie.split("|")]
    if cookie_key != request_key:
      logging.info((cookie_key, request_key, request_cookie))
      logging.warning("Request token does not match cookie")
      callback(None)
      return
    token = dict(key=cookie_key, secret=cookie_secret)
    if oauth_verifier:
      token["verifier"] = oauth_verifier

    response = content_remote.get_url(self._oauth_access_token_url(token))
    self._on_access_token(callback, response)

  def _on_access_token(self, callback, response):
    if response.error:
      logging.warning("Could not fetch access token")
      callback(None)
      return

    access_token = tornado.auth._oauth_parse_response(response.body)
    callback(access_token)

  def _on_tumblr_request(self, callback, response):
    if response.error:
      logging.warning("Error response %s fetching %s", response.error,
                      response.request.url)
      callback(None)
      return
    callback(tornado.escape.json_decode(response.body))

  def _oauth_consumer_token(self):
    self.require_setting("tumblr_consumer_key", "Tumblr OAuth")
    self.require_setting("tumblr_consumer_secret", "Tumblr OAuth")
    return dict(
        key=self.settings["tumblr_consumer_key"],
        secret=self.settings["tumblr_consumer_secret"])

  def _on_auth(self, access_token):
    if not access_token:
      raise tornado.web.HTTPError(500, "Tumblr auth failed")

    user = self.get_author_user()
    user.tumblr = json.dumps(access_token)
    user.save()

    self.tumblr_request(
          "http://api.tumblr.com/v2/user/info",
          self.info_result,
          access_token=access_token)

  def info_result(self, response):
    blogs = response['response']['user']['blogs']
    for blog in blogs:
      if blog['primary']:
        user = self.get_author_user()
        access_token = json.loads(user.tumblr)
        access_token['primary_blog'] = urlparse.urlparse(blog['url']).netloc
        user.tumblr = json.dumps(access_token)
        user.save()

        self.redirect(self.nav_url(section='dashboard'))
        break

  def delete(self):
    if not self.authenticate(author=True):
      return
    user = self.get_author_user()
    user.tumblr = None
    user.save()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 18:08
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion

class Migration(migrations.Migration):

    dependencies = [
        ('wizard_builder', '0044_auto_20171101_1412'),
    ]

    operations = [
        migrations.AlterField(
            model_name='formquestion',
            name='page',
            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='wizard_builder.Page'),
        ),
    ]
<commit_msg>$ make clean<commit_after># -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 18:08
from __future__ import unicode_literals

import django.db.models.deletion
from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('wizard_builder', '0044_auto_20171101_1412'),
    ]

    operations = [
        migrations.AlterField(
            model_name='formquestion',
            name='page',
            field=models.ForeignKey(
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                to='wizard_builder.Page'),
        ),
    ]
<|endoftext|>


<commit_before>import os.path as op
import numpy as np
import matplotlib.pyplot as plt

from elfpy.dataio import _get_filename

class Cycler(list):
    def __init__(self, sequence):
        list.__init__(self, sequence)
        self.n_max = len(sequence)

    def __getitem__(self, ii):
        return list.__getitem__(self, ii % self.n_max)

def define_plot_attributes():
    colors = Cycler([(0.0, 0.0, 0.0),
                     (0.6, 0.0, 1.0),
                     (1.0, 1.0, 0.0), (1.0, 0.0, 0.8),
                     (0.5, 1.0, 0.5), (0.5, 1.0, 1.0),
                     (0.8, 0.0, 0.2), (1.0, 0.0, 0.0),
                     (0.0, 0.0, 0.4), (0.0, 0.0, 1.0), (0.0, 0.75, 0.0),])

    markers = Cycler(['o', 'v', 's','^', '<',  'D', '>', 'x', 'p', 'h', '+'])

    linestyles = Cycler(['-', '--', '-.', ':'])

    color_vector=[]
    for ii in range(0,6):
        color_vector = np.append(color_vector, colors)
    color_vector = np.reshape(color_vector, (66,3))

    return markers, linestyles, color_vector

markers, linestyles, color_vector = define_plot_attributes()

plot_options = {
    'linewidth' : 1,
}

data_options = {
    'sampling' : 1,
    'use_markers' : 1,
}

def make_legend_text(args, ks):
    """
    Make a text of a legend.

    Parameters
    ----------
    - args : string
    - ks : float, float

    Returns
    -------
    - leg : string
    """

    leg = []
    for ii, arg in enumerate(args):
        print arg
        print ks[ii][0]
        print ks[ii][1]
        leg.append('%s,\n $E_0 = %.6f $, $E_1 = %.6f $'
                   % (op.splitext(arg)[0], ks[ii][0], ks[ii][1]))
    return leg

def _plot_curve(ax, dx, dy, xlabel, ylabel, label='', title=None):
    il = len(ax.lines)
    marker = markers[il] if data_options['use_markers'] else None
    ax.plot(dx, dy, label=label, color=color_vector[il,:3], marker=marker,
            **plot_options)
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)

    if title is not None:
        plt.title(title)

def _get_ax(fig_num, ax):
    fig = plt.figure(fig_num)

    if ax is None:
        fig.clf()
        ax = fig.add_subplot(111)

    return ax

def _get_label(data, label):
    if label:
        if label == '%':
            label = data.name

        else:
            label = ': '.join((data.name, label))

    return label

def _get_data(dx, dy):
    ic = data_options['sampling']

    length = dx.shape[0]
    num = float(length) / ic
    ii = np.linspace(0, length - 1, np.ceil(num)).astype(np.int)

    return dx[ii], dy[ii]

def set_sampling(data, sampling=1, **kwargs):
    data_options['sampling'] = sampling

def use_markers(data, use=1, **kwargs):
    data_options['use_markers'] = use

def set_plot_option(data, option='', value=0.0, **kwargs):
    plot_options[option] = value

def plot_strain_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.strain)
    _plot_curve(ax, dx, dy, 'time [s]', 'strain [1]',
                label=label, title='strain-time')
    return ax

def plot_stress_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.stress)
    _plot_curve(ax, dx, dy, 'time [s]', 'stress [MPa]',
                label=label, title='stress-time')
    return ax

def plot_stress_strain(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.strain, data.stress)
    _plot_curve(ax, dx, dy, 'strain [1]', 'stress [MPa]',
                label=label, title='stress-strain')
    return ax

def plot_raw_strain_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.raw_strain)
    _plot_curve(ax, dx, dy, 'time [s]', 'strain [1]',
                label=label, title='raw strain-time')
    return ax

def plot_raw_stress_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.raw_stress)
    _plot_curve(ax, dx, dy, 'time [s]', 'stress [MPa]',
                label=label, title='raw stress-time')
    return ax

def plot_raw_stress_strain(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.raw_strain, data.raw_stress)
    _plot_curve(ax, dx, dy, 'strain [1]', 'stress [MPa]',
                label=label, title='raw stress-strain')
    return ax

def plot_cycles_time(data, fig_num=1, ax=0):
    ax = _get_ax(fig_num, ax)
    ymin, ymax = ax.axis()[2:]

    for ii in data.cycles:
        plt.vlines(data.full_time[ii.start], ymin, ymax)

    return ax

def mark_ultimate_strain(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    plt.plot(data.time[data.iult], data.ultimate_strain, 'k*',
             ms=20, label=label)

    return ax

def mark_ultimate_stress(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    plt.plot(data.time[data.iult], data.ultimate_stress, 'k*',
             ms=20, label=label)

    return ax

def mark_ultimate_values(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    plt.plot(data.ultimate_strain, data.ultimate_stress, 'k*',
             ms=20, label=label)

    return ax

def _plot_stress_region_line(data, region, color, linewidth, label):
    if region is None: return

    ii = [region.start, region.stop]
    plt.plot(data.strain[ii], data.stress[ii], color,
             linewidth=linewidth, label=label)

def mark_stress_regions(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    for region in data.stress_regions:
        _plot_stress_region_line(data, region, 'k-', 5, label)

    _plot_stress_region_line(data, data.irange_small, 'b-', 5, label)
    _plot_stress_region_line(data, data.irange_large, 'r-', 5, label)

    return ax

def _plot_fit_line(data, region, coefs, color, linewidth, label):
    if coefs is None: return

    ii = [region.start, region.stop]
    strain = data.strain[ii]
    stress = coefs[0] * strain + coefs[1]
    plt.plot(strain, stress, color, linewidth=linewidth, label=label)

def mark_fits(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)

    _plot_fit_line(data, data.irange_small, data.linear_fit_small, 'b-', 5,
                   'small strain')
    _plot_fit_line(data, data.irange_large, data.linear_fit_large, 'r-', 5,
                   'large strain')

    return ax

def show(datas, **kwargs):
    plt.show()

def save_figure(datas, fig_num=1, suffix='', filename=''):
    fig = plt.figure(fig_num)

    if not filename:
        ax = fig.gca()
        title = ax.title.get_text()
        filename = title.replace(' ', '_')

    if not suffix:
        suffix = 'png'

    filename = _get_filename(datas, filename, '', suffix)

    fig.savefig(filename)
<commit_msg>new make_colors()<commit_after>import os.path as op
import numpy as np
import matplotlib.pyplot as plt

from elfpy.dataio import _get_filename

class Cycler(list):
    def __init__(self, sequence):
        list.__init__(self, sequence)
        self.n_max = len(sequence)

    def __getitem__(self, ii):
        return list.__getitem__(self, ii % self.n_max)

def define_plot_attributes():
    colors = Cycler([(0.0, 0.0, 0.0),
                     (0.6, 0.0, 1.0),
                     (1.0, 1.0, 0.0), (1.0, 0.0, 0.8),
                     (0.5, 1.0, 0.5), (0.5, 1.0, 1.0),
                     (0.8, 0.0, 0.2), (1.0, 0.0, 0.0),
                     (0.0, 0.0, 0.4), (0.0, 0.0, 1.0), (0.0, 0.75, 0.0),])

    markers = Cycler(['o', 'v', 's','^', '<',  'D', '>', 'x', 'p', 'h', '+'])

    linestyles = Cycler(['-', '--', '-.', ':'])

    color_vector=[]
    for ii in range(0,6):
        color_vector = np.append(color_vector, colors)
    color_vector = np.reshape(color_vector, (66,3))

    return markers, linestyles, color_vector

markers, linestyles, color_vector = define_plot_attributes()

def make_colors(num):
    """
    Make `num` continuously changing rainbow-like RGB colors.
    """
    def g(n):
        """
        Map sine [-1.0 .. 1.0] => color byte [0 .. 255].
        """
        return 255 * (n + 1) / 2.0

    def f(start, stop, num):

        interval = (stop - start) / num

        for n in range(num):
            coefficient = start + interval * n
            yield g(np.sin(coefficient * np.pi))

    red = f(0.5, 1.5, num)
    green = f(1.5, 3.5, num)
    blue = f(1.5, 2.5, num)

    rgbs = [('#%02x%02x%02x' % rgb) for rgb in zip(red, green, blue)]
    return rgbs

plot_options = {
    'linewidth' : 1,
}

data_options = {
    'sampling' : 1,
    'use_markers' : 1,
}

def make_legend_text(args, ks):
    """
    Make a text of a legend.

    Parameters
    ----------
    - args : string
    - ks : float, float

    Returns
    -------
    - leg : string
    """

    leg = []
    for ii, arg in enumerate(args):
        print arg
        print ks[ii][0]
        print ks[ii][1]
        leg.append('%s,\n $E_0 = %.6f $, $E_1 = %.6f $'
                   % (op.splitext(arg)[0], ks[ii][0], ks[ii][1]))
    return leg

def _plot_curve(ax, dx, dy, xlabel, ylabel, label='', title=None):
    il = len(ax.lines)
    marker = markers[il] if data_options['use_markers'] else None
    ax.plot(dx, dy, label=label, color=color_vector[il,:3], marker=marker,
            **plot_options)
    ax.set_xlabel(xlabel)
    ax.set_ylabel(ylabel)

    if title is not None:
        plt.title(title)

def _get_ax(fig_num, ax):
    fig = plt.figure(fig_num)

    if ax is None:
        fig.clf()
        ax = fig.add_subplot(111)

    return ax

def _get_label(data, label):
    if label:
        if label == '%':
            label = data.name

        else:
            label = ': '.join((data.name, label))

    return label

def _get_data(dx, dy):
    ic = data_options['sampling']

    length = dx.shape[0]
    num = float(length) / ic
    ii = np.linspace(0, length - 1, np.ceil(num)).astype(np.int)

    return dx[ii], dy[ii]

def set_sampling(data, sampling=1, **kwargs):
    data_options['sampling'] = sampling

def use_markers(data, use=1, **kwargs):
    data_options['use_markers'] = use

def set_plot_option(data, option='', value=0.0, **kwargs):
    plot_options[option] = value

def plot_strain_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.strain)
    _plot_curve(ax, dx, dy, 'time [s]', 'strain [1]',
                label=label, title='strain-time')
    return ax

def plot_stress_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.stress)
    _plot_curve(ax, dx, dy, 'time [s]', 'stress [MPa]',
                label=label, title='stress-time')
    return ax

def plot_stress_strain(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.strain, data.stress)
    _plot_curve(ax, dx, dy, 'strain [1]', 'stress [MPa]',
                label=label, title='stress-strain')
    return ax

def plot_raw_strain_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.raw_strain)
    _plot_curve(ax, dx, dy, 'time [s]', 'strain [1]',
                label=label, title='raw strain-time')
    return ax

def plot_raw_stress_time(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.time, data.raw_stress)
    _plot_curve(ax, dx, dy, 'time [s]', 'stress [MPa]',
                label=label, title='raw stress-time')
    return ax

def plot_raw_stress_strain(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)
    dx, dy = _get_data(data.raw_strain, data.raw_stress)
    _plot_curve(ax, dx, dy, 'strain [1]', 'stress [MPa]',
                label=label, title='raw stress-strain')
    return ax

def plot_cycles_time(data, fig_num=1, ax=0):
    ax = _get_ax(fig_num, ax)
    ymin, ymax = ax.axis()[2:]

    for ii in data.cycles:
        plt.vlines(data.full_time[ii.start], ymin, ymax)

    return ax

def mark_ultimate_strain(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    plt.plot(data.time[data.iult], data.ultimate_strain, 'k*',
             ms=20, label=label)

    return ax

def mark_ultimate_stress(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    plt.plot(data.time[data.iult], data.ultimate_stress, 'k*',
             ms=20, label=label)

    return ax

def mark_ultimate_values(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    plt.plot(data.ultimate_strain, data.ultimate_stress, 'k*',
             ms=20, label=label)

    return ax

def _plot_stress_region_line(data, region, color, linewidth, label):
    if region is None: return

    ii = [region.start, region.stop]
    plt.plot(data.strain[ii], data.stress[ii], color,
             linewidth=linewidth, label=label)

def mark_stress_regions(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)
    label = _get_label(data, label)

    for region in data.stress_regions:
        _plot_stress_region_line(data, region, 'k-', 5, label)

    _plot_stress_region_line(data, data.irange_small, 'b-', 5, label)
    _plot_stress_region_line(data, data.irange_large, 'r-', 5, label)

    return ax

def _plot_fit_line(data, region, coefs, color, linewidth, label):
    if coefs is None: return

    ii = [region.start, region.stop]
    strain = data.strain[ii]
    stress = coefs[0] * strain + coefs[1]
    plt.plot(strain, stress, color, linewidth=linewidth, label=label)

def mark_fits(data, fig_num=1, ax=0, label=''):
    ax = _get_ax(fig_num, ax)

    _plot_fit_line(data, data.irange_small, data.linear_fit_small, 'b-', 5,
                   'small strain')
    _plot_fit_line(data, data.irange_large, data.linear_fit_large, 'r-', 5,
                   'large strain')

    return ax

def show(datas, **kwargs):
    plt.show()

def save_figure(datas, fig_num=1, suffix='', filename=''):
    fig = plt.figure(fig_num)

    if not filename:
        ax = fig.gca()
        title = ax.title.get_text()
        filename = title.replace(' ', '_')

    if not suffix:
        suffix = 'png'

    filename = _get_filename(datas, filename, '', suffix)

    fig.savefig(filename)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##
## This file is part of Invenio.
## Copyright (C) 2009, 2010, 2011, 2012 CERN.
##
## Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## Invenio is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

"""
Invenio DB dumper.

Usage: /opt/invenio/bin/dbdump [options]

Command options:
  -o, --output=DIR      Output directory. [default=/opt/invenio/var/log]
  -n, --number=NUM      Keep up to NUM previous dump files. [default=5]

Scheduling options:
  -u, --user=USER User name to submit the task as, password needed.
  -t, --runtime=TIME Time to execute the task (now), e.g. +15s, 5m, 3h, 2002-10-27 13:57:26.
  -s, --sleeptime=SLEEP Sleeping frequency after which to repeat task (no), e.g.: 30m, 2h, 1d.
  -L  --limit=LIMIT Time limit when it is allowed to execute the task, e.g. Sunday 01:00-05:00.
                    The time limit syntax is [Wee[kday]] [hh[:mm][-hh[:mm]]].
  -P, --priority=PRI Task priority (0=default, 1=higher, etc).
  -N, --name=NAME Task specific name (advanced option).

General options:
  -h, --help  Print this help.
  -V, --version  Print version information.
  -v, --verbose=LEVEL Verbose level (0=min, 1=default, 9=max).
      --profile=STATS Print profile information. STATS is a comma-separated
   list of desired output stats (calls, cumulative,
   file, line, module, name, nfl, pcalls, stdname, time).
"""

__revision__ = "$Id$"

import os
import sys
from invenio.config import CFG_LOGDIR, CFG_PATH_MYSQL, CFG_PATH_GZIP
from invenio.legacy.dbquery import CFG_DATABASE_HOST, \
                            CFG_DATABASE_USER, \
                            CFG_DATABASE_PASS, \
                            CFG_DATABASE_NAME
from invenio.legacy.bibsched.bibtask import task_init, write_message, task_set_option, \
                            task_get_option, task_update_progress, \
                            task_get_task_param
from invenio.utils.shell import run_shell_command, escape_shell_arg

def _delete_old_dumps(dirname, filename, number_to_keep):
    """
    Look for files in DIRNAME directory starting with FILENAME
    pattern.  Delete up to NUMBER_TO_KEEP files (when sorted
    alphabetically, which is equal to sorted by date).  Useful to
    prune old dump files.
    """
    files = [x for x in os.listdir(dirname) if x.startswith(filename)]
    files.sort()
    for afile in files[:-number_to_keep]:
        write_message("... deleting %s" % dirname + os.sep + afile)
        os.remove(dirname + os.sep + afile)

def _dump_database(dirname, filename):
    """
    Dump Invenio database into SQL file called FILENAME living in
    DIRNAME.
    """
    write_message("... writing %s" % dirname + os.sep + filename)
    cmd = CFG_PATH_MYSQL + 'dump'
    if not os.path.exists(cmd):
        msg = "ERROR: cannot find %s." % cmd
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)

    cmd += " --skip-opt --add-drop-table --add-locks --create-options " \
           " --quick --extended-insert --set-charset --disable-keys " \
           " --host=%s --user=%s --password=%s %s | %s -c " % \
           (escape_shell_arg(CFG_DATABASE_HOST),
            escape_shell_arg(CFG_DATABASE_USER),
            escape_shell_arg(CFG_DATABASE_PASS),
            escape_shell_arg(CFG_DATABASE_NAME),
            CFG_PATH_GZIP)
    dummy1, dummy2, dummy3 = run_shell_command(cmd, None, dirname + os.sep + filename)
    if dummy1:
        msg = "ERROR: mysqldump exit code is %s." % repr(dummy1)
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)
    if dummy2:
        msg = "ERROR: mysqldump stdout is %s." % repr(dummy1)
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)
    if dummy3:
        msg = "ERROR: mysqldump stderr is %s." % repr(dummy1)
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)

def _dbdump_elaborate_submit_param(key, value, dummyopts, dummyargs):
    """
    Elaborate task submission parameter.  See bibtask's
    task_submit_elaborate_specific_parameter_fnc for help.
    """
    if key in ('-n', '--number'):
        try:
            task_set_option('number', int(value))
        except ValueError:
            raise StandardError("ERROR: Number '%s' is not integer." % value)
    elif key in ('-o', '--output'):
        if os.path.isdir(value):
            task_set_option('output', value)
        else:
            raise StandardError("ERROR: Output '%s' is not a directory." % \
                  value)
    else:
        return False
    return True

def _dbdump_run_task_core():
    """
    Run DB dumper core stuff.

    Note: do not use task_can_sleep() stuff here because we don't want
    other tasks to interrupt us while we are dumping the DB content.
    """
    # read params:
    task_update_progress("Reading parameters")
    write_message("Reading parameters started")
    output_dir = task_get_option('output', CFG_LOGDIR)
    output_num = task_get_option('number', 5)
    output_fil_prefix = CFG_DATABASE_NAME + '-dbdump-'
    output_fil_suffix = task_get_task_param('task_starting_time').replace(' ', '_') + '.sql.gz'
    output_fil = output_fil_prefix + output_fil_suffix
    write_message("Reading parameters ended")
    # make dump:
    task_update_progress("Dumping database")
    write_message("Database dump started")
    _dump_database(output_dir, output_fil)
    write_message("Database dump ended")
    # prune old dump files:
    task_update_progress("Pruning old dump files")
    write_message("Pruning old dump files started")
    _delete_old_dumps(output_dir, output_fil_prefix, output_num)
    write_message("Pruning old dump files ended")
    # we are done:
    task_update_progress("Done.")
    return True

def main():
    """Main that construct all the bibtask."""
    task_init(authorization_action='rundbdump',
              authorization_msg="DB Dump Task Submission",
              help_specific_usage="""\
  -o, --output=DIR      Output directory. [default=%s]
  -n, --number=NUM      Keep up to NUM previous dump files. [default=5]
""" % CFG_LOGDIR,
              version=__revision__,
              specific_params=("n:o:",
                               ["number=", "output="]),
              task_submit_elaborate_specific_parameter_fnc=_dbdump_elaborate_submit_param,
              task_run_fnc=_dbdump_run_task_core)

if __name__ == '__main__':
    main()
<commit_msg>legacy: dbdump fix<commit_after># -*- coding: utf-8 -*-
##
## This file is part of Invenio.
## Copyright (C) 2009, 2010, 2011, 2012 CERN.
##
## Invenio is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 2 of the
## License, or (at your option) any later version.
##
## Invenio is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Invenio; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

"""
Invenio DB dumper.

Usage: /opt/invenio/bin/dbdump [options]

Command options:
  -o, --output=DIR      Output directory. [default=/opt/invenio/var/log]
  -n, --number=NUM      Keep up to NUM previous dump files. [default=5]

Scheduling options:
  -u, --user=USER User name to submit the task as, password needed.
  -t, --runtime=TIME Time to execute the task (now), e.g. +15s, 5m, 3h, 2002-10-27 13:57:26.
  -s, --sleeptime=SLEEP Sleeping frequency after which to repeat task (no), e.g.: 30m, 2h, 1d.
  -L  --limit=LIMIT Time limit when it is allowed to execute the task, e.g. Sunday 01:00-05:00.
                    The time limit syntax is [Wee[kday]] [hh[:mm][-hh[:mm]]].
  -P, --priority=PRI Task priority (0=default, 1=higher, etc).
  -N, --name=NAME Task specific name (advanced option).

General options:
  -h, --help  Print this help.
  -V, --version  Print version information.
  -v, --verbose=LEVEL Verbose level (0=min, 1=default, 9=max).
      --profile=STATS Print profile information. STATS is a comma-separated
   list of desired output stats (calls, cumulative,
   file, line, module, name, nfl, pcalls, stdname, time).
"""

__revision__ = "$Id$"

import os
import sys
from invenio.config import CFG_LOGDIR, CFG_PATH_MYSQL, CFG_PATH_GZIP, \
                            CFG_DATABASE_HOST, \
                            CFG_DATABASE_USER, \
                            CFG_DATABASE_PASS, \
                            CFG_DATABASE_NAME
from invenio.legacy.bibsched.bibtask import task_init, write_message, task_set_option, \
                            task_get_option, task_update_progress, \
                            task_get_task_param
from invenio.utils.shell import run_shell_command, escape_shell_arg

def _delete_old_dumps(dirname, filename, number_to_keep):
    """
    Look for files in DIRNAME directory starting with FILENAME
    pattern.  Delete up to NUMBER_TO_KEEP files (when sorted
    alphabetically, which is equal to sorted by date).  Useful to
    prune old dump files.
    """
    files = [x for x in os.listdir(dirname) if x.startswith(filename)]
    files.sort()
    for afile in files[:-number_to_keep]:
        write_message("... deleting %s" % dirname + os.sep + afile)
        os.remove(dirname + os.sep + afile)

def _dump_database(dirname, filename):
    """
    Dump Invenio database into SQL file called FILENAME living in
    DIRNAME.
    """
    write_message("... writing %s" % dirname + os.sep + filename)
    cmd = CFG_PATH_MYSQL + 'dump'
    if not os.path.exists(cmd):
        msg = "ERROR: cannot find %s." % cmd
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)

    cmd += " --skip-opt --add-drop-table --add-locks --create-options " \
           " --quick --extended-insert --set-charset --disable-keys " \
           " --host=%s --user=%s --password=%s %s | %s -c " % \
           (escape_shell_arg(CFG_DATABASE_HOST),
            escape_shell_arg(CFG_DATABASE_USER),
            escape_shell_arg(CFG_DATABASE_PASS),
            escape_shell_arg(CFG_DATABASE_NAME),
            CFG_PATH_GZIP)
    dummy1, dummy2, dummy3 = run_shell_command(cmd, None, dirname + os.sep + filename)
    if dummy1:
        msg = "ERROR: mysqldump exit code is %s." % repr(dummy1)
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)
    if dummy2:
        msg = "ERROR: mysqldump stdout is %s." % repr(dummy1)
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)
    if dummy3:
        msg = "ERROR: mysqldump stderr is %s." % repr(dummy1)
        write_message(msg, stream=sys.stderr)
        raise StandardError(msg)

def _dbdump_elaborate_submit_param(key, value, dummyopts, dummyargs):
    """
    Elaborate task submission parameter.  See bibtask's
    task_submit_elaborate_specific_parameter_fnc for help.
    """
    if key in ('-n', '--number'):
        try:
            task_set_option('number', int(value))
        except ValueError:
            raise StandardError("ERROR: Number '%s' is not integer." % value)
    elif key in ('-o', '--output'):
        if os.path.isdir(value):
            task_set_option('output', value)
        else:
            raise StandardError("ERROR: Output '%s' is not a directory." % \
                  value)
    else:
        return False
    return True

def _dbdump_run_task_core():
    """
    Run DB dumper core stuff.

    Note: do not use task_can_sleep() stuff here because we don't want
    other tasks to interrupt us while we are dumping the DB content.
    """
    # read params:
    task_update_progress("Reading parameters")
    write_message("Reading parameters started")
    output_dir = task_get_option('output', CFG_LOGDIR)
    output_num = task_get_option('number', 5)
    output_fil_prefix = CFG_DATABASE_NAME + '-dbdump-'
    output_fil_suffix = task_get_task_param('task_starting_time').replace(' ', '_') + '.sql.gz'
    output_fil = output_fil_prefix + output_fil_suffix
    write_message("Reading parameters ended")
    # make dump:
    task_update_progress("Dumping database")
    write_message("Database dump started")
    _dump_database(output_dir, output_fil)
    write_message("Database dump ended")
    # prune old dump files:
    task_update_progress("Pruning old dump files")
    write_message("Pruning old dump files started")
    _delete_old_dumps(output_dir, output_fil_prefix, output_num)
    write_message("Pruning old dump files ended")
    # we are done:
    task_update_progress("Done.")
    return True

def main():
    """Main that construct all the bibtask."""
    task_init(authorization_action='rundbdump',
              authorization_msg="DB Dump Task Submission",
              help_specific_usage="""\
  -o, --output=DIR      Output directory. [default=%s]
  -n, --number=NUM      Keep up to NUM previous dump files. [default=5]
""" % CFG_LOGDIR,
              version=__revision__,
              specific_params=("n:o:",
                               ["number=", "output="]),
              task_submit_elaborate_specific_parameter_fnc=_dbdump_elaborate_submit_param,
              task_run_fnc=_dbdump_run_task_core)

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