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

# Built-in Imports
import requests
from requests import Request,Session,Response
import json
import constants
import sys
import os
import auth
import utils
from resourcegroup import *
from cloudify.exceptions import NonRecoverableError,RecoverableError
from cloudify import ctx
from cloudify.decorators import operation
import auth

@operation
def creation_validation(**_):
    for property_key in constants.PUBLIC_IP_REQUIRED_PROPERTIES:
        _validate_node_properties(property_key, ctx.node.properties)

@operation
def create_public_ip(**_):
    if 'use_external_resource' in ctx.node.properties and ctx.node.properties['use_external_resource']:
        if constants.EXISTING_PUBLIC_IP_NAME in ctx.node.properties:
            existing_public_ip_name = ctx.node.properties[constants.EXISTING_PUBLIC_IP_NAME]
            if existing_public_ip_name:
                public_ip_exists = _get_public_ip_name(existing_public_ip_name)
                if not public_ip_exists:
                    raise NonRecoverableError("Public ip {} doesn't exist your Azure account".format(existing_public_ip_name))
            else:
                raise NonRecoverableError("The value of '{}' in the input, is empty".format(constants.EXISTING_PUBLIC_IP_NAME))
        else:
            raise NonRecoverableError("'{}' was specified, but '{}' doesn't exist in the input".format('use_external_resource',constants.EXISTING_PUBLIC_IP_NAME))

        ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY] = ctx.node.properties[constants.EXISTING_PUBLIC_IP_NAME]
        return

    subscription_id = ctx.node.properties['subscription_id']
    location = ctx.node.properties['location']
    resource_group_name = ctx.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    credentials = 'Bearer ' + auth.get_auth_token()
    headers = {"Content-Type": "application/json", "Authorization": credentials}

    if constants.VNET_KEY in ctx.instance.runtime_properties:
        public_ip_name = ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY]
    else:
        random_suffix_value = utils.random_suffix_generator()
        public_ip_name = constants.PUBLIC_IP_PREFIX+random_suffix_value
        ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY] = public_ip_name

    check_public_ip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/publicIPAddresses/'+public_ip_name+'?api-version='+constants.api_version
    create_public_ip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/publicIPAddresses/'+public_ip_name+'?api-version='+constants.api_version
    public_ip_params = _get_public_ip_params(location, public_ip_name)
    utils.check_or_create_resource(headers, public_ip_name, public_ip_params, check_public_ip_url, create_public_ip_url, 'public_ip')

    ctx.logger.info("{} is {}".format(constants.PUBLIC_IP_KEY, public_ip_name))

@operation
def delete_public_ip(**_):

    subscription_id = ctx.node.properties['subscription_id']
    resource_group_name = ctx.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    public_ip_name = ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY]
    credentials = 'Bearer ' + auth.get_auth_token()
    headers = {"Content-Type": "application/json", "Authorization": credentials}

    try:
        ctx.logger.info("Deleting Public IP")
        public_ip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/ publicIPAddresses/'+public_ip_name+'?api-version='+constants.api_version
        response_pip = requests.delete(url=public_ip_url,headers=headers)
        print(response_pip.text)

    except:
        ctx.logger.info("Public IP {} could not be deleted.".format(public_ip_name))

    utils.clear_runtime_properties()

@operation
def set_dependent_resources_names(azure_config, **kwargs):
    ctx.source.instance.runtime_properties[constants.RESOURCE_GROUP_KEY] = ctx.target.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    ctx.source.instance.runtime_properties[constants.STORAGE_ACCOUNT_KEY] = ctx.target.instance.runtime_properties[constants.STORAGE_ACCOUNT_KEY]
    ctx.source.instance.runtime_properties[constants.VNET_KEY] = ctx.target.instance.runtime_properties[constants.VNET_KEY]
    ctx.source.instance.runtime_properties[constants.SUBNET_KEY] = ctx.target.instance.runtime_properties[constants.SUBNET_KEY]
    ctx.logger.info("{} is {}".format(constants.VNET_KEY, ctx.target.instance.runtime_properties[constants.VNET_KEY]))

def _validate_node_properties(key, ctx_node_properties):
    if key not in ctx_node_properties:
        raise NonRecoverableError('{0} is a required input. Unable to create.'.format(key))

def _get_public_ip_name(public_ip_name):
    if constants.RESOURCE_GROUP_KEY in ctx.instance.runtime_properties:
        resource_group_name = ctx.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    else:
        raise RecoverableError("{} is not in public ip runtime_properties yet.".format(constants.RESOURCE_GROUP_KEY))
    credentials = 'Bearer ' + auth.get_auth_token()
    headers = {"Content-Type": "application/json", "Authorization": credentials}
    subscription_id = ctx.node.properties['subscription_id']
    pip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/publicIPAddresses?api-version='+constants.api_version
    response_get_pip = requests.get(url=pip_url,headers=headers)
    if public_ip_name in response_get_pip.text:
        return True
    else:
        return False

def _get_public_ip_params(location, public_ip_name):
    return json.dumps({
        "location": location,
        "name": public_ip_name,
        "properties": {
            "publicIPAllocationMethod": "Dynamic",
            "idleTimeoutInMinutes": 4,
        }
    })

<commit_msg>Added public ip<commit_after>########
# Copyright (c) 2015 GigaSpaces Technologies Ltd. All rights reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
#    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    * See the License for the specific language governing permissions and
#    * limitations under the License.

# Built-in Imports
import requests
from requests import Request,Session,Response
import json
import constants
import sys
import os
import auth
import utils
from resourcegroup import *
from cloudify.exceptions import NonRecoverableError,RecoverableError
from cloudify import ctx
from cloudify.decorators import operation
import auth

@operation
def creation_validation(**_):
    for property_key in constants.PUBLIC_IP_REQUIRED_PROPERTIES:
        _validate_node_properties(property_key, ctx.node.properties)

@operation
def create_public_ip(**_):
    if 'use_external_resource' in ctx.node.properties and ctx.node.properties['use_external_resource']:
        if constants.EXISTING_PUBLIC_IP_NAME in ctx.node.properties:
            existing_public_ip_name = ctx.node.properties[constants.EXISTING_PUBLIC_IP_NAME]
            if existing_public_ip_name:
                public_ip_exists = _get_public_ip_name(existing_public_ip_name)
                if not public_ip_exists:
                    raise NonRecoverableError("Public ip {} doesn't exist your Azure account".format(existing_public_ip_name))
            else:
                raise NonRecoverableError("The value of '{}' in the input, is empty".format(constants.EXISTING_PUBLIC_IP_NAME))
        else:
            raise NonRecoverableError("'{}' was specified, but '{}' doesn't exist in the input".format('use_external_resource',constants.EXISTING_PUBLIC_IP_NAME))

        ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY] = ctx.node.properties[constants.EXISTING_PUBLIC_IP_NAME]
        return

    subscription_id = ctx.node.properties['subscription_id']
    location = ctx.node.properties['location']
    resource_group_name = ctx.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    credentials = 'Bearer ' + auth.get_auth_token()
    headers = {"Content-Type": "application/json", "Authorization": credentials}

    if constants.PUBLIC_IP_KEY in ctx.instance.runtime_properties:
        public_ip_name = ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY]
    else:
        random_suffix_value = utils.random_suffix_generator()
        public_ip_name = constants.PUBLIC_IP_PREFIX+random_suffix_value
        ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY] = public_ip_name

    check_public_ip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/publicIPAddresses/'+public_ip_name+'?api-version='+constants.api_version
    create_public_ip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/publicIPAddresses/'+public_ip_name+'?api-version='+constants.api_version
    public_ip_params = _get_public_ip_params(location, public_ip_name)
    utils.check_or_create_resource(headers, public_ip_name, public_ip_params, check_public_ip_url, create_public_ip_url, 'public_ip')

    ctx.logger.info("{} is {}".format(constants.PUBLIC_IP_KEY, public_ip_name))

@operation
def delete_public_ip(**_):

    subscription_id = ctx.node.properties['subscription_id']
    resource_group_name = ctx.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    public_ip_name = ctx.instance.runtime_properties[constants.PUBLIC_IP_KEY]
    credentials = 'Bearer ' + auth.get_auth_token()
    headers = {"Content-Type": "application/json", "Authorization": credentials}

    try:
        ctx.logger.info("Deleting Public IP")
        public_ip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/ publicIPAddresses/'+public_ip_name+'?api-version='+constants.api_version
        response_pip = requests.delete(url=public_ip_url,headers=headers)
        print(response_pip.text)

    except:
        ctx.logger.info("Public IP {} could not be deleted.".format(public_ip_name))

    utils.clear_runtime_properties()

@operation
def set_dependent_resources_names(azure_config, **kwargs):
    ctx.source.instance.runtime_properties[constants.RESOURCE_GROUP_KEY] = ctx.target.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    ctx.source.instance.runtime_properties[constants.STORAGE_ACCOUNT_KEY] = ctx.target.instance.runtime_properties[constants.STORAGE_ACCOUNT_KEY]
    ctx.source.instance.runtime_properties[constants.VNET_KEY] = ctx.target.instance.runtime_properties[constants.VNET_KEY]
    ctx.source.instance.runtime_properties[constants.SUBNET_KEY] = ctx.target.instance.runtime_properties[constants.SUBNET_KEY]
    ctx.logger.info("{} is {}".format(constants.VNET_KEY, ctx.target.instance.runtime_properties[constants.VNET_KEY]))

def _validate_node_properties(key, ctx_node_properties):
    if key not in ctx_node_properties:
        raise NonRecoverableError('{0} is a required input. Unable to create.'.format(key))

def _get_public_ip_name(public_ip_name):
    if constants.RESOURCE_GROUP_KEY in ctx.instance.runtime_properties:
        resource_group_name = ctx.instance.runtime_properties[constants.RESOURCE_GROUP_KEY]
    else:
        raise RecoverableError("{} is not in public ip runtime_properties yet.".format(constants.RESOURCE_GROUP_KEY))
    credentials = 'Bearer ' + auth.get_auth_token()
    headers = {"Content-Type": "application/json", "Authorization": credentials}
    subscription_id = ctx.node.properties['subscription_id']
    pip_url = constants.azure_url+'/subscriptions/'+subscription_id+'/resourceGroups/'+resource_group_name+'/providers/microsoft.network/publicIPAddresses?api-version='+constants.api_version
    response_get_pip = requests.get(url=pip_url,headers=headers)
    if public_ip_name in response_get_pip.text:
        return True
    else:
        return False

def _get_public_ip_params(location, public_ip_name):
    return json.dumps({
        "location": location,
        "name": public_ip_name,
        "properties": {
            "publicIPAllocationMethod": "Dynamic",
            "idleTimeoutInMinutes": 4,
        }
    })

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright (C) 2007 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

"""Basic infrastructure for extracting localizable messages from source files.

This module defines an extensible system for collecting localizable message
strings from a variety of sources. A native extractor for Python source files
is builtin, extractors for other sources can be added using very simple plugins.

The main entry points into the extraction functionality are the functions
`extract_from_dir` and `extract_from_file`.
"""

import os
try:
    set
except NameError:
    from sets import Set as set
import sys
from tokenize import generate_tokens, NAME, OP, STRING, COMMENT

from babel.util import pathmatch, relpath

__all__ = ['extract', 'extract_from_dir', 'extract_from_file']
__docformat__ = 'restructuredtext en'

GROUP_NAME = 'babel.extractors'

DEFAULT_KEYWORDS = {
    '_': None,
    'gettext': None,
    'ngettext': (1, 2),
    'ugettext': None,
    'ungettext': (1, 2),
    'dgettext': (2,),
    'dngettext': (2, 3),
}

DEFAULT_MAPPING = [('**.py', 'python')]

def extract_from_dir(dirname=os.getcwd(), method_map=DEFAULT_MAPPING,
                     options_map=None, keywords=DEFAULT_KEYWORDS,
                     comments_tags=[], callback=None):
    """Extract messages from any source files found in the given directory.

    This function generates tuples of the form:

        ``(filename, lineno, message)``

    Which extraction method is used per file is determined by the `method_map`
    parameter, which maps extended glob patterns to extraction method names.
    For example, the following is the default mapping:

    >>> method_map = [
    ...     ('**.py', 'python')
    ... ]

    This basically says that files with the filename extension ".py" at any
    level inside the directory should be processed by the "python" extraction
    method. Files that don't match any of the mapping patterns are ignored. See
    the documentation of the `pathmatch` function for details on the pattern
    syntax.

    The following extended mapping would also use the "genshi" extraction
    method on any file in "templates" subdirectory:

    >>> method_map = [
    ...     ('**/templates/**.*', 'genshi'),
    ...     ('**.py', 'python')
    ... ]

    The dictionary provided by the optional `options_map` parameter augments
    these mappings. It uses extended glob patterns as keys, and the values are
    dictionaries mapping options names to option values (both strings).

    The glob patterns of the `options_map` do not necessarily need to be the
    same as those used in the method mapping. For example, while all files in
    the ``templates`` folders in an application may be Genshi applications, the
    options for those files may differ based on extension:

    >>> options_map = {
    ...     '**/templates/**.txt': {
    ...         'template_class': 'genshi.template.text.TextTemplate',
    ...         'encoding': 'latin-1'
    ...     },
    ...     '**/templates/**.html': {
    ...         'include_attrs': ''
    ...     }
    ... }

    :param dirname: the path to the directory to extract messages from
    :param method_map: a list of ``(pattern, method)`` tuples that maps of
                       extraction method names to extended glob patterns
    :param options_map: a dictionary of additional options (optional)
    :param keywords: a dictionary mapping keywords (i.e. names of functions
                     that should be recognized as translation functions) to
                     tuples that specify which of their arguments contain
                     localizable strings
    :param callback: a function that is called for every file that message are
                     extracted from, just before the extraction itself is
                     performed; the function is passed the filename, the name
                     of the extraction method and and the options dictionary as
                     positional arguments, in that order
    :return: an iterator over ``(filename, lineno, funcname, message)`` tuples
    :rtype: ``iterator``
    :see: `pathmatch`
    """
    if options_map is None:
        options_map = {}

    absname = os.path.abspath(dirname)
    for root, dirnames, filenames in os.walk(absname):
        for subdir in dirnames:
            if subdir.startswith('.') or subdir.startswith('_'):
                dirnames.remove(subdir)
        for filename in filenames:
            filename = relpath(
                os.path.join(root, filename).replace(os.sep, '/'),
                dirname
            )
            for pattern, method in method_map:
                if pathmatch(pattern, filename):
                    filepath = os.path.join(absname, filename)
                    options = {}
                    for opattern, odict in options_map.items():
                        if pathmatch(opattern, filename):
                            options = odict
                    if callback:
                        callback(filename, method, options)
                    for lineno, message, comments in \
                                  extract_from_file(method, filepath,
                                                    keywords=keywords,
                                                    comments_tags=comments_tags,
                                                    options=options):
                        yield filename, lineno, message, comments
                    break

def extract_from_file(method, filename, keywords=DEFAULT_KEYWORDS,
                      comments_tags=[], options=None):
    """Extract messages from a specific file.

    This function returns a list of tuples of the form:

        ``(lineno, funcname, message)``

    :param filename: the path to the file to extract messages from
    :param method: a string specifying the extraction method (.e.g. "python")
    :param keywords: a dictionary mapping keywords (i.e. names of functions
                     that should be recognized as translation functions) to
                     tuples that specify which of their arguments contain
                     localizable strings
    :param options: a dictionary of additional options (optional)
    :return: the list of extracted messages
    :rtype: `list`
    """
    fileobj = open(filename, 'U')
    try:
        return list(extract(method, fileobj, keywords,
                            comments_tags=comments_tags, options=options))
    finally:
        fileobj.close()

def extract(method, fileobj, keywords=DEFAULT_KEYWORDS, comments_tags=[],
            options=None):
    """Extract messages from the given file-like object using the specified
    extraction method.

    This function returns a list of tuples of the form:

        ``(lineno, message, comments)``

    The implementation dispatches the actual extraction to plugins, based on the
    value of the ``method`` parameter.

    >>> source = '''# foo module
    ... def run(argv):
    ...    print _('Hello, world!')
    ... '''

    >>> from StringIO import StringIO
    >>> for message in extract('python', StringIO(source)):
    ...     print message
    (3, 'Hello, world!', [])

    :param method: a string specifying the extraction method (.e.g. "python")
    :param fileobj: the file-like object the messages should be extracted from
    :param keywords: a dictionary mapping keywords (i.e. names of functions
                     that should be recognized as translation functions) to
                     tuples that specify which of their arguments contain
                     localizable strings
    :param comments_tags: a list of translator tags to search for and include in
                          output
    :param options: a dictionary of additional options (optional)
    :return: the list of extracted messages
    :rtype: `list`
    :raise ValueError: if the extraction method is not registered
    """
    from pkg_resources import working_set

    for entry_point in working_set.iter_entry_points(GROUP_NAME, method):
        func = entry_point.load(require=True)
        m = []
        for lineno, funcname, messages, comments in \
                                               func(fileobj,
                                                    keywords.keys(),
                                                    comments_tags=comments_tags,
                                                    options=options or {}):
            if isinstance(messages, (list, tuple)):
                msgs = []
                for index in keywords[funcname]:
                    msgs.append(messages[index - 1])
                messages = tuple(msgs)
                if len(messages) == 1:
                    messages = messages[0]
            yield lineno, messages, comments
        return

    raise ValueError('Unknown extraction method %r' % method)

def extract_nothing(fileobj, keywords, comments_tags, options):
    """Pseudo extractor that does not actually extract anything, but simply
    returns an empty list.
    """
    return []

def extract_genshi(fileobj, keywords, comments_tags, options):
    """Extract messages from Genshi templates.

    :param fileobj: the file-like object the messages should be extracted from
    :param keywords: a list of keywords (i.e. function names) that should be
                     recognized as translation functions
    :param comments_tags: a list of translator tags to search for and include in
                          output
    :param options: a dictionary of additional options (optional)
    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples
    :rtype: ``iterator``
    """
    from genshi.filters.i18n import Translator
    from genshi.template import MarkupTemplate

    template_class = options.get('template_class', MarkupTemplate)
    if isinstance(template_class, basestring):
        module, clsname = template_class.split(':', 1)
        template_class = getattr(__import__(module, {}, {}, [clsname]), clsname)
    encoding = options.get('encoding', None)

    ignore_tags = options.get('ignore_tags', Translator.IGNORE_TAGS)
    if isinstance(ignore_tags, basestring):
        ignore_tags = ignore_tags.split()
    include_attrs = options.get('include_attrs', Translator.INCLUDE_ATTRS)
    if isinstance(include_attrs, basestring):
        include_attrs = include_attrs.split()

    tmpl = template_class(fileobj, filename=getattr(fileobj, 'name'),
                          encoding=encoding)
    translator = Translator(None, ignore_tags, include_attrs)
    for lineno, func, message in translator.extract(tmpl.stream,
                                                    gettext_functions=keywords):
        yield lineno, func, message, []

def extract_python(fileobj, keywords, comments_tags, options):
    """Extract messages from Python source code.

    :param fileobj: the file-like object the messages should be extracted from
    :param keywords: a list of keywords (i.e. function names) that should be
                     recognized as translation functions
    :param comments_tags: a list of translator tags to search for and include in
                          output
    :param options: a dictionary of additional options (optional)
    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples
    :rtype: ``iterator``
    """
    funcname = None
    lineno = None
    buf = []
    messages = []
    translator_comments = []
    in_args = False
    in_translator_comments = False

    tokens = generate_tokens(fileobj.readline)
    for tok, value, (lineno, _), _, _ in tokens:
        if funcname and tok == OP and value == '(':
            in_args = True
        elif tok == COMMENT:
            if in_translator_comments is True:
                translator_comments.append(value[1:].strip())
                continue
            for comments_tag in comments_tags:
                if comments_tag in value:
                    if in_translator_comments is not True:
                        in_translator_comments = True
                    translator_comments.append(value[1:].strip())
        elif funcname and in_args:
            if tok == OP and value == ')':
                in_args = in_translator_comments = False
                if buf:
                    messages.append(''.join(buf))
                    del buf[:]
                if filter(None, messages):
                    if len(messages) > 1:
                        messages = tuple(messages)
                    else:
                        messages = messages[0]
                    yield lineno, funcname, messages, translator_comments
                funcname = lineno = None
                messages = []
                translator_comments = []
            elif tok == STRING:
                if lineno is None:
                    lineno = stup[0]
                # Unwrap quotes in a safe manner
                buf.append(eval(value, {'__builtins__':{}}, {}))
            elif tok == OP and value == ',':
                messages.append(''.join(buf))
                del buf[:]
        elif funcname:
            funcname = None
        elif tok == NAME and value in keywords:
            funcname = value
<commit_msg>Missed some param's documentation regarding translator comments.<commit_after># -*- coding: utf-8 -*-
#
# Copyright (C) 2007 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

"""Basic infrastructure for extracting localizable messages from source files.

This module defines an extensible system for collecting localizable message
strings from a variety of sources. A native extractor for Python source files
is builtin, extractors for other sources can be added using very simple plugins.

The main entry points into the extraction functionality are the functions
`extract_from_dir` and `extract_from_file`.
"""

import os
try:
    set
except NameError:
    from sets import Set as set
import sys
from tokenize import generate_tokens, NAME, OP, STRING, COMMENT

from babel.util import pathmatch, relpath

__all__ = ['extract', 'extract_from_dir', 'extract_from_file']
__docformat__ = 'restructuredtext en'

GROUP_NAME = 'babel.extractors'

DEFAULT_KEYWORDS = {
    '_': None,
    'gettext': None,
    'ngettext': (1, 2),
    'ugettext': None,
    'ungettext': (1, 2),
    'dgettext': (2,),
    'dngettext': (2, 3),
}

DEFAULT_MAPPING = [('**.py', 'python')]

def extract_from_dir(dirname=os.getcwd(), method_map=DEFAULT_MAPPING,
                     options_map=None, keywords=DEFAULT_KEYWORDS,
                     comments_tags=[], callback=None):
    """Extract messages from any source files found in the given directory.

    This function generates tuples of the form:

        ``(filename, lineno, message, comments)``

    Which extraction method is used per file is determined by the `method_map`
    parameter, which maps extended glob patterns to extraction method names.
    For example, the following is the default mapping:

    >>> method_map = [
    ...     ('**.py', 'python')
    ... ]

    This basically says that files with the filename extension ".py" at any
    level inside the directory should be processed by the "python" extraction
    method. Files that don't match any of the mapping patterns are ignored. See
    the documentation of the `pathmatch` function for details on the pattern
    syntax.

    The following extended mapping would also use the "genshi" extraction
    method on any file in "templates" subdirectory:

    >>> method_map = [
    ...     ('**/templates/**.*', 'genshi'),
    ...     ('**.py', 'python')
    ... ]

    The dictionary provided by the optional `options_map` parameter augments
    these mappings. It uses extended glob patterns as keys, and the values are
    dictionaries mapping options names to option values (both strings).

    The glob patterns of the `options_map` do not necessarily need to be the
    same as those used in the method mapping. For example, while all files in
    the ``templates`` folders in an application may be Genshi applications, the
    options for those files may differ based on extension:

    >>> options_map = {
    ...     '**/templates/**.txt': {
    ...         'template_class': 'genshi.template.text.TextTemplate',
    ...         'encoding': 'latin-1'
    ...     },
    ...     '**/templates/**.html': {
    ...         'include_attrs': ''
    ...     }
    ... }

    :param dirname: the path to the directory to extract messages from
    :param method_map: a list of ``(pattern, method)`` tuples that maps of
                       extraction method names to extended glob patterns
    :param options_map: a dictionary of additional options (optional)
    :param keywords: a dictionary mapping keywords (i.e. names of functions
                     that should be recognized as translation functions) to
                     tuples that specify which of their arguments contain
                     localizable strings
    :param comments_tags: a list of translator tags to search for and include
                          in output
    :param callback: a function that is called for every file that message are
                     extracted from, just before the extraction itself is
                     performed; the function is passed the filename, the name
                     of the extraction method and and the options dictionary as
                     positional arguments, in that order
    :return: an iterator over ``(filename, lineno, funcname, message)`` tuples
    :rtype: ``iterator``
    :see: `pathmatch`
    """
    if options_map is None:
        options_map = {}

    absname = os.path.abspath(dirname)
    for root, dirnames, filenames in os.walk(absname):
        for subdir in dirnames:
            if subdir.startswith('.') or subdir.startswith('_'):
                dirnames.remove(subdir)
        for filename in filenames:
            filename = relpath(
                os.path.join(root, filename).replace(os.sep, '/'),
                dirname
            )
            for pattern, method in method_map:
                if pathmatch(pattern, filename):
                    filepath = os.path.join(absname, filename)
                    options = {}
                    for opattern, odict in options_map.items():
                        if pathmatch(opattern, filename):
                            options = odict
                    if callback:
                        callback(filename, method, options)
                    for lineno, message, comments in \
                                  extract_from_file(method, filepath,
                                                    keywords=keywords,
                                                    comments_tags=comments_tags,
                                                    options=options):
                        yield filename, lineno, message, comments
                    break

def extract_from_file(method, filename, keywords=DEFAULT_KEYWORDS,
                      comments_tags=[], options=None):
    """Extract messages from a specific file.

    This function returns a list of tuples of the form:

        ``(lineno, funcname, message)``

    :param filename: the path to the file to extract messages from
    :param method: a string specifying the extraction method (.e.g. "python")
    :param keywords: a dictionary mapping keywords (i.e. names of functions
                     that should be recognized as translation functions) to
                     tuples that specify which of their arguments contain
                     localizable strings
    :param comments_tags: a list of translator tags to search for and include
                          in output
    :param options: a dictionary of additional options (optional)
    :return: the list of extracted messages
    :rtype: `list`
    """
    fileobj = open(filename, 'U')
    try:
        return list(extract(method, fileobj, keywords,
                            comments_tags=comments_tags, options=options))
    finally:
        fileobj.close()

def extract(method, fileobj, keywords=DEFAULT_KEYWORDS, comments_tags=[],
            options=None):
    """Extract messages from the given file-like object using the specified
    extraction method.

    This function returns a list of tuples of the form:

        ``(lineno, message, comments)``

    The implementation dispatches the actual extraction to plugins, based on the
    value of the ``method`` parameter.

    >>> source = '''# foo module
    ... def run(argv):
    ...    print _('Hello, world!')
    ... '''

    >>> from StringIO import StringIO
    >>> for message in extract('python', StringIO(source)):
    ...     print message
    (3, 'Hello, world!', [])

    :param method: a string specifying the extraction method (.e.g. "python")
    :param fileobj: the file-like object the messages should be extracted from
    :param keywords: a dictionary mapping keywords (i.e. names of functions
                     that should be recognized as translation functions) to
                     tuples that specify which of their arguments contain
                     localizable strings
    :param comments_tags: a list of translator tags to search for and include
                          in output
    :param options: a dictionary of additional options (optional)
    :return: the list of extracted messages
    :rtype: `list`
    :raise ValueError: if the extraction method is not registered
    """
    from pkg_resources import working_set

    for entry_point in working_set.iter_entry_points(GROUP_NAME, method):
        func = entry_point.load(require=True)
        m = []
        for lineno, funcname, messages, comments in \
                                               func(fileobj,
                                                    keywords.keys(),
                                                    comments_tags=comments_tags,
                                                    options=options or {}):
            if isinstance(messages, (list, tuple)):
                msgs = []
                for index in keywords[funcname]:
                    msgs.append(messages[index - 1])
                messages = tuple(msgs)
                if len(messages) == 1:
                    messages = messages[0]
            yield lineno, messages, comments
        return

    raise ValueError('Unknown extraction method %r' % method)

def extract_nothing(fileobj, keywords, comments_tags, options):
    """Pseudo extractor that does not actually extract anything, but simply
    returns an empty list.
    """
    return []

def extract_genshi(fileobj, keywords, comments_tags, options):
    """Extract messages from Genshi templates.

    :param fileobj: the file-like object the messages should be extracted from
    :param keywords: a list of keywords (i.e. function names) that should be
                     recognized as translation functions
    :param comments_tags: a list of translator tags to search for and include
                          in output
    :param options: a dictionary of additional options (optional)
    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples
    :rtype: ``iterator``
    """
    from genshi.filters.i18n import Translator
    from genshi.template import MarkupTemplate

    template_class = options.get('template_class', MarkupTemplate)
    if isinstance(template_class, basestring):
        module, clsname = template_class.split(':', 1)
        template_class = getattr(__import__(module, {}, {}, [clsname]), clsname)
    encoding = options.get('encoding', None)

    ignore_tags = options.get('ignore_tags', Translator.IGNORE_TAGS)
    if isinstance(ignore_tags, basestring):
        ignore_tags = ignore_tags.split()
    include_attrs = options.get('include_attrs', Translator.INCLUDE_ATTRS)
    if isinstance(include_attrs, basestring):
        include_attrs = include_attrs.split()

    tmpl = template_class(fileobj, filename=getattr(fileobj, 'name'),
                          encoding=encoding)
    translator = Translator(None, ignore_tags, include_attrs)
    for lineno, func, message in translator.extract(tmpl.stream,
                                                    gettext_functions=keywords):
        yield lineno, func, message, []

def extract_python(fileobj, keywords, comments_tags, options):
    """Extract messages from Python source code.

    :param fileobj: the file-like object the messages should be extracted from
    :param keywords: a list of keywords (i.e. function names) that should be
                     recognized as translation functions
    :param comments_tags: a list of translator tags to search for and include
                          in output
    :param options: a dictionary of additional options (optional)
    :return: an iterator over ``(lineno, funcname, message, comments)`` tuples
    :rtype: ``iterator``
    """
    funcname = None
    lineno = None
    buf = []
    messages = []
    translator_comments = []
    in_args = False
    in_translator_comments = False

    tokens = generate_tokens(fileobj.readline)
    for tok, value, (lineno, _), _, _ in tokens:
        if funcname and tok == OP and value == '(':
            in_args = True
        elif tok == COMMENT:
            if in_translator_comments is True:
                translator_comments.append(value[1:].strip())
                continue
            for comments_tag in comments_tags:
                if comments_tag in value:
                    if in_translator_comments is not True:
                        in_translator_comments = True
                    translator_comments.append(value[1:].strip())
        elif funcname and in_args:
            if tok == OP and value == ')':
                in_args = in_translator_comments = False
                if buf:
                    messages.append(''.join(buf))
                    del buf[:]
                if filter(None, messages):
                    if len(messages) > 1:
                        messages = tuple(messages)
                    else:
                        messages = messages[0]
                    yield lineno, funcname, messages, translator_comments
                funcname = lineno = None
                messages = []
                translator_comments = []
            elif tok == STRING:
                if lineno is None:
                    lineno = stup[0]
                # Unwrap quotes in a safe manner
                buf.append(eval(value, {'__builtins__':{}}, {}))
            elif tok == OP and value == ',':
                messages.append(''.join(buf))
                del buf[:]
        elif funcname:
            funcname = None
        elif tok == NAME and value in keywords:
            funcname = value
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright (C) 2007 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

"""Plural form definitions."""

PLURALS = {
    # Afrikaans - From Pootle's PO's
    'af': (2, '(n != 1)'),
    # Arabic - From Pootle's PO's
    'ar': (6, '(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n>=3 && n<=10 ? 3 : n>=11 && n<=99 ? 4 : 5)'),
    # Bulgarian - From Pootle's PO's
    'bg': (2, '(n != 1)'),
    # Bengali - From Pootle's PO's
    'bn': (2, '(n != 1)'),
    # Catalan - From Pootle's PO's
    'ca': (2, '(n != 1)'),
    # Czech
    'cs': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Danish
    'da': (2, '(n != 1)'),
    # German
    'de': (2, '(n != 1)'),
    # Greek
    'el': (2, '(n != 1)'),
    # English
    'en': (2, '(n != 1)'),
    # Esperanto
    'eo': (2, '(n != 1)'),
    # Spanish
    'es': (2, '(n != 1)'),
    # Estonian
    'et': (2, '(n != 1)'),
    # Basque - From Pootle's PO's
    'eu': (2, '(n != 1)'),
    # Persian - From Pootle's PO's
    'fa': (1, '0'),
    # Finnish
    'fi': (2, '(n != 1)'),
    # French
    'fr': (2, '(n > 1)'),
    # Furlan - From Pootle's PO's
    'fur': (2, '(n > 1)'),
    # Irish
    'ga': (3, 'n==1 ? 0 : n==2 ? 1 : 2'),
    # Galego - From Pootle's PO's
    'gl': (2, '(n != 1)'),
    # Hausa - From Pootle's PO's
    'ha': (2, '(n != 1)'),
    # Hebrew
    'he': (2, '(n != 1)'),
    # Hindi - From Pootle's PO's
    'hi': (2, '(n != 1)'),
    # Croatian
    'hr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Hungarian
    'hu': (1, '0'),
    # Armenian - From Pootle's PO's
    'hy': (1, '0'),
    # Icelandic - From Pootle's PO's
    'is': (2, '(n != 1)'),
    # Italian
    'it': (2, '(n != 1)'),
    # Japanese
    'ja': (1, '0'),
    # Georgian - From Pootle's PO's
    'ka': (1, '0'),
    # Kongo - From Pootle's PO's
    'kg': (2, '(n != 1)'),
    # Khmer - From Pootle's PO's
    'km': (1, '0'),
    # Korean
    'ko': (1, '0'),
    # Kurdî - From Pootle's PO's
    'ku': (2, '(n != 1)'),
    # Lithuanian
    'lt': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Latvian
    'lv': (3, '(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)'),
    # Maltese - From Pootle's PO's
    'mt': (4, '(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)'),
    # Norwegian Bokmal
    'nb': (2, '(n != 1)'),
    # Dutch
    'nl': (2, '(n != 1)'),
    # Norwegian Nynorsk
    'nn': (2, '(n != 1)'),
    # Norwegian
    'no': (2, '(n != 1)'),
    # Punjabi - From Pootle's PO's
    'pa': (2, '(n != 1)'),
    # Polish
    'pl': (3, '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Portuguese
    'pt': (2, '(n != 1)'),
    # Brazilian
    'pt_BR': (2, '(n > 1)'),
    # Romanian - From Pootle's PO's
    'ro': (3, '(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2)'),
    # Russian
    'ru': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Slovak
    'sk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Slovenian
    'sl': (4, '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)'),
    # Serbian - From Pootle's PO's
    'sr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10< =4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Sesotho - From Pootle's PO's
    'st': (2, '(n != 1)'),
    # Swedish
    'sv': (2, '(n != 1)'),
    # Turkish
    'tr': (1, '0'),
    # Ukrainian
    'uk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Venda - From Pootle's PO's
    've': (2, '(n != 1)'),
    # Vietnamese - From Pootle's PO's
    'vi': (1, '0'),
    # Xhosa - From Pootle's PO's
    'xh': (2, '(n != 1)'),
    # Chinese - From Pootle's PO's
    'zh_CN': (1, '0'),
    'zh_HK': (1, '0'),
    'zh_TW': (1, '0'),
}
<commit_msg>Add a plurals definition for Thai.<commit_after># -*- coding: utf-8 -*-
#
# Copyright (C) 2007 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://babel.edgewall.org/wiki/License.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://babel.edgewall.org/log/.

"""Plural form definitions."""

PLURALS = {
    # Afrikaans - From Pootle's PO's
    'af': (2, '(n != 1)'),
    # Arabic - From Pootle's PO's
    'ar': (6, '(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n>=3 && n<=10 ? 3 : n>=11 && n<=99 ? 4 : 5)'),
    # Bulgarian - From Pootle's PO's
    'bg': (2, '(n != 1)'),
    # Bengali - From Pootle's PO's
    'bn': (2, '(n != 1)'),
    # Catalan - From Pootle's PO's
    'ca': (2, '(n != 1)'),
    # Czech
    'cs': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Danish
    'da': (2, '(n != 1)'),
    # German
    'de': (2, '(n != 1)'),
    # Greek
    'el': (2, '(n != 1)'),
    # English
    'en': (2, '(n != 1)'),
    # Esperanto
    'eo': (2, '(n != 1)'),
    # Spanish
    'es': (2, '(n != 1)'),
    # Estonian
    'et': (2, '(n != 1)'),
    # Basque - From Pootle's PO's
    'eu': (2, '(n != 1)'),
    # Persian - From Pootle's PO's
    'fa': (1, '0'),
    # Finnish
    'fi': (2, '(n != 1)'),
    # French
    'fr': (2, '(n > 1)'),
    # Furlan - From Pootle's PO's
    'fur': (2, '(n > 1)'),
    # Irish
    'ga': (3, 'n==1 ? 0 : n==2 ? 1 : 2'),
    # Galego - From Pootle's PO's
    'gl': (2, '(n != 1)'),
    # Hausa - From Pootle's PO's
    'ha': (2, '(n != 1)'),
    # Hebrew
    'he': (2, '(n != 1)'),
    # Hindi - From Pootle's PO's
    'hi': (2, '(n != 1)'),
    # Croatian
    'hr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Hungarian
    'hu': (1, '0'),
    # Armenian - From Pootle's PO's
    'hy': (1, '0'),
    # Icelandic - From Pootle's PO's
    'is': (2, '(n != 1)'),
    # Italian
    'it': (2, '(n != 1)'),
    # Japanese
    'ja': (1, '0'),
    # Georgian - From Pootle's PO's
    'ka': (1, '0'),
    # Kongo - From Pootle's PO's
    'kg': (2, '(n != 1)'),
    # Khmer - From Pootle's PO's
    'km': (1, '0'),
    # Korean
    'ko': (1, '0'),
    # Kurdî - From Pootle's PO's
    'ku': (2, '(n != 1)'),
    # Lithuanian
    'lt': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Latvian
    'lv': (3, '(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)'),
    # Maltese - From Pootle's PO's
    'mt': (4, '(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3)'),
    # Norwegian Bokmal
    'nb': (2, '(n != 1)'),
    # Dutch
    'nl': (2, '(n != 1)'),
    # Norwegian Nynorsk
    'nn': (2, '(n != 1)'),
    # Norwegian
    'no': (2, '(n != 1)'),
    # Punjabi - From Pootle's PO's
    'pa': (2, '(n != 1)'),
    # Polish
    'pl': (3, '(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Portuguese
    'pt': (2, '(n != 1)'),
    # Brazilian
    'pt_BR': (2, '(n > 1)'),
    # Romanian - From Pootle's PO's
    'ro': (3, '(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2)'),
    # Russian
    'ru': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Slovak
    'sk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Slovenian
    'sl': (4, '(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3)'),
    # Serbian - From Pootle's PO's
    'sr': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10< =4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Sesotho - From Pootle's PO's
    'st': (2, '(n != 1)'),
    # Swedish
    'sv': (2, '(n != 1)'),
    # Thai
    'th': (1, '0'),
    # Turkish
    'tr': (1, '0'),
    # Ukrainian
    'uk': (3, '(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)'),
    # Venda - From Pootle's PO's
    've': (2, '(n != 1)'),
    # Vietnamese - From Pootle's PO's
    'vi': (1, '0'),
    # Xhosa - From Pootle's PO's
    'xh': (2, '(n != 1)'),
    # Chinese - From Pootle's PO's
    'zh_CN': (1, '0'),
    'zh_HK': (1, '0'),
    'zh_TW': (1, '0'),
}
<|endoftext|>


<commit_before># Time:  O(n)
# Space: O(1)
#
# Given a binary tree, return the preorder traversal of its nodes' values.
#
# For example:
# Given binary tree {1,#,2,3},
#    1
#     \
#      2
#     /
#    3
# return [1,2,3].
#
# Note: Recursive solution is trivial, could you do it iteratively?
#

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

# Morris Traversal Solution
class Solution(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result, prev, cur = [], None, root
        while cur:
            if cur.left is None:
                result.append(cur.val)
                prev = cur
                cur = cur.right
            else:
                node = cur.left
                while node.right and node.right != cur:
                    node = node.right

                if node.right is None:
                    result.append(cur.val)
                    node.right = cur
                    prev =cur
                    cur = cur.left
                else:
                    node.right = None
                    cur = cur.right

        return result

# Time:  O(n)
# Space: O(h)
# Stack Solution
class Solution2(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result, stack = [], [(root, False)]
        while stack:
            root, is_visited = stack.pop()
            if root is None:
                continue
            if is_visited:
                result.append(root.val)
            else:
                stack.append((root.right, False))
                stack.append((root.left, False))
                stack.append((root, True))
        return result

if __name__ == "__main__":
    root = TreeNode(1)
    root.right = TreeNode(2)
    root.right.left = TreeNode(3)
    result = Solution().preorderTraversal(root)
    print result
<commit_msg>Update binary-tree-preorder-traversal.py<commit_after># Time:  O(n)
# Space: O(1)
#
# Given a binary tree, return the preorder traversal of its nodes' values.
#
# For example:
# Given binary tree {1,#,2,3},
#    1
#     \
#      2
#     /
#    3
# return [1,2,3].
#
# Note: Recursive solution is trivial, could you do it iteratively?
#

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

# Morris Traversal Solution
class Solution(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result, prev, cur = [], None, root
        while cur:
            if cur.left is None:
                result.append(cur.val)
                prev = cur
                cur = cur.right
            else:
                node = cur.left
                while node.right and node.right != cur:
                    node = node.right

                if node.right is None:
                    result.append(cur.val)
                    node.right = cur
                    prev =cur
                    cur = cur.left
                else:
                    node.right = None
                    cur = cur.right

        return result

# Time:  O(n)
# Space: O(h)
# Stack Solution
class Solution2(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        result, stack = [], [(root, False)]
        while stack:
            root, is_visited = stack.pop()
            if root is None:
                continue
            if is_visited:
                result.append(root.val)
            else:
                stack.append((root.right, False))
                stack.append((root.left, False))
                stack.append((root, True))
        return result

if __name__ == "__main__":
    root = TreeNode(1)
    root.right = TreeNode(2)
    root.right.left = TreeNode(3)
    result = Solution().preorderTraversal(root)
    print result
<|endoftext|>


<commit_before>###########################################################################################
#                                                                                #
#  some general function which can be called from other Apps                              #
#  update_object_time: sets the state from objects in HA. object will look like:          #
#                      'controle.friendly_name_from_entity'                               #
#                      state can be last time updated or time gone by since last update   #
#  check_last_update_time: checks when the last time was that a sensor was updated        #
#  save_last_update_time: saves the time that an object is updated to a file in a dir     #
#                         you can define. the file wil have the name: lut_entity_id.py    #
#  reformat_time: changed a timeformat from H:M:S to %H:%M:%S                             #
#                                                                                #
#  Rene Tode ( hass@reot.org )                                                            #
#  version 2.0                                                                            #
#  2016/09/04 Germany                                                                     #
#                                                                                #
###########################################################################################

import hassapi as hass
import datetime as datetime
import platform

class general_fnc(hass.Hass):
    def initialize(self):
        return

    def update_object_time(
        self,
        object_name,
        object_friendly_name,
        dir_name,
        time_gone_by,
        time_format,
        object_type,
    ):
        update_time = datetime.datetime.now()
        new_time_format = self.reformat_time(time_format)
        str_complete_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

        if time_gone_by == "true" or time_gone_by == "True":
            str_old_time = self.check_last_update_time(dir_name, object_name)
            try:
                old_time = datetime.datetime.strptime(str_old_time, "%Y-%m-%d %H:%M:%S")
            except:
                self.log("strptime gives err on: " + str_old_time, level="INFO")
                return
            gone_by_time = update_time - old_time
            str_update_time = str(gone_by_time)[:-7] + " ago"
        else:
            str_update_time = update_time.strftime(new_time_format)

        new_entity = object_friendly_name.replace(" ", "_")
        new_entity = new_entity.replace(".", "")
        new_entity = new_entity.replace("(", "")
        new_entity = new_entity.replace(")", "")
        self.set_state("controle." + new_entity, state=str_update_time)

    @staticmethod
    def check_last_update_time(objects_dir, object_name):
        if platform.system() == "windows":
            complete_file_name = objects_dir + "\\lut_" + object_name + ".py"
        else:
            complete_file_name = objects_dir + "/lut_" + object_name + ".py"
        try:
            set_object = open(complete_file_name, "r")
            old_time = set_object.readline()
            set_object.close()
            return old_time
        except:
            return "2000-01-01 00:00:00"

    def save_last_update_time(self, objects_dir, object_name):
        if platform.system() == "windows":
            complete_file_name = objects_dir + "\\lut_" + object_name + ".py"
        else:
            complete_file_name = objects_dir + "/lut_" + object_name + ".py"

        str_complete_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        try:
            set_object = open(complete_file_name, "w")
            set_object.write(str_complete_time)
            set_object.close()
        except:
            self.log(
                "couldn't save the time from: "
                + object_name
                + " in "
                + complete_file_name,
                level="INFO",
            )

    @staticmethod
    def reformat_time(time_format):
        new_time_format = ""
        for counter in range(0, len(time_format)):
            if (
                time_format[counter] != " "
                and time_format[counter] != "-"
                and time_format[counter] != ":"
                and time_format[counter] != "\\"
            ):
                new_time_format = new_time_format + "%" + time_format[counter]
            else:
                new_time_format = new_time_format + time_format[counter]
        return new_time_format
<commit_msg>fix flake8 issues for conf/example_apps/ObjectTracker/general_app_functions.py<commit_after>###########################################################################################
#                                                                                #
#  some general function which can be called from other Apps                              #
#  update_object_time: sets the state from objects in HA. object will look like:          #
#                      'controle.friendly_name_from_entity'                               #
#                      state can be last time updated or time gone by since last update   #
#  check_last_update_time: checks when the last time was that a sensor was updated        #
#  save_last_update_time: saves the time that an object is updated to a file in a dir     #
#                         you can define. the file wil have the name: lut_entity_id.py    #
#  reformat_time: changed a timeformat from H:M:S to %H:%M:%S                             #
#                                                                                #
#  Rene Tode ( hass@reot.org )                                                            #
#  version 2.0                                                                            #
#  2016/09/04 Germany                                                                     #
#                                                                                #
###########################################################################################

import hassapi as hass
import datetime as datetime
import platform

class general_fnc(hass.Hass):
    def initialize(self):
        return

    def update_object_time(
        self,
        object_name,
        object_friendly_name,
        dir_name,
        time_gone_by,
        time_format,
        object_type,
    ):
        update_time = datetime.datetime.now()
        new_time_format = self.reformat_time(time_format)

        if time_gone_by == "true" or time_gone_by == "True":
            str_old_time = self.check_last_update_time(dir_name, object_name)
            try:
                old_time = datetime.datetime.strptime(str_old_time, "%Y-%m-%d %H:%M:%S")
            except Exception:
                self.log("strptime gives err on: " + str_old_time, level="INFO")
                return
            gone_by_time = update_time - old_time
            str_update_time = str(gone_by_time)[:-7] + " ago"
        else:
            str_update_time = update_time.strftime(new_time_format)

        new_entity = object_friendly_name.replace(" ", "_")
        new_entity = new_entity.replace(".", "")
        new_entity = new_entity.replace("(", "")
        new_entity = new_entity.replace(")", "")
        self.set_state("controle." + new_entity, state=str_update_time)

    @staticmethod
    def check_last_update_time(objects_dir, object_name):
        if platform.system() == "windows":
            complete_file_name = objects_dir + "\\lut_" + object_name + ".py"
        else:
            complete_file_name = objects_dir + "/lut_" + object_name + ".py"
        try:
            set_object = open(complete_file_name, "r")
            old_time = set_object.readline()
            set_object.close()
            return old_time
        except Exception:
            return "2000-01-01 00:00:00"

    def save_last_update_time(self, objects_dir, object_name):
        if platform.system() == "windows":
            complete_file_name = objects_dir + "\\lut_" + object_name + ".py"
        else:
            complete_file_name = objects_dir + "/lut_" + object_name + ".py"

        str_complete_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        try:
            set_object = open(complete_file_name, "w")
            set_object.write(str_complete_time)
            set_object.close()
        except Exception:
            self.log(
                "couldn't save the time from: "
                + object_name
                + " in "
                + complete_file_name,
                level="INFO",
            )

    @staticmethod
    def reformat_time(time_format):
        new_time_format = ""
        for counter in range(0, len(time_format)):
            if (
                time_format[counter] != " "
                and time_format[counter] != "-"
                and time_format[counter] != ":"
                and time_format[counter] != "\\"
            ):
                new_time_format = new_time_format + "%" + time_format[counter]
            else:
                new_time_format = new_time_format + time_format[counter]
        return new_time_format
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# svnmerge-migrate-history.py: Migrate merge history from svnmerge.py's
#                              format to Subversion 1.5's format.
#
# ====================================================================
# Copyright (c) 2007 CollabNet.  All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.  The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals.  For exact contribution history, see the revision
# history and logs, available at http://subversion.tigris.org/.
# ====================================================================

import sys
import os
import sre
import getopt
try:
  my_getopt = getopt.gnu_getopt
except AttributeError:
  my_getopt = getopt.getopt

try:
  import svn.core
  import svn.fs
  import svn.repos
except ImportError, e:
  print >> sys.stderr, \
        "ERROR: Unable to import Subversion's Python bindings: '%s'\n" \
        "Hint: Set your PYTHONPATH environment variable, or adjust your " \
        "PYTHONSTARTUP\nfile to point to your Subversion install " \
        "location's svn-python directory." % e
  sys.exit(1)

# Pretend we have boolean data types for older Python versions.
try:
  True
  False
except:
  True = 1
  False = 0

def usage_and_exit(error_msg=None):
  """Write usage information and exit.  If ERROR_MSG is provide, that
  error message is printed first (to stderr), the usage info goes to
  stderr, and the script exits with a non-zero status.  Otherwise,
  usage info goes to stdout and the script exits with a zero status."""
  progname = os.path.basename(sys.argv[0])

  stream = error_msg and sys.stderr or sys.stdout
  if error_msg:
    print >> stream, "ERROR: %s\n" % error_msg
  print >> stream, """usage: %s REPOS_PATH [PATH_PREFIX...] [--verbose]
       %s --help

Migrate merge history from svnmerge.py's format to Subversion 1.5's
format, stopping as soon as merge history is encountered for a
directory tree.

PATH_PREFIX defines the repository paths to examine for merge history
to migrate.  If none are listed, the repository's root is examined.

Example: %s /path/to/repos trunk branches tags
""" % (progname, progname, progname)
  sys.exit(error_msg and 1 or 0)

class Migrator:
  "Migrates merge history."

  repos_path = None
  path_prefixes = None
  verbose = False
  fs = None

  def run(self):
    self.fs = svn.repos.fs(svn.repos.open(self.repos_path))

    revnum = svn.fs.youngest_rev(self.fs)
    root = svn.fs.revision_root(self.fs, revnum)

    # Validate path prefixes, retaining path calculations performed in
    # the process.
    leading_paths = []
    for path_prefix in self.path_prefixes:
      path = "/".join(path_prefix[:-1])
      leading_paths.append(path)
      if svn.fs.check_path(root, path) != svn.core.svn_node_dir:
        raise Exception("Repository path '%s' is not a directory" % path)

    for i in range(0, len(self.path_prefixes)):
      prefix = self.path_prefixes[i]
      self.process_dir(root, revnum, leading_paths[i],
                       prefix[len(prefix) - 1] + ".*")

  def process_dir(self, root, revnum, dir_path, pattern=None):
    "Recursively process children of DIR_PATH."
    dirents = svn.fs.dir_entries(root, dir_path)
    for name in dirents.keys():
      if not dirents[name].kind == svn.core.svn_node_dir:
        continue
      if pattern is None or sre.match(pattern, name):
        if dir_path == "":
          child_path = name
        else:
          child_path = "%s/%s" % (dir_path, name)
        if self.verbose:
          print "Examining path '%s' for conversion" % child_path
        if not self.convert_path_history(root, revnum, child_path):
          self.process_dir(root, revnum, child_path)

  def convert_path_history(self, root, revnum, path):
    "Migrate the merge history for PATH at ROOT at REVNUM."

    ### Bother to handle any pre-existing, inherited svn:mergeinfo?

    # Retrieve svnmerge.py's merge history meta data, and roll it into
    # Subversion 1.5 mergeinfo.
    mergeinfo_prop_val = svn.fs.node_prop(root, path,
                                          svn.core.SVN_PROP_MERGEINFO)
    integrated_prop_val = svn.fs.node_prop(root, path, "svnmerge-integrated")
    if self.verbose:
      print "Discovered pre-existing Subversion mergeinfo of '%s'" % \
        mergeinfo_prop_val
      print "Discovered svnmerge.py mergeinfo of '%s'" % integrated_prop_val
    mergeinfo_prop_val = self.add_to_mergeinfo(integrated_prop_val,
                                               mergeinfo_prop_val)
    ### LATER: We handle svnmerge-blocked by converting it into
    ### svn:mergeinfo, until revision blocking becomes available in
    ### Subversion's core.
    blocked_prop_val = svn.fs.node_prop(root, path, "svnmerge-blocked")
    if self.verbose:
      print "Discovered svnmerge.py blocked revisions of '%s'" % \
        blocked_prop_val
    mergeinfo_prop_val = self.add_to_mergeinfo(blocked_prop_val,
                                               mergeinfo_prop_val)

    if mergeinfo_prop_val is not None:
      # Begin a transaction in which we'll manipulate merge-related
      # properties.  Open the transaction root.
      txn = svn.fs.begin_txn2(self.fs, revnum, 0)
      root = svn.fs.txn_root(txn)

      # Manipulate the merge history.
      if self.verbose:
        print "Queuing change of %s to '%s'" % \
          (svn.core.SVN_PROP_MERGEINFO, mergeinfo_prop_val)
      svn.fs.change_node_prop(root, path, svn.core.SVN_PROP_MERGEINFO,
                              mergeinfo_prop_val)

      # Remove old property values.
      if integrated_prop_val is not None:
        if self.verbose:
          print "Queuing removal of svnmerge-integrated"
        svn.fs.change_node_prop(root, path, "svnmerge-integrated", None)
      if blocked_prop_val is not None:
        if self.verbose:
          print "Queuing removal of svnmerge-blocked"
        svn.fs.change_node_prop(root, path, "svnmerge-blocked", None)

      # Commit the transaction containing our property manipulation.
      if self.verbose:
        print "Committing the transaction containing the above changes"
      conflict, new_revnum = svn.fs.commit_txn(txn)
      if conflict:
        ### TODO: Do something more intelligent with the possible conflict.
        raise Exception("Conflict encountered (%s)" % conflict)
      print "Migrated merge history on '%s' in r%d" % (path, new_revnum)
      return True
    else:
      # No merge history to manipulate.
      if self.verbose:
        print "No merge history on '%s'" % path
      return False

  def add_to_mergeinfo(self, svnmerge_prop_val, mergeinfo_prop_val):
    if svnmerge_prop_val is not None:
      if mergeinfo_prop_val:
        mergeinfo = svn.core.svn_mergeinfo_parse(mergeinfo_prop_val)
        to_migrate = svn.core.svn_mergeinfo_parse(svnmerge_prop_val)
        mergeinfo = svn.core.svn_mergeinfo_merge(mergeinfo, to_migrate)
        mergeinfo_prop_val = svn.core.svn_mergeinfo_to_string(mergeinfo)
      else:
        mergeinfo_prop_val = svnmerge_prop_val

    return mergeinfo_prop_val

  def set_path_prefixes(self, prefixes):
    "Decompose path prefixes into something meaningful for comparision."
    self.path_prefixes = []
    for prefix in prefixes:
      prefix_components = []
      parts = prefix.split("/")
      for i in range(0, len(parts)):
        prefix_components.append(parts[i])
      self.path_prefixes.append(prefix_components)

def main():
  try:
    opts, args = my_getopt(sys.argv[1:], "vh?",
                           ["from-paths=", "verbose", "help"])
  except:
    usage_and_exit("Unable to process arguments/options")

  migrator = Migrator()

  # Process arguments.
  if len(args) >= 1:
    migrator.repos_path = svn.core.svn_path_canonicalize(args[0])
    if len(args) >= 2:
      path_prefixes = args[1:]
    else:
      # Default to the root of the repository.
      path_prefixes = [ "" ]
  else:
    usage_and_exit("REPOS_PATH argument required")

  # Process options.
  for opt, value in opts:
    if opt == "--help" or opt in ("-h", "-?"):
      usage_and_exit()
    elif opt == "--verbose" or opt == "-v":
      migrator.verbose = True
    else:
      usage_and_exit("Unknown option '%s'" % opt)

  migrator.set_path_prefixes(path_prefixes)
  migrator.run()

if __name__ == "__main__":
  main()
<commit_msg>Prevent svnmerge-migrate-history.py from creating no-op commits, and fix some progress printouts.<commit_after>#!/usr/bin/env python
#
# svnmerge-migrate-history.py: Migrate merge history from svnmerge.py's
#                              format to Subversion 1.5's format.
#
# ====================================================================
# Copyright (c) 2007 CollabNet.  All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.  The terms
# are also available at http://subversion.tigris.org/license-1.html.
# If newer versions of this license are posted there, you may use a
# newer version instead, at your option.
#
# This software consists of voluntary contributions made by many
# individuals.  For exact contribution history, see the revision
# history and logs, available at http://subversion.tigris.org/.
# ====================================================================

import sys
import os
import sre
import getopt
try:
  my_getopt = getopt.gnu_getopt
except AttributeError:
  my_getopt = getopt.getopt

try:
  import svn.core
  import svn.fs
  import svn.repos
except ImportError, e:
  print >> sys.stderr, \
        "ERROR: Unable to import Subversion's Python bindings: '%s'\n" \
        "Hint: Set your PYTHONPATH environment variable, or adjust your " \
        "PYTHONSTARTUP\nfile to point to your Subversion install " \
        "location's svn-python directory." % e
  sys.exit(1)

# Pretend we have boolean data types for older Python versions.
try:
  True
  False
except:
  True = 1
  False = 0

def usage_and_exit(error_msg=None):
  """Write usage information and exit.  If ERROR_MSG is provide, that
  error message is printed first (to stderr), the usage info goes to
  stderr, and the script exits with a non-zero status.  Otherwise,
  usage info goes to stdout and the script exits with a zero status."""
  progname = os.path.basename(sys.argv[0])

  stream = error_msg and sys.stderr or sys.stdout
  if error_msg:
    print >> stream, "ERROR: %s\n" % error_msg
  print >> stream, """usage: %s REPOS_PATH [PATH_PREFIX...] [--verbose]
       %s --help

Migrate merge history from svnmerge.py's format to Subversion 1.5's
format, stopping as soon as merge history is encountered for a
directory tree.

PATH_PREFIX defines the repository paths to examine for merge history
to migrate.  If none are listed, the repository's root is examined.

Example: %s /path/to/repos trunk branches tags
""" % (progname, progname, progname)
  sys.exit(error_msg and 1 or 0)

class Migrator:
  "Migrates merge history."

  repos_path = None
  path_prefixes = None
  verbose = False
  fs = None

  def run(self):
    self.fs = svn.repos.fs(svn.repos.open(self.repos_path))

    revnum = svn.fs.youngest_rev(self.fs)
    root = svn.fs.revision_root(self.fs, revnum)

    # Validate path prefixes, retaining path calculations performed in
    # the process.
    leading_paths = []
    for path_prefix in self.path_prefixes:
      path = "/".join(path_prefix[:-1])
      leading_paths.append(path)
      if svn.fs.check_path(root, path) != svn.core.svn_node_dir:
        raise Exception("Repository path '%s' is not a directory" % path)

    for i in range(0, len(self.path_prefixes)):
      prefix = self.path_prefixes[i]
      self.process_dir(root, revnum, leading_paths[i],
                       prefix[len(prefix) - 1] + ".*")

  def process_dir(self, root, revnum, dir_path, pattern=None):
    "Recursively process children of DIR_PATH."
    dirents = svn.fs.dir_entries(root, dir_path)
    for name in dirents.keys():
      if not dirents[name].kind == svn.core.svn_node_dir:
        continue
      if pattern is None or sre.match(pattern, name):
        if dir_path == "":
          child_path = name
        else:
          child_path = "%s/%s" % (dir_path, name)
        if self.verbose:
          print "Examining path '%s' for conversion" % child_path
        if not self.convert_path_history(root, revnum, child_path):
          self.process_dir(root, revnum, child_path)

  def convert_path_history(self, root, revnum, path):
    "Migrate the merge history for PATH at ROOT at REVNUM."

    ### Bother to handle any pre-existing, inherited svn:mergeinfo?

    # Retrieve existing Subversion 1.5 mergeinfo.
    mergeinfo_prop_val = svn.fs.node_prop(root, path,
                                          svn.core.SVN_PROP_MERGEINFO)
    if mergeinfo_prop_val is not None and self.verbose:
      print "Discovered pre-existing Subversion mergeinfo of '%s'" \
            % (mergeinfo_prop_val)

    # Retrieve svnmerge.py's merge history meta data, and roll it into
    # Subversion 1.5 mergeinfo.
    integrated_prop_val = svn.fs.node_prop(root, path, "svnmerge-integrated")
    if integrated_prop_val is not None and self.verbose:
      print "Discovered svnmerge.py mergeinfo of '%s'" \
            % (integrated_prop_val)

    ### LATER: We handle svnmerge-blocked by converting it into
    ### svn:mergeinfo, until revision blocking becomes available in
    ### Subversion's core.
    blocked_prop_val = svn.fs.node_prop(root, path, "svnmerge-blocked")
    if blocked_prop_val is not None and self.verbose:
      print "Discovered svnmerge.py blocked revisions of '%s'" \
            % (blocked_prop_val)

    new_mergeinfo_prop_val = self.add_to_mergeinfo(integrated_prop_val,
                                                   mergeinfo_prop_val)
    new_mergeinfo_prop_val = self.add_to_mergeinfo(blocked_prop_val,
                                                   new_mergeinfo_prop_val)

    # If we need to change the value of the svn:mergeinfo property or
    # delete any svnmerge-* properties, let's do so.
    if (new_mergeinfo_prop_val != mergeinfo_prop_val) \
       or (integrated_prop_val is not None) \
       or (blocked_prop_val is not None):
      # Begin a transaction in which we'll manipulate merge-related
      # properties.  Open the transaction root.
      txn = svn.fs.begin_txn2(self.fs, revnum, 0)
      root = svn.fs.txn_root(txn)

      # Manipulate the merge history.
      if new_mergeinfo_prop_val != mergeinfo_prop_val:
        if self.verbose:
          print "Queuing change of %s to '%s'" % \
                (svn.core.SVN_PROP_MERGEINFO, mergeinfo_prop_val)
        svn.fs.change_node_prop(root, path, svn.core.SVN_PROP_MERGEINFO,
                                mergeinfo_prop_val)

      # Remove old property values.
      if integrated_prop_val is not None:
        if self.verbose:
          print "Queuing removal of svnmerge-integrated"
        svn.fs.change_node_prop(root, path, "svnmerge-integrated", None)
      if blocked_prop_val is not None:
        if self.verbose:
          print "Queuing removal of svnmerge-blocked"
        svn.fs.change_node_prop(root, path, "svnmerge-blocked", None)

      # Commit the transaction containing our property manipulation.
      if self.verbose:
        print "Committing the transaction containing the above changes"
      conflict, new_revnum = svn.fs.commit_txn(txn)
      if conflict:
        ### TODO: Do something more intelligent with the possible conflict.
        raise Exception("Conflict encountered (%s)" % conflict)
      print "Migrated merge history on '%s' in r%d" % (path, new_revnum)
      return True
    else:
      # No merge history to manipulate.
      if self.verbose:
        print "No merge history on '%s'" % path
      return False

  def add_to_mergeinfo(self, svnmerge_prop_val, mergeinfo_prop_val):
    if svnmerge_prop_val is not None:
      if mergeinfo_prop_val:
        mergeinfo = svn.core.svn_mergeinfo_parse(mergeinfo_prop_val)
        to_migrate = svn.core.svn_mergeinfo_parse(svnmerge_prop_val)
        mergeinfo = svn.core.svn_mergeinfo_merge(mergeinfo, to_migrate)
        mergeinfo_prop_val = svn.core.svn_mergeinfo_to_string(mergeinfo)
      else:
        mergeinfo_prop_val = svnmerge_prop_val

    return mergeinfo_prop_val

  def set_path_prefixes(self, prefixes):
    "Decompose path prefixes into something meaningful for comparision."
    self.path_prefixes = []
    for prefix in prefixes:
      prefix_components = []
      parts = prefix.split("/")
      for i in range(0, len(parts)):
        prefix_components.append(parts[i])
      self.path_prefixes.append(prefix_components)

def main():
  try:
    opts, args = my_getopt(sys.argv[1:], "vh?",
                           ["from-paths=", "verbose", "help"])
  except:
    usage_and_exit("Unable to process arguments/options")

  migrator = Migrator()

  # Process arguments.
  if len(args) >= 1:
    migrator.repos_path = svn.core.svn_path_canonicalize(args[0])
    if len(args) >= 2:
      path_prefixes = args[1:]
    else:
      # Default to the root of the repository.
      path_prefixes = [ "" ]
  else:
    usage_and_exit("REPOS_PATH argument required")

  # Process options.
  for opt, value in opts:
    if opt == "--help" or opt in ("-h", "-?"):
      usage_and_exit()
    elif opt == "--verbose" or opt == "-v":
      migrator.verbose = True
    else:
      usage_and_exit("Unknown option '%s'" % opt)

  migrator.set_path_prefixes(path_prefixes)
  migrator.run()

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


<commit_before>"""
# Tool Name:  Find Next Upstream or Downstream NHD
# Author: Marc Weber and Tad Larsen
# Date: October 3, 2014
# Select upstream or downstream feature from a
# selected NHDPlus feature (stream line or catchment)
"""
# Import system modules
import os, arcpy, sys
import struct, decimal, itertools
from collections import deque, defaultdict

def selectStr_by_list(field, lst):
    exp = ''
    for item in lst:
        exp += '"' + field + '" = ' + str(item) + " OR "
    return (exp[:-4])

# Main Function
if __name__ == "__main__":
    #ADD CODE TO SELECT Catchment using restoration site
    #InputFC = sys.argv[1] # NHDPlus feature
    InputFC = r"C:\ArcGIS\Local_GIS\NHD_Plus\NHDPlusNationalData\NHDPlusV21_National_Seamless.gdb\NHDPlusCatchment\Catchment" #selection on FC in GDB
    #InputField = sys.argv[2] # Field with COMID or FEATUREID
    InputField = "FEATUREID" #field from feature layer
    Path = arcpy.Describe(InputFC).Path
    arcpy.env.workspace = Path
    #UpDown = sys.argv[3]
    UpDown = "Downstream" #alt = "Upstream"
    #if (InputFC == "Catchment"):
    #    Flow = Path.replace('NHDPlusCatchment','NHDPlusAttributes')+'\PlusFlow.dbf' #replace(*old*, *new*)
    #else:
    #    Flow = Path.replace('NHDSnapshot\\Hydrography','NHDPlusAttributes')+'\PlusFlow.dbf'
    Flow = Path.replace('\\NHDPlusCatchment','\\PlusFlow')

    try:
        #STEP 1: pull to/from out into memory
        UpCOMs = defaultdict(list)
        DownCOMs = defaultdict(list)
        #FeatureclassName = arcpy.Describe(InputFC).Name #don't think this is used
        arcpy.AddMessage("Gathering info on upstream / downstream relationships")
        with arcpy.da.SearchCursor(Flow, ["FROMCOMID", "TOCOMID"]) as cursor:
            for row in cursor:
                FROMCOMID = row[0]
                TOCOMID = row[1]
                if TOCOMID != 0:
                    UpCOMs[TOCOMID].append(TOCOMID)
                    DownCOMs[FROMCOMID].append(TOCOMID)
        #infile = open(Flow, 'rb')
        #arcpy.AddMessage("Making list from dbf file.")
        #data = list(dbfreader(infile))
        #infile.close()
        #for line in data[2:]:
        #    FROMCOMID=line[0]
        #    TOCOMID=line[3]
        #    UpCOMs[TOCOMID].append(FROMCOMID)
        #    DownCOMs[FROMCOMID].append(TOCOMID)
        #for k in UpCOMs.iterkeys():
        #    for items in UpCOMs[k]:
        #        if items == 0:
        #            UpCOMs[k] = []
        #for k in DownCOMs.iterkeys():
        #    for items in DownCOMs[k]:
        #        if items == 0:
        #            DownCOMs[k] = []

        #STEP 2: Get start IDs from input
        COMID_lst = [] #set instead? would eliminate duplicates
        with arcpy.da.SearchCursor(InputFC, [InputField]) as cursor:
            for row in cursor:
                COMID_lst.append = row[0]
#QUESTION: Nest function into each row instead of using list?
        #STEP 3: Use IDs list to find upstream/downstream
        for COMID in COMID_lst:
            if UpDown == "Upstream":
                arcpy.AddMessage("Finding next upstream feature(s)...")
                #stuff = str(UpCOMs[COMID]).strip('[]')
                selection = selectStr_by_list(InputField, UpCOMs[COMID])
            if UpDown == "Downstream":
                arcpy.AddMessage("Finding next downstream feature(s)...")
                #stuff = str(DownCOMs[COMID]).strip('[]')
                selection = selectStr_by_list(InputField, DownCOMs[COMID])
            #arcpy.SelectLayerByAttribute_management(InputFC,"NEW_SELECTION",selection)
            arcpy.MakeFeatureLayer_management(InputFC, "InputFC_lyr", selection, "", "")
#OR IF THERE is no upstream/downstream (reached end of network)
            if outsideTest("InputFC_lyr", boundary) == False:
                #add to selection
                repeat process using current selection
            else:
                FinalSelection

            #loop this section until selection is outside of buffer
            #if InputFC is within Buffer == TRUE:

        #rows = arcpy.SearchCursor(InputFC)
        #for row in rows:
        #    COMID = (row.getValue("%s"%(InputField)))

                if UpDown == "Upstream":
                    stuff = str(UpCOMs[COMID]).strip('[]')
                    string = "\"%s\" IN (%s)"%(InputField,stuff)
                    arcpy.AddMessage("Adding upstream features(s) to selection...")
                    arcpy.SelectLayerByAttribute_management(InputFC,"ADD_TO_SELECTION",string)

                if UpDown == "Downstream":
                    stuff = str(DownCOMs[COMID]).strip('[]')
                    string = "\"%s\" IN (%s)"%(InputField,stuff)
                    arcpy.AddMessage("Adding downstream features(s) to selection...")
                    arcpy.SelectLayerByAttribute_management(InputFC,"ADD_TO_SELECTION",string)
        #Else:
                    arcpy.AddMessages("Selection complete")
        arcpy.AddMessage(" ")
    except:
      arcpy.GetMessages()

<commit_msg>Started adding site based selection of catchments<commit_after>"""
# Tool Name:  Find Next Upstream or Downstream NHD
# Author: Marc Weber and Tad Larsen
# Date: October 3, 2014
# Select upstream or downstream feature from a
# selected NHDPlus feature (stream line or catchment)
"""
# Import system modules
import os, arcpy, sys
#import struct, decimal, itertools
from collections import deque, defaultdict

"""Selection Query String from list
Purpose: return a string for a where clause from a list of field values
"""
def selectStr_by_list(field, lst):
    exp = ''
    for item in lst:
        exp += '"' + field + '" = ' + str(item) + " OR "
    return (exp[:-4])

"""Intersect Boolean
Purpose: returns T/F if two layers intersect at all
"""
def intersect_boolean(lyr1, lyr2):
    arcpy.SelectLayerByLocation_management(lyr1, 'intersect', lyr2)
    cnt = int(arcpy.GetCount_management(lyr1)[0])
    if cnt == 0:
        return False
    else:
        return True

# Main Function
if __name__ == "__main__":
    #ADD CODE TO SELECT Catchment using restoration site
    #InputFC = sys.argv[1] # NHDPlus feature
    InputFC = r"C:\ArcGIS\Local_GIS\NHD_Plus\NHDPlusNationalData\NHDPlusV21_National_Seamless.gdb\NHDPlusCatchment\Catchment" #selection on FC in GDB
    #InputField = sys.argv[2] # Field with COMID or FEATUREID
    InputField = "FEATUREID" #field from feature layer
    Path = arcpy.Describe(InputFC).Path
    arcpy.env.workspace = Path
    #UpDown = sys.argv[3]
    UpDown = "Downstream" #alt = "Upstream"
    #if (InputFC == "Catchment"):
    #    Flow = Path.replace('NHDPlusCatchment','NHDPlusAttributes')+'\PlusFlow.dbf' #replace(*old*, *new*)
    #else:
    #    Flow = Path.replace('NHDSnapshot\\Hydrography','NHDPlusAttributes')+'\PlusFlow.dbf'
    Flow = Path.replace('\\NHDPlusCatchment','\\PlusFlow')

    RestorationSite = r"L:\Public\jbousqui\Code\Python\Python_Addins\Tier1_pyt\Test_Results\Intermediates2.gdb\Results"

    #make FCs into lyrs
    arcpy.MakeFeatureLayer_management(RestorationSite, "RestorationSite_lyr")
    arcpy.MakeFeatureLayer_management(InputFC, "InputFC_lyr")

    try:
        #STEP 1: pull to/from out into memory
        UpCOMs = defaultdict(list)
        DownCOMs = defaultdict(list)
        #FeatureclassName = arcpy.Describe(InputFC).Name #don't think this is used
        arcpy.AddMessage("Gathering info on upstream / downstream relationships")
        with arcpy.da.SearchCursor(Flow, ["FROMCOMID", "TOCOMID"]) as cursor:
            for row in cursor:
                FROMCOMID = row[0]
                TOCOMID = row[1]
                if TOCOMID != 0:
                    UpCOMs[TOCOMID].append(TOCOMID)
                    DownCOMs[FROMCOMID].append(TOCOMID)
        #infile = open(Flow, 'rb')
        #arcpy.AddMessage("Making list from dbf file.")
        #data = list(dbfreader(infile))
        #infile.close()
        #for line in data[2:]:
        #    FROMCOMID=line[0]
        #    TOCOMID=line[3]
        #    UpCOMs[TOCOMID].append(FROMCOMID)
        #    DownCOMs[FROMCOMID].append(TOCOMID)
        #for k in UpCOMs.iterkeys():
        #    for items in UpCOMs[k]:
        #        if items == 0:
        #            UpCOMs[k] = []
        #for k in DownCOMs.iterkeys():
        #    for items in DownCOMs[k]:
        #        if items == 0:
        #            DownCOMs[k] = []

        #STEP 2: Get start IDs from input
        #select catchment using restoration site
        arcpy.SelectLayerByLocation_management("InputFC_lyr", 'intersect', "RestorationSite_lyr")
        COMID_lst = [] #set instead? would eliminate duplicates
        with arcpy.da.SearchCursor(InputFC_lyr, [InputField]) as cursor:
            for row in cursor:
                COMID_lst.append(row[0])
#QUESTION: Nest function into each row instead of using list?
        #STEP 3: Use IDs list to find upstream/downstream
        for COMID in COMID_lst:
            if UpDown == "Upstream":
                arcpy.AddMessage("Finding next upstream feature(s)...")
                #stuff = str(UpCOMs[COMID]).strip('[]')
                selection = selectStr_by_list(InputField, UpCOMs[COMID])
            if UpDown == "Downstream":
                arcpy.AddMessage("Finding next downstream feature(s)...")
                #stuff = str(DownCOMs[COMID]).strip('[]')
                selection = selectStr_by_list(InputField, DownCOMs[COMID])
            #arcpy.SelectLayerByAttribute_management(InputFC,"NEW_SELECTION",selection)
            arcpy.MakeFeatureLayer_management(InputFC, "InputFC_lyr", selection, "", "")
#OR IF THERE is no upstream/downstream (reached end of network)
            if outsideTest("InputFC_lyr", boundary) == False:
                #add to selection
                repeat process using current selection
            else:
                FinalSelection

            #loop this section until selection is outside of buffer
            #if InputFC is within Buffer == TRUE:

        #rows = arcpy.SearchCursor(InputFC)
        #for row in rows:
        #    COMID = (row.getValue("%s"%(InputField)))

                if UpDown == "Upstream":
                    stuff = str(UpCOMs[COMID]).strip('[]')
                    string = "\"%s\" IN (%s)"%(InputField,stuff)
                    arcpy.AddMessage("Adding upstream features(s) to selection...")
                    arcpy.SelectLayerByAttribute_management(InputFC,"ADD_TO_SELECTION",string)

                if UpDown == "Downstream":
                    stuff = str(DownCOMs[COMID]).strip('[]')
                    string = "\"%s\" IN (%s)"%(InputField,stuff)
                    arcpy.AddMessage("Adding downstream features(s) to selection...")
                    arcpy.SelectLayerByAttribute_management(InputFC,"ADD_TO_SELECTION",string)
        #Else:
                    arcpy.AddMessages("Selection complete")
        arcpy.AddMessage(" ")
    except:
      arcpy.GetMessages()
<|endoftext|>


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

from __future__ import unicode_literals
import frappe
import json
from frappe.desk.desktop import save_new_widget
from frappe.model.document import Document

class InternalWikiPage(Document):

	def before_insert(self):
		sequence_id_list = frappe.get_all('Internal Wiki Page', {'sequence_id'})
		self.sequence_id = max([page.sequence_id for page in sequence_id_list]) + 1

@frappe.whitelist()
def save_wiki_page(title, parent, sb_items, deleted_pages, new_widgets, blocks, save=True):
	if save:
		if not frappe.db.exists("Workspace", title):
			wspace = frappe.new_doc('Workspace')
			wspace.label = title
			wspace.insert()

		doc = frappe.new_doc('Internal Wiki Page')
		doc.title = title
		doc.parent_page = parent
		doc.content = blocks
		doc.insert()
	else:
		doc = frappe.get_doc('Internal Wiki Page', title)
		doc.content = blocks
		doc.save()

	if json.loads(sb_items):
		for seq, d in enumerate(json.loads(sb_items)):
			doc = frappe.get_doc('Internal Wiki Page', d.get('name'))
			doc.sequence_id = seq + 1
			doc.parent_page = d.get('parent_page') or ""
			doc.save()
		doc.title = title

	if json.loads(deleted_pages):
		for d in json.loads(deleted_pages):
			wiki_doc = frappe.get_doc('Internal Wiki Page', d)
			wiki_doc.delete()
			wspace_doc = frappe.get_doc('Workspace', d)
			if not wspace_doc.is_standard:
				wspace_doc.delete()
		return 'Build'

	if json.loads(new_widgets):
		save_new_widget(title, new_widgets)

	return doc.title<commit_msg>fix: minor fixes<commit_after># -*- coding: utf-8 -*-
# Copyright (c) 2021, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
import json
from frappe.desk.desktop import save_new_widget
from frappe.model.document import Document

class InternalWikiPage(Document):

	def before_insert(self):
		sequence_id_list = frappe.get_all('Internal Wiki Page', {'sequence_id'})
		self.sequence_id = max([page.sequence_id for page in sequence_id_list] or [0]) + 1

@frappe.whitelist()
def save_wiki_page(title, parent, sb_items, deleted_pages, new_widgets, blocks, save=True):
	if save:
		if not frappe.db.exists("Workspace", title):
			wspace = frappe.new_doc('Workspace')
			wspace.label = title
			wspace.insert()

		doc = frappe.new_doc('Internal Wiki Page')
		doc.title = title
		doc.parent_page = parent
		doc.content = blocks
		doc.insert()
	else:
		doc = frappe.get_doc('Internal Wiki Page', title)
		doc.content = blocks
		doc.save()

	if json.loads(sb_items):
		for seq, d in enumerate(json.loads(sb_items)):
			doc = frappe.get_doc('Internal Wiki Page', d.get('name'))
			doc.sequence_id = seq + 1
			doc.parent_page = d.get('parent_page') or ""
			doc.save()
		doc.title = title

	if json.loads(deleted_pages):
		for d in json.loads(deleted_pages):
			wiki_doc = frappe.get_doc('Internal Wiki Page', d)
			wiki_doc.delete()
			wspace_doc = frappe.get_doc('Workspace', d)
			if not wspace_doc.is_standard:
				wspace_doc.delete()
		return 'Build'

	if json.loads(new_widgets):
		save_new_widget(title, new_widgets)

	return doc.title<|endoftext|>