<commit_before>import bot_app.settings as settings
from telegram import ParseMode

# Help messages for all the bot commands. Use the internal function names as key!
help_messages = {}
help_messages["send_message"] = "Usage of /msg:\n/msg <match-id> <message>\nYou can get the match-id by executing /matches."
help_messages["poll_messages"] = "Usage of /poll_msgs:\n/poll_msgs <match-id> <n>\nPolls the last n messages from the match. You can get the match-id by executing /matches."
help_messages["set_location"] = "Usage of /set_location:\n/set_location <latitude> <longitude>\nYou can also just use telegram to send a location to the group."
help_messages["set_setting"] = "Usage of /set_setting:\n/set_setting <setting> <value>\nCommand may only be used by account owner."

help_messages["help"] = "*Usage of the bot:*\n" \
                        "\n" \
                        "_Logging in with your Tinder account:_\n" \
                        "1. Use /set_account\n" \
                        "2. The bot will ask you for your facebook token. Just send it plain.\n" \
                        "\n" \
                        "_Searching for matches:_\n" \
                        " * Use /location to set your location.\n" \
                        " * Use /new_vote to start voting for a new stranger. Voting time can be set with /timeout.\n" \
                        " * Use /auto to toggle between automatic and manual mode. In automatic mode, a new vote will be started after the current one is finished.\n" \
                        " * Use /matches to list your matches in your private chat.\n" \
                        " * A draw is always a no.\n" \
                        "\n" \
                        "_Chatting with matches:_\n" \
                        " * Use /matches to list your matches in your private chat. Every match has an id. It can change if old matches unmatch.\n" \
                        " * Use /msg to send a message to a match, and /poll_msgs to get the chat history with a match.\n" \
                        "\n" \
                        "_Configuration:_\n" \
                        " * Use /list_settings to list all settings and their values.\n" \
                        " * Use /set_setting to change a setting.This command can only be executed by the account owner."

# All normal messages sent to the user
messages = {}
messages["welcome"] = 'Hey ! \nFirst things first, you will need to set your authentication ' \
                      'token using the /set_account command if you want to link your Tinder account.\n' \
                      'If you need help, type /help!'
messages["location_updated"] = "Location updated."
messages["setting_updated"] = "Setting updated."

# Error messages
error_messages = {}
error_messages["account_not_setup"] = "Chat not registered yet, please add token."
error_messages["unknown_match_id"] = "Unknown match-id."
error_messages["command_not_allowed"] = "This command must not be executed by this user."
error_messages["range_too_large"] = "The given range is too large. Maximum size currently allowed is 100."

### Functions for sending messages to the user ###

def debug(bot, chat_id, message):
    if settings.DEBUG_MODE:
        bot.sendMessage(chat_id, text=message)

def send_help(bot, chat_id, command, error=""):
    if command not in help_messages:
        raise Exception('Unknown command: ' + command)

    message = ""
    if error != "":
        message = "Error: " + error + "\n"

    message += help_messages[command]
    bot.sendMessage(chat_id, text=message)

def send_message(bot, chat_id, name):
    if name not in messages:
        raise Exception('Unknown message: ' + name)

    bot.sendMessage(chat_id, text=messages[name])

def send_error(bot, chat_id, name):
    if name not in error_messages:
        raise Exception('Unknown error messages: ' + name)

    bot.sendMessage(chat_id, text=error_messages[name])

def send_custom_message(bot, chat_id, message):
    bot.sendMessage(chat_id, text=message)

### Handling bot commands ###

def send_help_message(bot, update):
    send_help(bot, update.message.chat_id, "help")<commit_msg>Added documentation about ranges<commit_after>import bot_app.settings as settings
from telegram import ParseMode

# Help messages for all the bot commands. Use the internal function names as key!
help_messages = {}
help_messages["send_message"] = "Usage of /msg:\n/msg <match-id> <message>\nYou can get the match-id by executing /matches. Supports id ranges."
help_messages["poll_messages"] = "Usage of /poll_msgs:\n/poll_msgs <match-id> <n>\nPolls the last n messages from the match. You can get the match-id by executing /matches. Supports id ranges."
help_messages["set_location"] = "Usage of /set_location:\n/set_location <latitude> <longitude>\nYou can also just use telegram to send a location to the group."
help_messages["set_setting"] = "Usage of /set_setting:\n/set_setting <setting> <value>\nCommand may only be used by account owner."

help_messages["help"] = "*Usage of the bot:*\n" \
                        "\n" \
                        "_Logging in with your Tinder account:_\n" \
                        "1. Use /set_account\n" \
                        "2. The bot will ask you for your facebook token. Just send it plain.\n" \
                        "\n" \
                        "_Searching for matches:_\n" \
                        " * Use /location to set your location.\n" \
                        " * Use /new_vote to start voting for a new stranger. Voting time can be set with /timeout.\n" \
                        " * Use /auto to toggle between automatic and manual mode. In automatic mode, a new vote will be started after the current one is finished.\n" \
                        " * Use /matches to list your matches in your private chat.\n" \
                        " * A draw is always a no.\n" \
                        "\n" \
                        "_Chatting with matches:_\n" \
                        " * Use /matches to list your matches in your private chat. Every match has an id. It can change if old matches unmatch.\n" \
                        " * Use /msg to send a message to a match, and /poll_msgs to get the chat history with a match.\n" \
                        "\n" \
                        "_Configuration:_\n" \
                        " * Use /list_settings to list all settings and their values.\n" \
                        " * Use /set_setting to change a setting.This command can only be executed by the account owner.\n" \
                        "\n" \
                        "_Ranges:_\n" \
                        "Ranges are a comma-separated lists of numbers or number pairs. Number pairs are separated by a hyphen. Use no spaces in your range definition."

# All normal messages sent to the user
messages = {}
messages["welcome"] = 'Hey ! \nFirst things first, you will need to set your authentication ' \
                      'token using the /set_account command if you want to link your Tinder account.\n' \
                      'If you need help, type /help!'
messages["location_updated"] = "Location updated."
messages["setting_updated"] = "Setting updated."

# Error messages
error_messages = {}
error_messages["account_not_setup"] = "Chat not registered yet, please add token."
error_messages["unknown_match_id"] = "Unknown match-id."
error_messages["command_not_allowed"] = "This command must not be executed by this user."
error_messages["range_too_large"] = "The given range is too large. Maximum size currently allowed is 100."

### Functions for sending messages to the user ###

def debug(bot, chat_id, message):
    if settings.DEBUG_MODE:
        bot.sendMessage(chat_id, text=message)

def send_help(bot, chat_id, command, error=""):
    if command not in help_messages:
        raise Exception('Unknown command: ' + command)

    message = ""
    if error != "":
        message = "Error: " + error + "\n"

    message += help_messages[command]
    bot.sendMessage(chat_id, text=message)

def send_message(bot, chat_id, name):
    if name not in messages:
        raise Exception('Unknown message: ' + name)

    bot.sendMessage(chat_id, text=messages[name])

def send_error(bot, chat_id, name):
    if name not in error_messages:
        raise Exception('Unknown error messages: ' + name)

    bot.sendMessage(chat_id, text=error_messages[name])

def send_custom_message(bot, chat_id, message):
    bot.sendMessage(chat_id, text=message)

### Handling bot commands ###

def send_help_message(bot, update):
    send_help(bot, update.message.chat_id, "help")<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
import googlemaps
import datetime

class GoogleMapsSettings(Document):
	def validate(self):
		if self.enabled:
			if not self.client_key:
				frappe.throw(_("Client key is required"))
			if not self.home_address:
				frappe.throw(_("Home Address is required"))

	def get_client(self):
		try:
			client = googlemaps.Client(key=self.client_key)
		except Exception as e:
			frappe.throw(e.message)

		return client
<commit_msg>Check if Google Maps is enabled when trying to get the client<commit_after># -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals

import googlemaps

import frappe
from frappe import _
from frappe.model.document import Document

class GoogleMapsSettings(Document):
	def validate(self):
		if self.enabled:
			if not self.client_key:
				frappe.throw(_("Client key is required"))
			if not self.home_address:
				frappe.throw(_("Home Address is required"))

	def get_client(self):
		if not self.enabled:
			frappe.throw(_("Google Maps integration is not enabled"))

		try:
			client = googlemaps.Client(key=self.client_key)
		except Exception as e:
			frappe.throw(e.message)

		return client
<|endoftext|>


<commit_before># Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

class LogFile(object):

    def __init__(self, connection=None):
        self.connection = connection
        self.size = None
        self.logfilename = None
        self.lastwritten = None

    def __repr__(self):
        #return '(%s, %s, %s)' % (self.logfilename, self.size, self.lastwritten)
        return '%s' % (self.logfilename)
        #return ''

    def startElement(self, name, attrs, connection):
        #print "startElement : {0}".format(name)
        #print "startElement connection {0}".format(connection)
        #if name == 'DescribeDBLogFilesDetails':
        ##print name
        ##if name == 'DescribeDBLogFiles':
        #    #print "LogFile EQ : {0}".format(name)
        #    #print "Handling the self {0}".format(self)
        #    #print "values {0}".format(dir(self))
        #    #print "the name is {0}".format(self.LogFileName)
        #    #print "attrs is {0}".format(attrs)
        #    details = FileDetails(self)
        #    #print "NOW DEALINGS : {0}".format(details)
        #    #print "DescribeDBLogFilesDetails attrs {0}".format(attrs)
        #else:
            #print " ####", name, "####", attrs
        #    pass
        pass

    def endElement(self, name, value, connection):
        if name == 'LastWritten':
            self.lastwritten = value
        elif name == 'LogFileName':
            self.logfilename = value
        elif name == 'Size':
            self.size = value
        else:
            setattr(self, name, value)
        #print "{0} size is {1}, last write {2}".format(self.logfilename, self.size, self.lastwritten)
        #print "endElement :%s ----> %s" %(name, value)
        #setattr(self, name, value)
        #pass

class FileDetails(object):

    def __init__(self, connection=None):
        self.connection = connection
        self.size = None
        self.logfilename = None
        self.lastwritten = None

    def __repr__(self):
        return '"%s"' % self.logfilename

    def startElement(self, name, attrs, connection):
        pass

    def endElement(self, name, value, connection):
        #print "$$$$in place", name
        if name == 'LastWritten':
            self.lastwritten = value
        elif name == 'LogFileName':
            self.logfilename = value
        elif name == 'Size':
            self.size = value
        else:
            setattr(self, name, value)
<commit_msg>clean some codes<commit_after># Copyright (c) 2006-2009 Mitch Garnaat http://garnaat.org/
# 2014-01-15  Jumping Qu  @ BPO
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish, dis-
# tribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the fol-
# lowing conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

class LogFile(object):

    def __init__(self, connection=None):
        self.connection = connection
        self.size = None
        self.logfilename = None
        self.lastwritten = None

    def __repr__(self):
        #return '(%s, %s, %s)' % (self.logfilename, self.size, self.lastwritten)
        return '%s' % (self.logfilename)

    def startElement(self, name, attrs, connection):
        pass

    def endElement(self, name, value, connection):
        if name == 'LastWritten':
            self.lastwritten = value
        elif name == 'LogFileName':
            self.logfilename = value
        elif name == 'Size':
            self.size = value
        else:
            setattr(self, name, value)
<|endoftext|>


<commit_before>"""
Automatic builder for Sphinx based documentation sets.

MIT License. See LICENSE for more details.
Copyright (c) 2013, Jonathan Stoppani
"""

import argparse
import fnmatch
import os
import re
import subprocess
import sys
import port_for

try:
    import pty
except ImportError:
    pty = None

from livereload import Server

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

__version__ = '0.5.2'
__url__ = 'https://github.com/GaretJax/sphinx-autobuild'

DEFAULT_IGNORE_REGEX = [
    r'__pycache__/.*\.py',
    r'.*\.pyc',
]

class _WatchdogHandler(FileSystemEventHandler):

    def __init__(self, watcher, action):
        super(_WatchdogHandler, self).__init__()
        self._watcher = watcher
        self._action = action

    def on_any_event(self, event):
        if event.is_directory:
            return
        self._action(self._watcher,
                     getattr(event, 'dest_path', event.src_path))

def _set_changed(w, _):
    w.set_changed()

class LivereloadWatchdogWatcher(object):
    """
    File system watch dog.
    """
    def __init__(self):
        super(LivereloadWatchdogWatcher, self).__init__()
        self._changed = False
        # TODO: Hack.
        # Allows the LivereloadWatchdogWatcher
        # instance to set the file which was
        # modified. Used for output purposes only.
        self._action_file = None
        self._observer = Observer()
        self._observer.start()

        # Compatibility with livereload's builtin watcher

        # Accessed by LiveReloadHandler's on_message method to decide if a task
        # has to be added to watch the cwd.
        self._tasks = True

        # Accessed by LiveReloadHandler's watch_task method. When set to a
        # boolean false value, everything is reloaded in the browser ('*').
        self.filepath = None

        # Accessed by Server's serve method to set reload time to 0 in
        # LiveReloadHandler's poll_tasks method.
        self._changes = []

    def set_changed(self):
        self._changed = True

    def examine(self):
        """
        Called by LiveReloadHandler's poll_tasks method.

        If a boolean true value is returned, then the waiters (browsers) are
        reloaded.
        """
        if self._changes:
            return self._changes.pop()

        action_file = None
        if self._changed:
            self._changed = False
            action_file = self._action_file or True  # TODO: Hack (see above)
        return action_file, None

    def watch(self, path, action, _):
        """
        Called by the Server instance when a new watch task is requested.
        """
        if action is None:
            action = _set_changed
        event_handler = _WatchdogHandler(self, action)
        self._observer.schedule(event_handler, path=path, recursive=True)

    def start(self, callback):
        """
        Start the watcher running, calling callback when changes are
        observed.

        If this returns False, regular polling will be used.
        """
        return False

class SphinxBuilder(object):
    """
    Helper class to run sphinx-build command.
    """
    def __init__(self, outdir, args, ignored=None, regex_ignored=None):
        self._outdir = outdir
        self._args = args
        self._ignored = ignored or []
        self._ignored.append(outdir)
        self._regex_ignored = [re.compile(r) for r in regex_ignored or []]

    def is_ignored(self, src_path):
        path = self.get_relative_path(src_path)
        for i in self._ignored:
            if fnmatch.fnmatch(path, i):
                return True
            if src_path.startswith(i + os.sep):
                return True

        for r in self._regex_ignored:
            if r.search(src_path):
                return True

    def __call__(self, watcher, src_path):
        path = self.get_relative_path(src_path)

        if self.is_ignored(src_path):
            return

        watcher._action_file = path  # TODO: Hack (see above)

        self.build(path)

    def build(self, path):
        pre = '+--------- {0} changed '.format(path)
        sys.stdout.write('\n')
        sys.stdout.write(pre)
        sys.stdout.write('-' * (81 - len(pre)))
        sys.stdout.write('\n')

        args = ['sphinx-build'] + self._args
        if pty:
            master, slave = pty.openpty()
            stdout = os.fdopen(master)
            subprocess.Popen(args, stdout=slave)
            os.close(slave)
        else:
            stdout = subprocess.Popen(args,
                                      stdout=subprocess.PIPE,
                                      universal_newlines=True).stdout
        try:
            while 1:
                line = stdout.readline()
                if not line:
                    break
                sys.stdout.write('| ')
                sys.stdout.write(line.rstrip())
                sys.stdout.write('\n')
        except IOError:
            pass
        finally:
            if not pty:
                stdout.close()
        sys.stdout.write('+')
        sys.stdout.write('-' * 80)
        sys.stdout.write('\n\n')

    def get_relative_path(self, path):
        return os.path.relpath(path)

SPHINX_BUILD_OPTIONS = (
    ('b', 'builder'),
    ('a', None),
    ('E', None),
    ('d', 'path'),
    ('j', 'N'),

    ('c', 'path'),
    ('C', None),
    ('D', 'setting=value'),
    ('t', 'tag'),
    ('A', 'name=value'),
    ('n', None),

    ('v', None),
    ('q', None),
    ('Q', None),
    ('w', 'file'),
    ('W', None),
    ('T', None),
    ('N', None),
    ('P', None),
)

def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--port', type=int, default=8000)
    parser.add_argument('-H', '--host', type=str, default='127.0.0.1')
    parser.add_argument('-r', '--re-ignore', action='append', default=[])
    parser.add_argument('-i', '--ignore', action='append', default=[])
    parser.add_argument('-B', '--open-browser', dest='openbrowser', action='store_true', default=False)
    parser.add_argument('-s', '--delay', dest='delay', type=int, default=5)
    parser.add_argument('-z', '--watch', action='append', metavar='DIR',
                        default=[],
                        help=('Specify additional directories to watch. May be'
                              ' used multiple times.'),
                        dest='additional_watched_dirs')

    for opt, meta in SPHINX_BUILD_OPTIONS:
        if meta is None:
            parser.add_argument('-{0}'.format(opt), action='count',
                                help='See `sphinx-build -h`')
        else:
            parser.add_argument('-{0}'.format(opt), action='append',
                                metavar=meta, help='See `sphinx-build -h`')

    parser.add_argument('sourcedir')
    parser.add_argument('outdir')
    parser.add_argument('filenames', nargs='*', help='See `sphinx-build -h`')
    return parser

def main():
    parser = get_parser()
    args = parser.parse_args()

    srcdir = os.path.realpath(args.sourcedir)
    outdir = os.path.realpath(args.outdir)

    build_args = []
    for arg, meta in SPHINX_BUILD_OPTIONS:
        val = getattr(args, arg)
        if not val:
            continue
        opt = '-{0}'.format(arg)
        if meta is None:
            build_args.extend([opt] * val)
        else:
            for v in val:
                build_args.extend([opt, v])

    build_args.extend([srcdir, outdir])
    build_args.extend(args.filenames)

    ignored = args.ignore
    if args.w:  # Logfile
        ignored.append(os.path.realpath(args.w[0]))
    if args.d:  # Doctrees
        ignored.append(os.path.realpath(args.d[0]))

    if not os.path.exists(outdir):
        os.makedirs(outdir)

    re_ignore = args.re_ignore + DEFAULT_IGNORE_REGEX

    if args.port != 0:
        portn = args.port
    else:
        portn = port_for.select_random()

    builder = SphinxBuilder(outdir, build_args, ignored, re_ignore)
    server = Server(watcher=LivereloadWatchdogWatcher())

    server.watch(srcdir, builder)
    for dirpath in args.additional_watched_dirs:
        dirpath = os.path.realpath(dirpath)
        server.watch(dirpath, builder)
    server.watch(outdir)

    if args.openbrowser is True:
        server.serve(port=portn, host=args.host, root=outdir, open_url_delay=args.delay)
    else:
        server.serve(port=portn, host=args.host, root=outdir)
<commit_msg>Make PEP-8 compliant<commit_after>"""
Automatic builder for Sphinx based documentation sets.

MIT License. See LICENSE for more details.
Copyright (c) 2013, Jonathan Stoppani
"""

import argparse
import fnmatch
import os
import re
import subprocess
import sys
import port_for

try:
    import pty
except ImportError:
    pty = None

from livereload import Server

from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

__version__ = '0.5.2'
__url__ = 'https://github.com/GaretJax/sphinx-autobuild'

DEFAULT_IGNORE_REGEX = [
    r'__pycache__/.*\.py',
    r'.*\.pyc',
]

class _WatchdogHandler(FileSystemEventHandler):

    def __init__(self, watcher, action):
        super(_WatchdogHandler, self).__init__()
        self._watcher = watcher
        self._action = action

    def on_any_event(self, event):
        if event.is_directory:
            return
        self._action(self._watcher,
                     getattr(event, 'dest_path', event.src_path))

def _set_changed(w, _):
    w.set_changed()

class LivereloadWatchdogWatcher(object):
    """
    File system watch dog.
    """
    def __init__(self):
        super(LivereloadWatchdogWatcher, self).__init__()
        self._changed = False
        # TODO: Hack.
        # Allows the LivereloadWatchdogWatcher
        # instance to set the file which was
        # modified. Used for output purposes only.
        self._action_file = None
        self._observer = Observer()
        self._observer.start()

        # Compatibility with livereload's builtin watcher

        # Accessed by LiveReloadHandler's on_message method to decide if a task
        # has to be added to watch the cwd.
        self._tasks = True

        # Accessed by LiveReloadHandler's watch_task method. When set to a
        # boolean false value, everything is reloaded in the browser ('*').
        self.filepath = None

        # Accessed by Server's serve method to set reload time to 0 in
        # LiveReloadHandler's poll_tasks method.
        self._changes = []

    def set_changed(self):
        self._changed = True

    def examine(self):
        """
        Called by LiveReloadHandler's poll_tasks method.

        If a boolean true value is returned, then the waiters (browsers) are
        reloaded.
        """
        if self._changes:
            return self._changes.pop()

        action_file = None
        if self._changed:
            self._changed = False
            action_file = self._action_file or True  # TODO: Hack (see above)
        return action_file, None

    def watch(self, path, action, _):
        """
        Called by the Server instance when a new watch task is requested.
        """
        if action is None:
            action = _set_changed
        event_handler = _WatchdogHandler(self, action)
        self._observer.schedule(event_handler, path=path, recursive=True)

    def start(self, callback):
        """
        Start the watcher running, calling callback when changes are
        observed.

        If this returns False, regular polling will be used.
        """
        return False

class SphinxBuilder(object):
    """
    Helper class to run sphinx-build command.
    """
    def __init__(self, outdir, args, ignored=None, regex_ignored=None):
        self._outdir = outdir
        self._args = args
        self._ignored = ignored or []
        self._ignored.append(outdir)
        self._regex_ignored = [re.compile(r) for r in regex_ignored or []]

    def is_ignored(self, src_path):
        path = self.get_relative_path(src_path)
        for i in self._ignored:
            if fnmatch.fnmatch(path, i):
                return True
            if src_path.startswith(i + os.sep):
                return True

        for r in self._regex_ignored:
            if r.search(src_path):
                return True

    def __call__(self, watcher, src_path):
        path = self.get_relative_path(src_path)

        if self.is_ignored(src_path):
            return

        watcher._action_file = path  # TODO: Hack (see above)

        self.build(path)

    def build(self, path):
        pre = '+--------- {0} changed '.format(path)
        sys.stdout.write('\n')
        sys.stdout.write(pre)
        sys.stdout.write('-' * (81 - len(pre)))
        sys.stdout.write('\n')

        args = ['sphinx-build'] + self._args
        if pty:
            master, slave = pty.openpty()
            stdout = os.fdopen(master)
            subprocess.Popen(args, stdout=slave)
            os.close(slave)
        else:
            stdout = subprocess.Popen(args,
                                      stdout=subprocess.PIPE,
                                      universal_newlines=True).stdout
        try:
            while 1:
                line = stdout.readline()
                if not line:
                    break
                sys.stdout.write('| ')
                sys.stdout.write(line.rstrip())
                sys.stdout.write('\n')
        except IOError:
            pass
        finally:
            if not pty:
                stdout.close()
        sys.stdout.write('+')
        sys.stdout.write('-' * 80)
        sys.stdout.write('\n\n')

    def get_relative_path(self, path):
        return os.path.relpath(path)

SPHINX_BUILD_OPTIONS = (
    ('b', 'builder'),
    ('a', None),
    ('E', None),
    ('d', 'path'),
    ('j', 'N'),

    ('c', 'path'),
    ('C', None),
    ('D', 'setting=value'),
    ('t', 'tag'),
    ('A', 'name=value'),
    ('n', None),

    ('v', None),
    ('q', None),
    ('Q', None),
    ('w', 'file'),
    ('W', None),
    ('T', None),
    ('N', None),
    ('P', None),
)

def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--port', type=int, default=8000)
    parser.add_argument('-H', '--host', type=str, default='127.0.0.1')
    parser.add_argument('-r', '--re-ignore', action='append', default=[])
    parser.add_argument('-i', '--ignore', action='append', default=[])
    parser.add_argument('-B', '--open-browser', dest='openbrowser',
                        action='store_true', default=False)
    parser.add_argument('-s', '--delay', dest='delay', type=int, default=5)
    parser.add_argument('-z', '--watch', action='append', metavar='DIR',
                        default=[],
                        help=('Specify additional directories to watch. May be'
                              ' used multiple times.'),
                        dest='additional_watched_dirs')

    for opt, meta in SPHINX_BUILD_OPTIONS:
        if meta is None:
            parser.add_argument('-{0}'.format(opt), action='count',
                                help='See `sphinx-build -h`')
        else:
            parser.add_argument('-{0}'.format(opt), action='append',
                                metavar=meta, help='See `sphinx-build -h`')

    parser.add_argument('sourcedir')
    parser.add_argument('outdir')
    parser.add_argument('filenames', nargs='*', help='See `sphinx-build -h`')
    return parser

def main():
    parser = get_parser()
    args = parser.parse_args()

    srcdir = os.path.realpath(args.sourcedir)
    outdir = os.path.realpath(args.outdir)

    build_args = []
    for arg, meta in SPHINX_BUILD_OPTIONS:
        val = getattr(args, arg)
        if not val:
            continue
        opt = '-{0}'.format(arg)
        if meta is None:
            build_args.extend([opt] * val)
        else:
            for v in val:
                build_args.extend([opt, v])

    build_args.extend([srcdir, outdir])
    build_args.extend(args.filenames)

    ignored = args.ignore
    if args.w:  # Logfile
        ignored.append(os.path.realpath(args.w[0]))
    if args.d:  # Doctrees
        ignored.append(os.path.realpath(args.d[0]))

    if not os.path.exists(outdir):
        os.makedirs(outdir)

    re_ignore = args.re_ignore + DEFAULT_IGNORE_REGEX

    if args.port != 0:
        portn = args.port
    else:
        portn = port_for.select_random()

    builder = SphinxBuilder(outdir, build_args, ignored, re_ignore)
    server = Server(watcher=LivereloadWatchdogWatcher())

    server.watch(srcdir, builder)
    for dirpath in args.additional_watched_dirs:
        dirpath = os.path.realpath(dirpath)
        server.watch(dirpath, builder)
    server.watch(outdir)

    if args.openbrowser is True:
        server.serve(port=portn, host=args.host,
                     root=outdir, open_url_delay=args.delay)
    else:
        server.serve(port=portn, host=args.host, root=outdir)
<|endoftext|>


<commit_before><commit_msg>Fix mistake in improved skirmish requirements.<commit_after><|endoftext|>


<commit_before># The MIT License
#
# Copyright (c) 2008 Bob Farrell
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os.path

__version__ = 'mercurial'
package_dir = os.path.abspath(os.path.dirname(__file__))

def embed(locals_=None, args=['-i', '-q'], banner=None):
    from bpython.cli import main
    return main(args, locals_, banner)
<commit_msg>Bump version number and tag release<commit_after># The MIT License
#
# Copyright (c) 2008 Bob Farrell
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os.path

__version__ = '0.11'
package_dir = os.path.abspath(os.path.dirname(__file__))

def embed(locals_=None, args=['-i', '-q'], banner=None):
    from bpython.cli import main
    return main(args, locals_, banner)
<|endoftext|>


<commit_before>
from docutils import nodes
from docutils.parsers.rst.directives import unchanged_required

import os
import sys
import copy

from docutils.parsers import rst
import breathe.doxparsers.index
import breathe.doxparsers.compound

class ElementDescription(object):

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

    def match(self, other):
        return self.name == other.name and self.kind == other.kind

class DoxygenBase(object):

    def get_path(self):

        index_path = DoxygenBase.projects[ DoxygenBase.default_project ]

        if self.options.has_key("project"):
            try:
                index_path = DoxygenBase.projects[ self.options["project"] ]
            except KeyError, e:
                sys.stderr.write(
                        "Unable to find project '%s' in breathe_projects dictionary" % self.options["project"]
                        )

        if self.options.has_key("path"):
            index_path = self.options["path"]

        return index_path

    def get_index_object(self):

        index_path = self.get_path()
        index_file = os.path.join(index_path, "index.xml")

        return doxparsers.index.parse( index_file )

# Directives
# ----------

class DoxygenIndexDirective(rst.Directive, DoxygenBase):

    required_arguments = 0
    optional_arguments = 2
    option_spec = {
            "path" : unchanged_required,
            "project" : unchanged_required,
            }
    has_content = False

    def run(self):

        index_path = self.get_path()

        index_file = os.path.join(index_path, "index.xml")

        root_object = doxparsers.index.parse( index_file )

        return root_object.rst_nodes(index_path)

class DoxygenFunctionDirective(rst.Directive, DoxygenBase):

    required_arguments = 1
    optional_arguments = 1
    option_spec = {
            "path" : unchanged_required,
            "project" : unchanged_required,
            }
    has_content = False

    def run(self):

        function_name = self.arguments[0]

        index_path = self.get_path()
        index_file = os.path.join(index_path, "index.xml")

        root_object = doxparsers.index.parse( index_file )

        # Find function in the index file
        details = ElementDescription(name=function_name, kind="function")
        results = root_object.find_compounds_and_members( details )

        if not results:
            warning = 'doxygenfunction: Cannot find function "%s" in doxygen xml output' % function_name
            return [ nodes.warning( "", nodes.paragraph("", "", nodes.Text(warning))),
                    self.state.document.reporter.warning( warning, line=self.lineno) ]

        objects = []

        # Find functions in files suggested by index
        for entry in results:

            ref_xml_path = os.path.join( index_path, "%s.xml" % entry[0].refid )
            root_object = breathe.doxparsers.compound.parse( ref_xml_path )

            for memberdef in entry[1]:

                criteria = copy.deepcopy(details)
                criteria.refid = memberdef.refid

                objects.append(root_object.find(criteria))

        if not objects:
            warning = 'doxygenfunction: Cannot find %s in doxygen xml output' % function_name
            return [ self.state.document.reporter.warning( warning, line=self.lineno) ]

        elif len( objects ) > 1:
            warning =  'doxygenfunction: Found multiple matches for "%s" in doxygen xml output.' % function_name
            warning += '                 Please be more specific.'
            return [ self.state.document.reporter.warning( warning, line=self.lineno) ]

        return objects[0].rst_nodes()

class DoxygenStructDirective(rst.Directive, DoxygenBase):

    required_arguments = 1
    optional_arguments = 1
    option_spec = {
            "path" : unchanged_required,
            "project" : unchanged_required,
            }
    has_content = False

    def run(self):

        struct_name = self.arguments[0]
        root_object = self.get_index_object()

        # Find function in the index file
        details = ElementDescription(name=struct_name, kind="struct")
        results = root_object.find_compounds_and_members( details )

        if not results:
            warning = 'doxygenstruct: Cannot find struct "%s" in doxygen xml output' % struct_name
            return [ nodes.warning( "", nodes.paragraph("", "", nodes.Text(warning))),
                    self.state.document.reporter.warning( warning, line=self.lineno) ]

        elif len( results ) > 1:
            warning =  'doxygenstruct: Found multiple matches for "%s" in doxygen xml output.' % struct_name
            warning += '               Please be more specific.'
            return [ self.state.document.reporter.warning( warning, line=self.lineno) ]

        return results[0][0].rst_nodes(self.get_path())

class DoxygenClassDirective(rst.Directive, DoxygenBase):

    required_arguments = 1
    optional_arguments = 1
    option_spec = {
            "file" : unchanged_required,
            "project" : unchanged_required,
            }
    has_content = False

    def run(self):

        class_name = self.arguments[0]
        root_object = self.get_index_object()

        # Find function in the index file
        details = ElementDescription(name=class_name, kind="class")
        results = root_object.find_compounds_and_members( details )

        if not results:
            warning = 'doxygenclass: Cannot find class "%s" in doxygen xml output' % class_name
            return [ nodes.warning( "", nodes.paragraph("", "", nodes.Text(warning))),
                    self.state.document.reporter.warning( warning, line=self.lineno) ]

        elif len( results ) > 1:
            warning =  'doxygenclass: Found multiple matches for "%s" in doxygen xml output.' % class_name
            warning += '               Please be more specific.'
            return [ self.state.document.reporter.warning( warning, line=self.lineno) ]

        return results[0][0].rst_nodes(self.get_path())

def get_config_values(app):

    DoxygenBase.projects = app.config.breathe_projects
    DoxygenBase.default_project = app.config.breathe_default_project

# Setup
# -----

def setup(app):

    app.add_directive(
            "doxygenindex",
            DoxygenIndexDirective,
            )

    app.add_directive(
            "doxygenfunction",
            DoxygenFunctionDirective,
            )

    app.add_directive(
            "doxygenstruct",
            DoxygenStructDirective,
            )

    app.add_directive(
            "doxygenclass",
            DoxygenClassDirective,
            )

    app.add_config_value("breathe_projects", {}, True)
    app.add_config_value("breathe_default_project", "", True)

    app.connect("builder-inited", get_config_values)

<commit_msg>Generalised DoxygenStructDirective to allow DoxygenClassDirective<commit_after>
from docutils import nodes
from docutils.parsers.rst.directives import unchanged_required

import os
import sys
import copy

from docutils.parsers import rst
import breathe.doxparsers.index
import breathe.doxparsers.compound

class ElementDescription(object):

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

    def match(self, other):
        return self.name == other.name and self.kind == other.kind

class DoxygenBase(object):

    def get_path(self):

        index_path = DoxygenBase.projects[ DoxygenBase.default_project ]

        if self.options.has_key("project"):
            try:
                index_path = DoxygenBase.projects[ self.options["project"] ]
            except KeyError, e:
                sys.stderr.write(
                        "Unable to find project '%s' in breathe_projects dictionary" % self.options["project"]
                        )

        if self.options.has_key("path"):
            index_path = self.options["path"]

        return index_path

    def get_index_object(self):

        index_path = self.get_path()
        index_file = os.path.join(index_path, "index.xml")

        return doxparsers.index.parse( index_file )

# Directives
# ----------

class DoxygenIndexDirective(rst.Directive, DoxygenBase):

    required_arguments = 0
    optional_arguments = 2
    option_spec = {
            "path" : unchanged_required,
            "project" : unchanged_required,
            }
    has_content = False

    def run(self):

        index_path = self.get_path()

        index_file = os.path.join(index_path, "index.xml")

        root_object = doxparsers.index.parse( index_file )

        return root_object.rst_nodes(index_path)

class DoxygenFunctionDirective(rst.Directive, DoxygenBase):

    required_arguments = 1
    optional_arguments = 1
    option_spec = {
            "path" : unchanged_required,
            "project" : unchanged_required,
            }
    has_content = False

    def run(self):

        function_name = self.arguments[0]

        index_path = self.get_path()
        index_file = os.path.join(index_path, "index.xml")

        root_object = doxparsers.index.parse( index_file )

        # Find function in the index file
        details = ElementDescription(name=function_name, kind="function")
        results = root_object.find_compounds_and_members( details )

        if not results:
            warning = 'doxygenfunction: Cannot find function "%s" in doxygen xml output' % function_name
            return [ nodes.warning( "", nodes.paragraph("", "", nodes.Text(warning))),
                    self.state.document.reporter.warning( warning, line=self.lineno) ]

        objects = []

        # Find functions in files suggested by index
        for entry in results:

            ref_xml_path = os.path.join( index_path, "%s.xml" % entry[0].refid )
            root_object = breathe.doxparsers.compound.parse( ref_xml_path )

            for memberdef in entry[1]:

                criteria = copy.deepcopy(details)
                criteria.refid = memberdef.refid

                objects.append(root_object.find(criteria))

        if not objects:
            warning = 'doxygenfunction: Cannot find %s in doxygen xml output' % function_name
            return [ self.state.document.reporter.warning( warning, line=self.lineno) ]

        elif len( objects ) > 1:
            warning =  'doxygenfunction: Found multiple matches for "%s" in doxygen xml output.' % function_name
            warning += '                 Please be more specific.'
            return [ self.state.document.reporter.warning( warning, line=self.lineno) ]

        return objects[0].rst_nodes()

class DoxygenStructDirective(rst.Directive, DoxygenBase):

    kind = "struct"

    required_arguments = 1
    optional_arguments = 1
    option_spec = {
            "path" : unchanged_required,
            "project" : unchanged_required,
            }
    has_content = False

    def run(self):

        struct_name = self.arguments[0]
        root_object = self.get_index_object()

        # Find function in the index file
        details = ElementDescription(name=struct_name, kind=self.kind)
        results = root_object.find_compounds_and_members( details )

        if not results:
            warning = 'doxygenstruct: Cannot find %s "%s" in doxygen xml output' % ( self.kind, struct_name )
            return [ nodes.warning( "", nodes.paragraph("", "", nodes.Text(warning))),
                    self.state.document.reporter.warning( warning, line=self.lineno) ]

        elif len( results ) > 1:
            warning =  'doxygenstruct: Found multiple matches for "%s" in doxygen xml output.' % struct_name
            warning += '               Please be more specific.'
            return [ self.state.document.reporter.warning( warning, line=self.lineno) ]

        return results[0][0].rst_nodes(self.get_path())

class DoxygenClassDirective(DoxygenStructDirective):

    kind = "class"

def get_config_values(app):

    DoxygenBase.projects = app.config.breathe_projects
    DoxygenBase.default_project = app.config.breathe_default_project

# Setup
# -----

def setup(app):

    app.add_directive(
            "doxygenindex",
            DoxygenIndexDirective,
            )

    app.add_directive(
            "doxygenfunction",
            DoxygenFunctionDirective,
            )

    app.add_directive(
            "doxygenstruct",
            DoxygenStructDirective,
            )

    app.add_directive(
            "doxygenclass",
            DoxygenClassDirective,
            )

    app.add_config_value("breathe_projects", {}, True)
    app.add_config_value("breathe_default_project", "", True)

    app.connect("builder-inited", get_config_values)

<|endoftext|>


<commit_before>#
# Jasy - JavaScript Tooling Refined
# Copyright 2010 Sebastian Werner
#

import logging, re, copy, json
from jasy.parser.Node import Node
from jasy.ext import polib

__all__ = ["TranslationError", "Translation"]

class TranslationError(Exception):
    pass

class Translation:
    def __init__(self, locale, files=None, table=None):
        self.__locale = locale

        logging.debug("Initialize translation: %s" % locale)
        self.__table = {}

        if table:
            self.__table.update(table)

        if files:
            logging.debug("Load %s translation files..." % len(files))
            for path in files:
                pofile = polib.pofile(path)
                for entry in pofile:
                    if entry.msgstr != "" and not entry.msgid in self.__table:
                        self.__table[entry.msgid] = entry.msgstr

        logging.debug("Translation of %s entries ready" % len(self.__table))

    #
    # Public API
    #

    def generate(self):
        return "this.$$translation=%s;" % json.dumps(self.__generate({}), separators=(',',':'))

    def patch(self, node):
        self.__recurser(node)

    def load(self, pofile):
        pass
        # TODO

    def __str__(self):
        return "Translation(%s)" % self.__locale

    #
    # Generate :: Implementation
    #

    def __generate(self, data):
        for msgid in self.__table:
            data[msgid] = self.__table[msgid]

        return data

    #
    # Patch :: Implementation
    #

    __methods = ("tr", "trc", "trn")
    __replacer = re.compile("(%[0-9])")

    def __rebuildAsSplitted(self, value, mapper):
        """ The real splitter engine. Creates plus Node instances and cascade them automatically """

        result = []
        splits = self.__replacer.split(value)
        if len(splits) == 1:
            return None

        pair = Node(None, "plus")

        for entry in splits:
            if entry == "":
                continue

            if len(pair) == 2:
                newPair = Node(None, "plus")
                newPair.append(pair)
                pair = newPair

            if self.__replacer.match(entry):
                pos = int(entry[1]) - 1

                # Items might be added multiple times. Copy to protect original.
                try:
                    repl = mapper[pos]
                except KeyError:
                    raise TranslationError("Invalid positional value: %s in %s" % (entry, value))

                copied = copy.deepcopy(mapper[pos])
                if copied.type not in ("identifier", "call"):
                    copied.parenthesized = True
                pair.append(copied)

            else:
                child = Node(None, "string")
                child.value = entry
                pair.append(child)

        return pair

    def __splitTemplate(self, replaceNode, patchParam, valueParams):
        """ Split string into plus-expression(s) """

        mapper = { pos: value for pos, value in enumerate(valueParams) }

        try:
            pair = self.__rebuildAsSplitted(patchParam.value, mapper)
        except TranslationError as ex:
            raise TranslationError("Invalid translation usage in line %s. %s" % (replaceNode.line, ex))

        if pair:
            replaceNode.parent.replace(replaceNode, pair)

    def __recurser(self, node):
        if node.type == "call":
            funcName = None

            if node[0].type == "identifier":
                funcName = node[0].value
            elif node[0].type == "dot" and node[0][1].type == "identifier":
                funcName = node[0][1].value

            if funcName in self.__methods:
                params = node[1]
                table = self.__table

                # Verify param types
                if params[0].type != "string":
                    logging.warn("Expecting translation string to be type string: %s at line %s" % (params[0].type, params[0].line))

                if (funcName == "trn" or funcName == "trc") and params[1].type != "string":
                    logging.warn("Expecting translation string to be type string: %s at line %s" % (params[1].type, params[1].line))

                # Signature tr(msg, arg1, arg2, ...)
                if funcName == "tr":
                    key = params[0].value
                    if key in table:
                        params[0].value = table[key]

                    if len(params) == 1:
                        node.parent.replace(node, params[0])
                    else:
                        self.__splitTemplate(node, params[0], params[1:])

                # Signature trc(hint, msg, arg1, arg2, ...)
                elif funcName == "trc":
                    key = params[0].value
                    if key in table:
                        params[1].value = table[key]

                    if len(params) == 2:
                        node.parent.replace(node, params[1])
                    else:
                        self.__splitTemplate(node, params[1], params[2:])

                # Signature trn(msg, msg2, [...], int, arg1, arg2, ...)
                elif funcName == "trn":
                    keySingular = params[0].value
                    if keySingular in table:
                        params[0].value = table[keySingular]

                    keyPlural = params[1].value
                    if keyPlural in table:
                        params[1].value = table[keyPlural]

                    # TODO: Multi plural support

                    # Patch strings with dynamic values
                    if len(params) >= 3:
                        self.__splitTemplate(params[0], params[0], params[3:])
                        self.__splitTemplate(params[1], params[1], params[3:])

                    # Replace the whole call with: int < 2 ? singularMessage : pluralMessage
                    hook = Node(None, "hook")
                    hook.parenthesized = True
                    condition = Node(None, "le")
                    condition.append(params[2])
                    number = Node(None, "number")
                    number.value = 1
                    condition.append(number)

                    hook.append(condition, "condition")
                    hook.append(params[1], "elsePart")
                    hook.append(params[0], "thenPart")

                    node.parent.replace(node, hook)

        # Process children
        for child in node:
            if child != None:
                self.__recurser(child)
                <commit_msg>Fixed ugly issue in filtering routine with plural translations.<commit_after>#
# Jasy - JavaScript Tooling Refined
# Copyright 2010 Sebastian Werner
#

import logging, re, copy, json
from jasy.parser.Node import Node
from jasy.ext import polib

__all__ = ["TranslationError", "Translation"]

class TranslationError(Exception):
    pass

class Translation:
    def __init__(self, locale, files=None, table=None):
        self.__locale = locale

        logging.debug("Initialize translation: %s" % locale)
        self.__table = {}

        if table:
            self.__table.update(table)

        if files:
            logging.debug("Load %s translation files..." % len(files))
            for path in files:
                pofile = polib.pofile(path)
                print("Process: %s" % path)
                for entry in pofile:
                    if (entry.msgstr != "" or entry.msgstr_plural) and not entry.msgid in self.__table:
                        self.__table[entry.msgid] = entry.msgstr

        logging.debug("Translation of %s entries ready" % len(self.__table))

    #
    # Public API
    #

    def generate(self):
        return "this.$$translation=%s;" % json.dumps(self.__generate({}), separators=(',',':'))

    def patch(self, node):
        self.__recurser(node)

    def load(self, pofile):
        pass
        # TODO

    def __str__(self):
        return "Translation(%s)" % self.__locale

    #
    # Generate :: Implementation
    #

    def __generate(self, data):
        for msgid in self.__table:
            data[msgid] = self.__table[msgid]

        return data

    #
    # Patch :: Implementation
    #

    __methods = ("tr", "trc", "trn")
    __replacer = re.compile("(%[0-9])")

    def __rebuildAsSplitted(self, value, mapper):
        """ The real splitter engine. Creates plus Node instances and cascade them automatically """

        result = []
        splits = self.__replacer.split(value)
        if len(splits) == 1:
            return None

        pair = Node(None, "plus")

        for entry in splits:
            if entry == "":
                continue

            if len(pair) == 2:
                newPair = Node(None, "plus")
                newPair.append(pair)
                pair = newPair

            if self.__replacer.match(entry):
                pos = int(entry[1]) - 1

                # Items might be added multiple times. Copy to protect original.
                try:
                    repl = mapper[pos]
                except KeyError:
                    raise TranslationError("Invalid positional value: %s in %s" % (entry, value))

                copied = copy.deepcopy(mapper[pos])
                if copied.type not in ("identifier", "call"):
                    copied.parenthesized = True
                pair.append(copied)

            else:
                child = Node(None, "string")
                child.value = entry
                pair.append(child)

        return pair

    def __splitTemplate(self, replaceNode, patchParam, valueParams):
        """ Split string into plus-expression(s) """

        mapper = { pos: value for pos, value in enumerate(valueParams) }

        try:
            pair = self.__rebuildAsSplitted(patchParam.value, mapper)
        except TranslationError as ex:
            raise TranslationError("Invalid translation usage in line %s. %s" % (replaceNode.line, ex))

        if pair:
            replaceNode.parent.replace(replaceNode, pair)

    def __recurser(self, node):
        if node.type == "call":
            funcName = None

            if node[0].type == "identifier":
                funcName = node[0].value
            elif node[0].type == "dot" and node[0][1].type == "identifier":
                funcName = node[0][1].value

            if funcName in self.__methods:
                params = node[1]
                table = self.__table

                # Verify param types
                if params[0].type != "string":
                    logging.warn("Expecting translation string to be type string: %s at line %s" % (params[0].type, params[0].line))

                if (funcName == "trn" or funcName == "trc") and params[1].type != "string":
                    logging.warn("Expecting translation string to be type string: %s at line %s" % (params[1].type, params[1].line))

                # Signature tr(msg, arg1, arg2, ...)
                if funcName == "tr":
                    key = params[0].value
                    if key in table:
                        params[0].value = table[key]

                    if len(params) == 1:
                        node.parent.replace(node, params[0])
                    else:
                        self.__splitTemplate(node, params[0], params[1:])

                # Signature trc(hint, msg, arg1, arg2, ...)
                elif funcName == "trc":
                    key = params[0].value
                    if key in table:
                        params[1].value = table[key]

                    if len(params) == 2:
                        node.parent.replace(node, params[1])
                    else:
                        self.__splitTemplate(node, params[1], params[2:])

                # Signature trn(msg, msg2, [...], int, arg1, arg2, ...)
                elif funcName == "trn":
                    keySingular = params[0].value
                    if keySingular in table:
                        params[0].value = table[keySingular]

                    keyPlural = params[1].value
                    if keyPlural in table:
                        params[1].value = table[keyPlural]

                    # TODO: Multi plural support

                    # Patch strings with dynamic values
                    if len(params) >= 3:
                        self.__splitTemplate(params[0], params[0], params[3:])
                        self.__splitTemplate(params[1], params[1], params[3:])

                    # Replace the whole call with: int < 2 ? singularMessage : pluralMessage
                    hook = Node(None, "hook")
                    hook.parenthesized = True
                    condition = Node(None, "le")
                    condition.append(params[2])
                    number = Node(None, "number")
                    number.value = 1
                    condition.append(number)

                    hook.append(condition, "condition")
                    hook.append(params[1], "elsePart")
                    hook.append(params[0], "thenPart")

                    node.parent.replace(node, hook)

        # Process children
        for child in node:
            if child != None:
                self.__recurser(child)
                <|endoftext|>


<commit_before># stdlib
import functools

class timeoutDecorator(object):
    def __init__(self, function):
        self.function = function
        self.__doc__ = function.__doc__
        self.__name__ = function.__name__
        self.__module__ = function.__module__

    def __call__(self, *args, **kwargs):
        if 'dev_timeout' in kwargs:
            try:
                dev = args[0].dev
            except:
                dev = args[0]
            restore_timeout = dev.timeout
            dev.timeout = kwargs['dev_timeout']
            kwargs.pop('dev_timeout', None)
            try:
                result = self.function(*args, **kwargs)
                dev.timeout = restore_timeout
                return result
            except Exception:
                dev.timeout = restore_timeout
                raise
        else:
            try:
                return self.function(*args, **kwargs)
            except Exception:
                raise

    def __get__(self, obj_self, objtype):
        return functools.partial(self.__call__, obj_self)
<commit_msg>Changed timeout dec to function for autodoc support<commit_after># stdlib
from functools import wraps

def timeoutDecorator(function):
    @wraps(function)
    def wrapper(*args, **kwargs):
        if 'dev_timeout' in kwargs:
            try:
                dev = args[0].dev
            except:
                dev = args[0]
            restore_timeout = dev.timeout
            dev.timeout = kwargs['dev_timeout']
            kwargs.pop('dev_timeout', None)
            try:
                result = function(*args, **kwargs)
                dev.timeout = restore_timeout
                return result
            except Exception:
                dev.timeout = restore_timeout
                raise
        else:
            try:
                return function(*args, **kwargs)
            except Exception:
                raise

    return wrapper
<|endoftext|>


<commit_before>from time import strptime

def get_current_date():

def date_to_json(year, month, day):
    formatted =  '"year" : ' + str(year)
    formatted += ', "month" : ' + str(month)
    formatted += ', "day" : ' + str(day)
    return formatted

def time_to_json(hour, minute):
    formatted =  ', "hour" : ' + str(hour)
    formatted += ', "minute" : ' + str(minute)
    return formatted

def time_predicted(date):
    year = date[0:4]
    month = strptime(date[5:8], '%b').tm_mon # convert month to number
    day = date[9:11]
    json = '{ "time_predicted" : { ' + date_to_json(year, month, day)
    json += time_to_json(-1, -1) + '}'
    return json

def parse28(input_text):
    document = input_text.split("\n")
    # Set up array of json objects
    output_text = '[ '
    for line in document:
	# As of the project creation, all lines in the file are either comments,
	# or they start with the year. So testing for isdigit() is sufficient
	if line[0:4].isdigit():
	    json = time_predicted(line[0:11])
	    kp_value = line[-1]	# kp is all we need, and it is at the end of line.
	    json += ', "forecast" : "28day", "kp" : ' + str(kp_value) + '}, '

	    output_text += json
    # Remove the off-by-1 comma made by the loop.
    output_text = output_text[:-2]
    return output_text + ' ]'

def main():
    print parse28("2014 Feb 11    150		5	3\n2014 Feb 12	    111		5	2")

if __name__ == "__main__":
    main()
<commit_msg>get_current_time now working.<commit_after>import time	# for strptime and strftime
import datetime

def month_name_to_num(month):
     return time.strptime(month, '%b').tm_mon

def get_current_date():
    return time.strftime("%Y %m %d")

def date_to_json(year, month, day):
    format_text =  '"year" : ' + str(year)
    format_text += ', "month" : ' + str(month)
    format_text += ', "day" : ' + str(day)
    return format_text

def time_to_json(hour, minute):
    format_text =  ', "hour" : ' + str(hour)
    format_text += ', "minute" : ' + str(minute)
    return format_text

def time_predicted(date):
    year = date[0:4]
    month = month_name_to_num(date[5:8])
    day = date[9:11]
    json = '{ "time_predicted" : { ' + date_to_json(year, month, day)
    json += time_to_json(-1, -1) + '}'
    return json

def parse28(input_text):
    now = get_current_date()
    print now
    document = input_text.split("\n")
    # Set up array of json objects
    output_text = '[ '
    for line in document:
	# As of the project creation, all lines in the file are either comments,
	# or they start with the year. So testing for isdigit() is sufficient
	if line[0:4].isdigit():
	    json = time_predicted(line[0:11])
	    kp_value = line[-1]	# kp is all we need, and it is at the end of line.
	    json += ', "forecast" : "28day", "kp" : ' + str(kp_value) + '}, '

	    output_text += json
    # Remove the off-by-1 comma made by the loop.
    output_text = output_text[:-2]
    return output_text + ' ]'

def main():
    print parse28("2014 Feb 11    150		5	3\n2014 Feb 12	    111		5	2")

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


<commit_before># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

class PyScikitLearn(PythonPackage):
    """A set of python modules for machine learning and data mining."""

    homepage = "https://pypi.python.org/pypi/scikit-learn"
    url      = "https://pypi.io/packages/source/s/scikit-learn/scikit-learn-0.23.2.tar.gz"
    git      = "https://github.com/scikit-learn/scikit-learn.git"

    maintainers = ['adamjstewart']

    version('master', branch='master')
    version('0.23.2', sha256='20766f515e6cd6f954554387dfae705d93c7b544ec0e6c6a5d8e006f6f7ef480')
    version('0.23.1', sha256='e3fec1c8831f8f93ad85581ca29ca1bb88e2da377fb097cf8322aa89c21bc9b8')
    version('0.23.0', sha256='639a53df6273acc6a7510fb0c658b94e0c70bb13dafff9d14932c981ff9baff4')
    version('0.22.1', sha256='51ee25330fc244107588545c70e2f3570cfc4017cff09eed69d6e1d82a212b7d')
    version('0.22',   sha256='314abf60c073c48a1e95feaae9f3ca47a2139bd77cebb5b877c23a45c9e03012')
    version('0.21.3', sha256='eb9b8ebf59eddd8b96366428238ab27d05a19e89c5516ce294abc35cea75d003')
    version('0.21.2', sha256='0aafc312a55ebf58073151b9308761a5fcfa45b7f7730cea4b1f066f824c72db')
    version('0.21.1', sha256='228d0611e69e5250946f8cd7bbefec75347950f0ca426d0c518db8f06583f660')
    version('0.20.3', sha256='c503802a81de18b8b4d40d069f5e363795ee44b1605f38bc104160ca3bfe2c41')
    version('0.20.2', sha256='bc5bc7c7ee2572a1edcb51698a6caf11fae554194aaab9a38105d9ec419f29e6')
    version('0.20.0', sha256='97d1d971f8ec257011e64b7d655df68081dd3097322690afa1a71a1d755f8c18')
    version('0.19.1', sha256='5ca0ad32ee04abe0d4ba02c8d89d501b4e5e0304bdf4d45c2e9875a735b323a0')
    version('0.18.1', sha256='1eddfc27bb37597a5d514de1299981758e660e0af56981c0bfdf462c9568a60c')
    version('0.15.2', sha256='1a8a881f6f13edc0ac58931ce21f899eb7920af50aa08802413d1239e2aa5fa6')
    version('0.16.1', sha256='c0721e295056c95c7002e05726f2bd271a7923e88bdeab34a2b60aac2b0ee6e4')
    version('0.17.1', sha256='9f4cf58e57d81783289fc503caaed1f210bab49b7a6f680bf3c04b1e0a96e5f0')
    version('0.13.1', sha256='a6e4759a779ba792435d096c882a0d66ee29d369755c09209f1a4e50877bdc94')

    variant('openmp', default=True, description='Build with OpenMP support')

    depends_on('python@2.6:2.8,3.3:', when='@:0.19', type=('build', 'run'))
    depends_on('python@2.7:2.8,3.4:', when='@0.20.0:0.20.999', type=('build', 'run'))
    depends_on('python@3.5:', when='@0.21:', type=('build', 'run'))
    depends_on('python@3.6:', when='@0.23:', type=('build', 'run'))
    depends_on('py-numpy@1.6.1:', when='@:0.19', type=('build', 'run'))
    depends_on('py-numpy@1.8.2:', when='@0.20.0:0.20.999', type=('build', 'run'))
    depends_on('py-numpy@1.11.0:', when='@0.21:', type=('build', 'run'))
    depends_on('py-numpy@1.13.3:', when='@0.23:', type=('build', 'run'))
    depends_on('py-scipy@0.9:', when='@:0.19', type=('build', 'run'))
    depends_on('py-scipy@0.13.3:', when='@0.20.0:0.20.999', type=('build', 'run'))
    depends_on('py-scipy@0.17.0:', when='@0.21:', type=('build', 'run'))
    depends_on('py-scipy@0.19.1:', when='@0.23:', type=('build', 'run'))
    depends_on('py-joblib@0.11:', type=('build', 'run'))
    depends_on('py-threadpoolctl@2.0.0:', when='@0.23:', type=('build', 'run'))
    depends_on('py-cython@0.23:', type='build')
    depends_on('py-cython@0.28.5:', when='@0.21:', type='build')
    depends_on('py-pytest@3.3.0:', type='test')
    depends_on('py-pandas', type='test')
    depends_on('py-setuptools', type='build')
    depends_on('llvm-openmp', when='@0.21: %apple-clang +openmp')

    # Release tarballs are already cythonized. If you wanted to build a release
    # version without OpenMP support, you would need to delete all .c files
    # that include omp.h, as well as PKG-INFO.
    # See https://github.com/scikit-learn/scikit-learn/issues/14332
    conflicts('~openmp', when='@:999', msg='Only master supports ~openmp')

    def setup_build_environment(self, env):
        # https://scikit-learn.org/stable/developers/advanced_installation.html#building-from-source
        if self.spec.satisfies('~openmp'):
            env.set('SKLEARN_NO_OPENMP', 'True')
        # https://scikit-learn.org/stable/developers/advanced_installation.html#mac-osx
        elif self.spec.satisfies('@0.21: %apple-clang +openmp'):
            env.append_flags(
                'CPPFLAGS', self.compiler.openmp_flag)
            env.append_flags(
                'CFLAGS', self.spec['llvm-openmp'].headers.include_flags)
            env.append_flags(
                'CXXFLAGS', self.spec['llvm-openmp'].headers.include_flags)
            env.append_flags(
                'LDFLAGS', self.spec['llvm-openmp'].libs.ld_flags)

    @run_after('install')
    @on_package_attributes(run_tests=True)
    def install_test(self):
        # https://scikit-learn.org/stable/developers/advanced_installation.html#testing
        with working_dir('spack-test', create=True):
            pytest = which('pytest')
            pytest(join_path(self.prefix, site_packages_dir, 'sklearn'))
<commit_msg>py-scikit-learn: add v0.24.0 (#20519)<commit_after># Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

class PyScikitLearn(PythonPackage):
    """A set of python modules for machine learning and data mining."""

    homepage = "https://pypi.python.org/pypi/scikit-learn"
    url      = "https://pypi.io/packages/source/s/scikit-learn/scikit-learn-0.24.0.tar.gz"
    git      = "https://github.com/scikit-learn/scikit-learn.git"

    maintainers = ['adamjstewart']

    version('master', branch='master')
    version('0.24.0', sha256='076369634ee72b5a5941440661e2f306ff4ac30903802dc52031c7e9199ac640')
    version('0.23.2', sha256='20766f515e6cd6f954554387dfae705d93c7b544ec0e6c6a5d8e006f6f7ef480')
    version('0.23.1', sha256='e3fec1c8831f8f93ad85581ca29ca1bb88e2da377fb097cf8322aa89c21bc9b8')
    version('0.23.0', sha256='639a53df6273acc6a7510fb0c658b94e0c70bb13dafff9d14932c981ff9baff4')
    version('0.22.1', sha256='51ee25330fc244107588545c70e2f3570cfc4017cff09eed69d6e1d82a212b7d')
    version('0.22',   sha256='314abf60c073c48a1e95feaae9f3ca47a2139bd77cebb5b877c23a45c9e03012')
    version('0.21.3', sha256='eb9b8ebf59eddd8b96366428238ab27d05a19e89c5516ce294abc35cea75d003')
    version('0.21.2', sha256='0aafc312a55ebf58073151b9308761a5fcfa45b7f7730cea4b1f066f824c72db')
    version('0.21.1', sha256='228d0611e69e5250946f8cd7bbefec75347950f0ca426d0c518db8f06583f660')
    version('0.20.3', sha256='c503802a81de18b8b4d40d069f5e363795ee44b1605f38bc104160ca3bfe2c41')
    version('0.20.2', sha256='bc5bc7c7ee2572a1edcb51698a6caf11fae554194aaab9a38105d9ec419f29e6')
    version('0.20.0', sha256='97d1d971f8ec257011e64b7d655df68081dd3097322690afa1a71a1d755f8c18')
    version('0.19.1', sha256='5ca0ad32ee04abe0d4ba02c8d89d501b4e5e0304bdf4d45c2e9875a735b323a0')
    version('0.18.1', sha256='1eddfc27bb37597a5d514de1299981758e660e0af56981c0bfdf462c9568a60c')
    version('0.15.2', sha256='1a8a881f6f13edc0ac58931ce21f899eb7920af50aa08802413d1239e2aa5fa6')
    version('0.16.1', sha256='c0721e295056c95c7002e05726f2bd271a7923e88bdeab34a2b60aac2b0ee6e4')
    version('0.17.1', sha256='9f4cf58e57d81783289fc503caaed1f210bab49b7a6f680bf3c04b1e0a96e5f0')
    version('0.13.1', sha256='a6e4759a779ba792435d096c882a0d66ee29d369755c09209f1a4e50877bdc94')

    variant('openmp', default=True, description='Build with OpenMP support')

    depends_on('python@2.6:2.8,3.3:', when='@:0.19', type=('build', 'run'))
    depends_on('python@2.7:2.8,3.4:', when='@0.20.0:0.20.999', type=('build', 'run'))
    depends_on('python@3.5:', when='@0.21:', type=('build', 'run'))
    depends_on('python@3.6:', when='@0.23:', type=('build', 'run'))
    depends_on('py-numpy@1.6.1:', when='@:0.19', type=('build', 'run'))
    depends_on('py-numpy@1.8.2:', when='@0.20.0:0.20.999', type=('build', 'run'))
    depends_on('py-numpy@1.11.0:', when='@0.21:', type=('build', 'run'))
    depends_on('py-numpy@1.13.3:', when='@0.23:', type=('build', 'run'))
    depends_on('py-scipy@0.9:', when='@:0.19', type=('build', 'run'))
    depends_on('py-scipy@0.13.3:', when='@0.20.0:0.20.999', type=('build', 'run'))
    depends_on('py-scipy@0.17.0:', when='@0.21:', type=('build', 'run'))
    depends_on('py-scipy@0.19.1:', when='@0.23:', type=('build', 'run'))
    depends_on('py-joblib@0.11:', type=('build', 'run'))
    depends_on('py-threadpoolctl@2.0.0:', when='@0.23:', type=('build', 'run'))
    depends_on('py-cython@0.23:', type='build')
    depends_on('py-cython@0.28.5:', when='@0.21:', type='build')
    depends_on('py-pytest@5.0.1:', type='test')
    depends_on('py-pandas', type='test')
    depends_on('py-setuptools', type='build')
    depends_on('llvm-openmp', when='@0.21: %apple-clang +openmp')

    # Release tarballs are already cythonized. If you wanted to build a release
    # version without OpenMP support, you would need to delete all .c files
    # that include omp.h, as well as PKG-INFO.
    # See https://github.com/scikit-learn/scikit-learn/issues/14332
    conflicts('~openmp', when='@:999', msg='Only master supports ~openmp')

    def setup_build_environment(self, env):
        # https://scikit-learn.org/stable/developers/advanced_installation.html#building-from-source
        if self.spec.satisfies('~openmp'):
            env.set('SKLEARN_NO_OPENMP', 'True')
        # https://scikit-learn.org/stable/developers/advanced_installation.html#mac-osx
        elif self.spec.satisfies('@0.21: %apple-clang +openmp'):
            env.append_flags(
                'CPPFLAGS', self.compiler.openmp_flag)
            env.append_flags(
                'CFLAGS', self.spec['llvm-openmp'].headers.include_flags)
            env.append_flags(
                'CXXFLAGS', self.spec['llvm-openmp'].headers.include_flags)
            env.append_flags(
                'LDFLAGS', self.spec['llvm-openmp'].libs.ld_flags)

    @run_after('install')
    @on_package_attributes(run_tests=True)
    def install_test(self):
        # https://scikit-learn.org/stable/developers/advanced_installation.html#testing
        with working_dir('spack-test', create=True):
            pytest = which('pytest')
            pytest(join_path(self.prefix, site_packages_dir, 'sklearn'))
<|endoftext|>


<commit_before># Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function
from __future__ import absolute_import
import logging
import posixpath
import shutil
import time
import six.moves._thread  # pylint: disable=import-error

import py_utils
from py_utils import exc_util

from telemetry import decorators
from telemetry.core import debug_data
from telemetry.internal.backends.chrome import chrome_browser_backend
from telemetry.internal.backends.chrome import minidump_finder

class LacrosBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
  def __init__(self, cros_platform_backend, browser_options,
               browser_directory, profile_directory, env,
               cros_browser_backend, build_dir=None):
    """
    Args:
      cros_platform_backend: The cros_platform_backend.CrOSPlatformBackend
          instance to use.
      browser_options: The browser_options.BrowserOptions instance to use.
      browser_directory: A string containing the path to the directory on the
          device where the browser is installed.
      profile_directory: A string containing a path to the directory on the
          device to store browser profile information in.
      env: A list of strings containing environment variables to start the
          browser with.
      cros_browser_backend: The CrOs browser Lacros is running on top of.
          Some actions (e.g. Close) are further delegated to this.
      build_dir: A string containing a path to the directory on the host that
          the browser was built in, for finding debug artifacts. Can be None if
          the browser was not locally built, or the directory otherwise cannot
          be determined.
    """
    assert browser_options.IsCrosBrowserOptions()
    super().__init__(
        cros_platform_backend,
        browser_options=browser_options,
        browser_directory=browser_directory,
        profile_directory=profile_directory,
        supports_extensions=True,
        supports_tab_control=True,
        build_dir=build_dir)
    self._cri = cros_platform_backend.cri
    self._env = env
    self._devtools_client_os = None
    self._devtools_port_path = self._GetDevToolsActivePortPath()
    self._cros_browser_backend = cros_browser_backend
    self._is_browser_running = False

  @property
  def log_file_path(self):
    return None

  def _GetDevToolsActivePortPath(self):
    return '/usr/local/lacros-chrome/user_data/DevToolsActivePort'

  def _RunCommandAndLog(self, cmd):
    results = self._cri.RunCmdOnDevice(cmd)
    logging.info("stdout: " + results[0])
    logging.info("stderr: " + results[1])

  def _IsDevtoolsUp(self):
    return self._cri.FileExistsOnDevice(self._GetDevToolsActivePortPath())

  # TODO(crbug.com/1148868): Share this and others with CrOSBrowserBackend.
  def _FindDevToolsPortAndTarget(self):
    devtools_file_path = self._GetDevToolsActivePortPath()
    # GetFileContents may rise IOError or OSError, the caller will retry.
    lines = self._cri.GetFileContents(devtools_file_path).splitlines()
    if not lines:
      raise EnvironmentError('DevTools file empty')

    devtools_port = int(lines[0])
    browser_target = lines[1] if len(lines) >= 2 else None
    return devtools_port, browser_target

  def _FindUIDevtoolsPort(self):
    devtools_file_path = posixpath.join(
        '/', 'usr', 'local', 'lacros-chrome', 'user_data',
        'UIDevToolsActivePort')
    # GetFileContents may raise IOError or OSError, the caller will retry.
    lines = self._cri.GetFileContents(devtools_file_path).splitlines()
    if not lines:
      raise EnvironmentError('UIDevTools file empty')

    devtools_port = int(lines[0])
    return devtools_port

  def GetPid(self):
    return self._cri.GetChromePid()

  def _ReformatArg(self, startup_args, arg_name):
    arg_str = '--' + arg_name + '='
    for i, arg in enumerate(startup_args):
      if arg_str in arg:
        new_arg = arg
        new_arg = new_arg.replace(arg_str, arg_str + "'")
        new_arg = new_arg + "'"
        new_arg = new_arg.replace(';', '\\;')
        new_arg = new_arg.replace(',', '\\,')
        startup_args[i] = new_arg

  def _LaunchLacrosChromeHelper(self, startup_args):
    self._cri.RunCmdOnDevice(['cp', '/usr/local/lacros-chrome/chrome',
                              '/usr/local/lacros-chrome/lacros-chrome'])

    # Some args need escaping, etc.
    self._ReformatArg(startup_args, 'enable-features')
    self._ReformatArg(startup_args, 'disable-features')
    self._ReformatArg(startup_args, 'force-fieldtrials')
    self._ReformatArg(startup_args, 'force-fieldtrial-params')
    self._ReformatArg(startup_args, 'proxy-bypass-list')
    self._ReformatArg(startup_args, 'user-agent')

    def _Launch():
      # This will block until the launched browser is closed.
      self._RunCommandAndLog(
          ['EGL_PLATFORM=surfaceless',
           'XDG_RUNTIME_DIR=/run/chrome',
           'python',
           '/usr/local/bin/mojo_connection_lacros_launcher.py',
           '-s', '/tmp/lacros.sock',
           '/usr/local/lacros-chrome/lacros-chrome',
           '--ozone-platform=wayland',
           '--user-data-dir=/usr/local/lacros-chrome/user_data',
           '--enable-gpu-rasterization',
           '--enable-oop-rasterization',
           '--lang=en-US',
           '--breakpad-dump-location=/usr/local/lacros-chrome/',
           '--no-sandbox',
           '--trace-smb-size=32768'] + startup_args)
      # This will only exist if launch was successful.
      return self._IsDevtoolsUp()

    # TODO(crbug/1148534) - Launch only works sporadically.
    # This will return either when the timeout is hit or the test closes Lacros,
    # whichever is *later*
    py_utils.WaitFor(_Launch, 40)
    self._is_browser_running = False

  def LaunchLacrosChrome(self, startup_args):
    six.moves._thread.start_new_thread(
        self._LaunchLacrosChromeHelper, (startup_args,))
    py_utils.WaitFor(self._IsDevtoolsUp, 40)
    self._is_browser_running = self._IsDevtoolsUp()
    # TODO(crbug/1150455) - Find another condtion to wait on.
    time.sleep(1)
    print('Is Lacros up? ' + str(self._is_browser_running))

  def Start(self, startup_args):
    self._cri.OpenConnection()
    # Remove the stale file with the devtools port / browser target
    # prior to restarting chrome.
    self._cri.RmRF(self._GetDevToolsActivePortPath())

    self._dump_finder = minidump_finder.MinidumpFinder(
        self.browser.platform.GetOSName(), self.browser.platform.GetArchName())

    self.LaunchLacrosChrome(startup_args)
    self.BindDevToolsClient()

  def Background(self):
    raise NotImplementedError

  @exc_util.BestEffort
  def Close(self):
    super().Close()

    if self._tmp_minidump_dir:
      shutil.rmtree(self._tmp_minidump_dir, ignore_errors=True)
      self._tmp_minidump_dir = None

    # Underlying CrOS browser is responsible for closing the cri
    self._cros_browser_backend.Close()

  def IsBrowserRunning(self):
    return self._is_browser_running

  def GetStandardOutput(self):
    return 'Cannot get standard output on Lacros'

  def PullMinidumps(self):
    if self._cri:
      self._cri.PullDumps(self._tmp_minidump_dir)
    else:
      logging.error(
          'Attempted to pull minidumps without CrOSInterface. Either the '
          'browser is already closed or was never started.')

  def SymbolizeMinidump(self, minidump_path):
    return self._cros_browser_backend.SymbolizeMinidump(minidump_path)

  def _GetBrowserExecutablePath(self):
    # pylint: disable=protected-access
    return self._cros_browser_backend._GetBrowserExecutablePath()
    # pylint: enable=protected-access

  def CollectDebugData(self, log_level):
    """Collects various information that may be useful for debugging.

    Args:
      log_level: The logging level to use from the logging module, e.g.
          logging.ERROR.

    Returns:
      A debug_data.DebugData object containing the collected data.
    """
    # TODO(crbug.com/1148528): Pull Lacros data.
    return debug_data.DebugData()

  @property
  def screenshot_timeout(self):
    # Screenshots fail when the screen is off, and we can flakily attempt to
    # capture screenshots on failure when the screen is off. So, retry for a
    # while if we run into that.
    return 15

  @property
  def supports_overview_mode(self): # pylint: disable=invalid-name
    return True

  @property
  def devtools_window_manager_backend(self):
    # pylint: disable=protected-access
    return self._cros_browser_backend._devtools_client.window_manager_backend
    # pylint: enable=protected-access

  def EnterOverviewMode(self, timeout):
    self.devtools_window_manager_backend.EnterOverviewMode(timeout)

  def ExitOverviewMode(self, timeout):
    self.devtools_window_manager_backend.ExitOverviewMode(timeout)

  @property
  @decorators.Cache
  def misc_web_contents_backend(self):
    """Access to chrome://oobe/login page."""
    return self._cros_browser_backend.misc_web_contents_backend

  @property
  def oobe(self):
    return self._cros_browser_backend.misc_web_contents_backend.GetOobe()

  @property
  def oobe_exists(self):
    return self._cros_browser_backend.misc_web_contents_backend.oobe_exists
<commit_msg>Notify user of build and deploy requirements for local Lacros testing<commit_after># Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function
from __future__ import absolute_import
import logging
import posixpath
import shutil
import time
import six.moves._thread  # pylint: disable=import-error

import py_utils
from py_utils import exc_util

from telemetry import decorators
from telemetry.core import debug_data
from telemetry.internal.backends.chrome import chrome_browser_backend
from telemetry.internal.backends.chrome import minidump_finder

class LacrosBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
  def __init__(self, cros_platform_backend, browser_options,
               browser_directory, profile_directory, env,
               cros_browser_backend, build_dir=None):
    """
    Args:
      cros_platform_backend: The cros_platform_backend.CrOSPlatformBackend
          instance to use.
      browser_options: The browser_options.BrowserOptions instance to use.
      browser_directory: A string containing the path to the directory on the
          device where the browser is installed.
      profile_directory: A string containing a path to the directory on the
          device to store browser profile information in.
      env: A list of strings containing environment variables to start the
          browser with.
      cros_browser_backend: The CrOs browser Lacros is running on top of.
          Some actions (e.g. Close) are further delegated to this.
      build_dir: A string containing a path to the directory on the host that
          the browser was built in, for finding debug artifacts. Can be None if
          the browser was not locally built, or the directory otherwise cannot
          be determined.
    """
    assert browser_options.IsCrosBrowserOptions()
    super().__init__(
        cros_platform_backend,
        browser_options=browser_options,
        browser_directory=browser_directory,
        profile_directory=profile_directory,
        supports_extensions=True,
        supports_tab_control=True,
        build_dir=build_dir)
    self._cri = cros_platform_backend.cri
    self._env = env
    self._devtools_client_os = None
    self._devtools_port_path = self._GetDevToolsActivePortPath()
    self._cros_browser_backend = cros_browser_backend
    self._is_browser_running = False

  @property
  def log_file_path(self):
    return None

  def _GetDevToolsActivePortPath(self):
    return '/usr/local/lacros-chrome/user_data/DevToolsActivePort'

  def _RunCommandAndLog(self, cmd):
    results = self._cri.RunCmdOnDevice(cmd)
    logging.info("stdout: " + results[0])
    logging.info("stderr: " + results[1])

  def _IsDevtoolsUp(self):
    return self._cri.FileExistsOnDevice(self._GetDevToolsActivePortPath())

  # TODO(crbug.com/1148868): Share this and others with CrOSBrowserBackend.
  def _FindDevToolsPortAndTarget(self):
    devtools_file_path = self._GetDevToolsActivePortPath()
    # GetFileContents may rise IOError or OSError, the caller will retry.
    lines = self._cri.GetFileContents(devtools_file_path).splitlines()
    if not lines:
      raise EnvironmentError('DevTools file empty')

    devtools_port = int(lines[0])
    browser_target = lines[1] if len(lines) >= 2 else None
    return devtools_port, browser_target

  def _FindUIDevtoolsPort(self):
    devtools_file_path = posixpath.join(
        '/', 'usr', 'local', 'lacros-chrome', 'user_data',
        'UIDevToolsActivePort')
    # GetFileContents may raise IOError or OSError, the caller will retry.
    lines = self._cri.GetFileContents(devtools_file_path).splitlines()
    if not lines:
      raise EnvironmentError('UIDevTools file empty')

    devtools_port = int(lines[0])
    return devtools_port

  def GetPid(self):
    return self._cri.GetChromePid()

  def _ReformatArg(self, startup_args, arg_name):
    arg_str = '--' + arg_name + '='
    for i, arg in enumerate(startup_args):
      if arg_str in arg:
        new_arg = arg
        new_arg = new_arg.replace(arg_str, arg_str + "'")
        new_arg = new_arg + "'"
        new_arg = new_arg.replace(';', '\\;')
        new_arg = new_arg.replace(',', '\\,')
        startup_args[i] = new_arg

  def _LaunchLacrosChromeHelper(self, startup_args):
    self._cri.RunCmdOnDevice(['cp', '/usr/local/lacros-chrome/chrome',
                              '/usr/local/lacros-chrome/lacros-chrome'])

    # Some args need escaping, etc.
    self._ReformatArg(startup_args, 'enable-features')
    self._ReformatArg(startup_args, 'disable-features')
    self._ReformatArg(startup_args, 'force-fieldtrials')
    self._ReformatArg(startup_args, 'force-fieldtrial-params')
    self._ReformatArg(startup_args, 'proxy-bypass-list')
    self._ReformatArg(startup_args, 'user-agent')

    def _Launch():
      # This will block until the launched browser is closed.
      self._RunCommandAndLog(
          ['EGL_PLATFORM=surfaceless',
           'XDG_RUNTIME_DIR=/run/chrome',
           'python',
           '/usr/local/bin/mojo_connection_lacros_launcher.py',
           '-s', '/tmp/lacros.sock',
           '/usr/local/lacros-chrome/lacros-chrome',
           '--ozone-platform=wayland',
           '--user-data-dir=/usr/local/lacros-chrome/user_data',
           '--enable-gpu-rasterization',
           '--enable-oop-rasterization',
           '--lang=en-US',
           '--breakpad-dump-location=/usr/local/lacros-chrome/',
           '--no-sandbox',
           '--trace-smb-size=32768'] + startup_args)
      # This will only exist if launch was successful.
      return self._IsDevtoolsUp()

    # TODO(crbug/1148534) - Launch only works sporadically.
    # This will return either when the timeout is hit or the test closes Lacros,
    # whichever is *later*
    py_utils.WaitFor(_Launch, 40)
    self._is_browser_running = False

  def LaunchLacrosChrome(self, startup_args):
    six.moves._thread.start_new_thread(
        self._LaunchLacrosChromeHelper, (startup_args,))
    py_utils.WaitFor(self._IsDevtoolsUp, 40)
    self._is_browser_running = self._IsDevtoolsUp()
    # TODO(crbug/1150455) - Find another condtion to wait on.
    time.sleep(1)
    print('Is Lacros up? ' + str(self._is_browser_running))

  def Start(self, startup_args):
    self._cri.OpenConnection()
    # Remove the stale file with the devtools port / browser target
    # prior to restarting chrome.
    self._cri.RmRF(self._GetDevToolsActivePortPath())

    self._dump_finder = minidump_finder.MinidumpFinder(
        self.browser.platform.GetOSName(), self.browser.platform.GetArchName())

    self.LaunchLacrosChrome(startup_args)
    if not self._is_browser_running:
      raise EnvironmentError('Unable to launch Lacros. If this is a local '
       'run, did you install Lacros via deploy_chrome? If not, build and '
       'deploy Lacros by following the instructions at '
       'https://docs.google.com/document/d/1gkc_df4pv0OdVqRTz49kTkSsIybTAU_b'
       'KfjFSWNcqnk/edit#bookmark=kix.edfe7j8hizjs '
       '(Googlers only).')
    self.BindDevToolsClient()

  def Background(self):
    raise NotImplementedError

  @exc_util.BestEffort
  def Close(self):
    super().Close()

    if self._tmp_minidump_dir:
      shutil.rmtree(self._tmp_minidump_dir, ignore_errors=True)
      self._tmp_minidump_dir = None

    # Underlying CrOS browser is responsible for closing the cri
    self._cros_browser_backend.Close()

  def IsBrowserRunning(self):
    return self._is_browser_running

  def GetStandardOutput(self):
    return 'Cannot get standard output on Lacros'

  def PullMinidumps(self):
    if self._cri:
      self._cri.PullDumps(self._tmp_minidump_dir)
    else:
      logging.error(
          'Attempted to pull minidumps without CrOSInterface. Either the '
          'browser is already closed or was never started.')

  def SymbolizeMinidump(self, minidump_path):
    return self._cros_browser_backend.SymbolizeMinidump(minidump_path)

  def _GetBrowserExecutablePath(self):
    # pylint: disable=protected-access
    return self._cros_browser_backend._GetBrowserExecutablePath()
    # pylint: enable=protected-access

  def CollectDebugData(self, log_level):
    """Collects various information that may be useful for debugging.

    Args:
      log_level: The logging level to use from the logging module, e.g.
          logging.ERROR.

    Returns:
      A debug_data.DebugData object containing the collected data.
    """
    # TODO(crbug.com/1148528): Pull Lacros data.
    return debug_data.DebugData()

  @property
  def screenshot_timeout(self):
    # Screenshots fail when the screen is off, and we can flakily attempt to
    # capture screenshots on failure when the screen is off. So, retry for a
    # while if we run into that.
    return 15

  @property
  def supports_overview_mode(self): # pylint: disable=invalid-name
    return True

  @property
  def devtools_window_manager_backend(self):
    # pylint: disable=protected-access
    return self._cros_browser_backend._devtools_client.window_manager_backend
    # pylint: enable=protected-access

  def EnterOverviewMode(self, timeout):
    self.devtools_window_manager_backend.EnterOverviewMode(timeout)

  def ExitOverviewMode(self, timeout):
    self.devtools_window_manager_backend.ExitOverviewMode(timeout)

  @property
  @decorators.Cache
  def misc_web_contents_backend(self):
    """Access to chrome://oobe/login page."""
    return self._cros_browser_backend.misc_web_contents_backend

  @property
  def oobe(self):
    return self._cros_browser_backend.misc_web_contents_backend.GetOobe()

  @property
  def oobe_exists(self):
    return self._cros_browser_backend.misc_web_contents_backend.oobe_exists
<|endoftext|>