<commit_before># Copyright 2013 Metacloud
#
# 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.

"""Caching Layer Implementation."""

import dogpile.cache
from dogpile.cache import proxy
from dogpile.cache import util
from oslo_config import cfg
from oslo_log import log
from oslo_utils import importutils

from oslo_cache import exception
from oslo_cache._i18n import _, _LE
from oslo_cache import _opts

__all__ = [
    'configure',
    'configure_cache_region',
    'DebugProxy',
    'get_memoization_decorator',
]

_CONF = cfg.CONF
_LOG = log.getLogger(__name__)

_make_region = dogpile.cache.make_region

dogpile.cache.register_backend(
    'oslo_cache.noop',
    'oslo_cache.backends.noop',
    'NoopCacheBackend')

dogpile.cache.register_backend(
    'oslo_cache.mongo',
    'oslo_cache.backends.mongo',
    'MongoCacheBackend')

dogpile.cache.register_backend(
    'oslo_cache.memcache_pool',
    'oslo_cache.backends.memcache_pool',
    'PooledMemcachedBackend')

class DebugProxy(proxy.ProxyBackend):
    """Extra Logging ProxyBackend."""
    # NOTE(morganfainberg): Pass all key/values through repr to ensure we have
    # a clean description of the information.  Without use of repr, it might
    # be possible to run into encode/decode error(s). For logging/debugging
    # purposes encode/decode is irrelevant and we should be looking at the
    # data exactly as it stands.

    def get(self, key):
        value = self.proxied.get(key)
        _LOG.debug('CACHE_GET: Key: "%(key)r" Value: "%(value)r"',
                   {'key': key, 'value': value})
        return value

    def get_multi(self, keys):
        values = self.proxied.get_multi(keys)
        _LOG.debug('CACHE_GET_MULTI: "%(keys)r" Values: "%(values)r"',
                   {'keys': keys, 'values': values})
        return values

    def set(self, key, value):
        _LOG.debug('CACHE_SET: Key: "%(key)r" Value: "%(value)r"',
                   {'key': key, 'value': value})
        return self.proxied.set(key, value)

    def set_multi(self, keys):
        _LOG.debug('CACHE_SET_MULTI: "%r"', keys)
        self.proxied.set_multi(keys)

    def delete(self, key):
        self.proxied.delete(key)
        _LOG.debug('CACHE_DELETE: "%r"', key)

    def delete_multi(self, keys):
        _LOG.debug('CACHE_DELETE_MULTI: "%r"', keys)
        self.proxied.delete_multi(keys)

def _build_cache_config():
    """Build the cache region dictionary configuration.

    :returns: dict
    """
    prefix = _CONF.cache.config_prefix
    conf_dict = {}
    conf_dict['%s.backend' % prefix] = _CONF.cache.backend
    conf_dict['%s.expiration_time' % prefix] = _CONF.cache.expiration_time
    for argument in _CONF.cache.backend_argument:
        try:
            (argname, argvalue) = argument.split(':', 1)
        except ValueError:
            msg = _LE('Unable to build cache config-key. Expected format '
                      '"<argname>:<value>". Skipping unknown format: %s')
            _LOG.error(msg, argument)
            continue

        arg_key = '.'.join([prefix, 'arguments', argname])
        conf_dict[arg_key] = argvalue

        _LOG.debug('Oslo Cache Config: %s', conf_dict)
    # NOTE(yorik-sar): these arguments will be used for memcache-related
    # backends. Use setdefault for url to support old-style setting through
    # backend_argument=url:127.0.0.1:11211
    conf_dict.setdefault('%s.arguments.url' % prefix,
                         _CONF.cache.memcache_servers)
    for arg in ('dead_retry', 'socket_timeout', 'pool_maxsize',
                'pool_unused_timeout', 'pool_connection_get_timeout'):
        value = getattr(_CONF.cache, 'memcache_' + arg)
        conf_dict['%s.arguments.%s' % (prefix, arg)] = value

    return conf_dict

def _sha1_mangle_key(key):
    """Wrapper for dogpile's sha1_mangle_key.

    dogpile's sha1_mangle_key function expects an encoded string, so we
    should take steps to properly handle multiple inputs before passing
    the key through.
    """
    try:
        key = key.encode('utf-8', errors='xmlcharrefreplace')
    except (UnicodeError, AttributeError):
        # NOTE(stevemar): if encoding fails just continue anyway.
        pass
    return util.sha1_mangle_key(key)

def configure_cache_region(region):
    """Configure a cache region.

    :param region: optional CacheRegion object, if not provided a new region
                   will be instantiated
    :raises: exception.ConfigurationError
    :returns: dogpile.cache.CacheRegion
    """
    if not isinstance(region, dogpile.cache.CacheRegion):
        raise exception.ConfigurationError(
            _('region not type dogpile.cache.CacheRegion'))

    if not region.is_configured:
        # NOTE(morganfainberg): this is how you tell if a region is configured.
        # There is a request logged with dogpile.cache upstream to make this
        # easier / less ugly.

        config_dict = _build_cache_config()
        region.configure_from_config(config_dict,
                                     '%s.' % _CONF.cache.config_prefix)

        if _CONF.cache.debug_cache_backend:
            region.wrap(DebugProxy)

        # NOTE(morganfainberg): if the backend requests the use of a
        # key_mangler, we should respect that key_mangler function.  If a
        # key_mangler is not defined by the backend, use the sha1_mangle_key
        # mangler provided by dogpile.cache. This ensures we always use a fixed
        # size cache-key.
        if region.key_mangler is None:
            region.key_mangler = _sha1_mangle_key

        for class_path in _CONF.cache.proxies:
            # NOTE(morganfainberg): if we have any proxy wrappers, we should
            # ensure they are added to the cache region's backend.  Since
            # configure_from_config doesn't handle the wrap argument, we need
            # to manually add the Proxies. For information on how the
            # ProxyBackends work, see the dogpile.cache documents on
            # "changing-backend-behavior"
            cls = importutils.import_class(class_path)
            _LOG.debug("Adding cache-proxy '%s' to backend.", class_path)
            region.wrap(cls)

    return region

def _get_should_cache_fn(section):
    """Build a function that returns a config section's caching status.

    For any given object that has caching capabilities, a boolean config option
    for that object's section should exist and default to ``True``. This
    function will use that value to tell the caching decorator if caching for
    that object is enabled. To properly use this with the decorator, pass this
    function the configuration section and assign the result to a variable.
    Pass the new variable to the caching decorator as the named argument
    ``should_cache_fn``.  e.g.::

        import oslo_cache

        SHOULD_CACHE = oslo_cache._get_should_cache_fn(section='section1')

        @oslo_cache._on_arguments(should_cache_fn=SHOULD_CACHE)
        def function(arg1, arg2):
            ...

    :param section: name of the configuration section to examine
    :type section: string
    :returns: function reference
    """
    def should_cache(value):
        if not _CONF.cache.enabled:
            return False
        conf_group = getattr(_CONF, section)
        return getattr(conf_group, 'caching', True)
    return should_cache

def _get_expiration_time_fn(section):
    """Build a function that returns a config section's expiration time status.

    For any given object that has caching capabilities, an int config option
    called ``cache_time`` for that driver's section should exist and typically
    default to ``None``. This function will use that value to tell the caching
    decorator of the TTL override for caching the resulting objects. If the
    value of the config option is ``None`` the default value provided in the
    ``[cache] expiration_time`` option will be used by the decorator. The
    default may be set to something other than ``None`` in cases where the
    caching TTL should not be tied to the global default(s).

    To properly use this with the decorator, pass this function the
    configuration section and assign the result to a variable. Pass the new
    variable to the caching decorator as the named argument
    ``expiration_time``.  e.g.::

        import oslo_cache

        EXPIRATION_TIME = oslo_cache._get_expiration_time_fn(
            section='section1')

        @oslo_cache._on_arguments(expiration_time=EXPIRATION_TIME)
        def function(arg1, arg2):
            ...

    :param section: name of the configuration section to examine
    :type section: string
    :rtype: function reference
    """
    def get_expiration_time():
        conf_group = getattr(_CONF, section)
        return getattr(conf_group, 'cache_time', None)
    return get_expiration_time

def _key_generate_to_str(s):
    # NOTE(morganfainberg): Since we need to stringify all arguments, attempt
    # to stringify and handle the Unicode error explicitly as needed.
    try:
        return str(s)
    except UnicodeEncodeError:
        return s.encode('utf-8')

def _function_key_generator(namespace, fn, to_str=_key_generate_to_str):
    # NOTE(morganfainberg): This wraps dogpile.cache's default
    # function_key_generator to change the default to_str mechanism.
    return util.function_key_generator(namespace, fn, to_str=to_str)

_REGION = dogpile.cache.make_region(
    function_key_generator=_function_key_generator)
_on_arguments = _REGION.cache_on_arguments

def get_memoization_decorator(section, expiration_section=None):
    """Build a function based on the `_on_arguments` decorator for the section.

    For any given object that has caching capabilities, a pair of functions is
    required to properly determine the status of the caching capabilities (a
    toggle to indicate caching is enabled and any override of the default TTL
    for cached data). This function will return an object that has the
    memoization decorator ``_on_arguments`` pre-configured for the driver.

    Example usage::

        import oslo_cache

        MEMOIZE = oslo_cache.get_memoization_decorator(section='section1')

        @MEMOIZE
        def function(arg1, arg2):
            ...

        ALTERNATE_MEMOIZE = oslo_cache.get_memoization_decorator(
            section='section2', expiration_section='section3')

        @ALTERNATE_MEMOIZE
        def function2(arg1, arg2):
            ...

    :param section: name of the configuration section to examine
    :type section: string
    :param expiration_section: name of the configuration section to examine
                               for the expiration option. This will fall back
                               to using ``section`` if the value is unspecified
                               or ``None``
    :type expiration_section: string
    :rtype: function reference
    """
    if expiration_section is None:
        expiration_section = section
    should_cache = _get_should_cache_fn(section)
    expiration_time = _get_expiration_time_fn(expiration_section)

    memoize = _REGION.cache_on_arguments(should_cache_fn=should_cache,
                                         expiration_time=expiration_time)

    # Make sure the actual "should_cache" and "expiration_time" methods are
    # available. This is potentially interesting/useful to pre-seed cache
    # values.
    memoize.should_cache = should_cache
    memoize.get_expiration_time = expiration_time

    return memoize

def configure(conf):
    _opts.configure(conf)
<commit_msg>Docs for configure()<commit_after># Copyright 2013 Metacloud
#
# 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.

"""Caching Layer Implementation."""

import dogpile.cache
from dogpile.cache import proxy
from dogpile.cache import util
from oslo_config import cfg
from oslo_log import log
from oslo_utils import importutils

from oslo_cache import exception
from oslo_cache._i18n import _, _LE
from oslo_cache import _opts

__all__ = [
    'configure',
    'configure_cache_region',
    'DebugProxy',
    'get_memoization_decorator',
]

_CONF = cfg.CONF
_LOG = log.getLogger(__name__)

_make_region = dogpile.cache.make_region

dogpile.cache.register_backend(
    'oslo_cache.noop',
    'oslo_cache.backends.noop',
    'NoopCacheBackend')

dogpile.cache.register_backend(
    'oslo_cache.mongo',
    'oslo_cache.backends.mongo',
    'MongoCacheBackend')

dogpile.cache.register_backend(
    'oslo_cache.memcache_pool',
    'oslo_cache.backends.memcache_pool',
    'PooledMemcachedBackend')

class DebugProxy(proxy.ProxyBackend):
    """Extra Logging ProxyBackend."""
    # NOTE(morganfainberg): Pass all key/values through repr to ensure we have
    # a clean description of the information.  Without use of repr, it might
    # be possible to run into encode/decode error(s). For logging/debugging
    # purposes encode/decode is irrelevant and we should be looking at the
    # data exactly as it stands.

    def get(self, key):
        value = self.proxied.get(key)
        _LOG.debug('CACHE_GET: Key: "%(key)r" Value: "%(value)r"',
                   {'key': key, 'value': value})
        return value

    def get_multi(self, keys):
        values = self.proxied.get_multi(keys)
        _LOG.debug('CACHE_GET_MULTI: "%(keys)r" Values: "%(values)r"',
                   {'keys': keys, 'values': values})
        return values

    def set(self, key, value):
        _LOG.debug('CACHE_SET: Key: "%(key)r" Value: "%(value)r"',
                   {'key': key, 'value': value})
        return self.proxied.set(key, value)

    def set_multi(self, keys):
        _LOG.debug('CACHE_SET_MULTI: "%r"', keys)
        self.proxied.set_multi(keys)

    def delete(self, key):
        self.proxied.delete(key)
        _LOG.debug('CACHE_DELETE: "%r"', key)

    def delete_multi(self, keys):
        _LOG.debug('CACHE_DELETE_MULTI: "%r"', keys)
        self.proxied.delete_multi(keys)

def _build_cache_config():
    """Build the cache region dictionary configuration.

    :returns: dict
    """
    prefix = _CONF.cache.config_prefix
    conf_dict = {}
    conf_dict['%s.backend' % prefix] = _CONF.cache.backend
    conf_dict['%s.expiration_time' % prefix] = _CONF.cache.expiration_time
    for argument in _CONF.cache.backend_argument:
        try:
            (argname, argvalue) = argument.split(':', 1)
        except ValueError:
            msg = _LE('Unable to build cache config-key. Expected format '
                      '"<argname>:<value>". Skipping unknown format: %s')
            _LOG.error(msg, argument)
            continue

        arg_key = '.'.join([prefix, 'arguments', argname])
        conf_dict[arg_key] = argvalue

        _LOG.debug('Oslo Cache Config: %s', conf_dict)
    # NOTE(yorik-sar): these arguments will be used for memcache-related
    # backends. Use setdefault for url to support old-style setting through
    # backend_argument=url:127.0.0.1:11211
    conf_dict.setdefault('%s.arguments.url' % prefix,
                         _CONF.cache.memcache_servers)
    for arg in ('dead_retry', 'socket_timeout', 'pool_maxsize',
                'pool_unused_timeout', 'pool_connection_get_timeout'):
        value = getattr(_CONF.cache, 'memcache_' + arg)
        conf_dict['%s.arguments.%s' % (prefix, arg)] = value

    return conf_dict

def _sha1_mangle_key(key):
    """Wrapper for dogpile's sha1_mangle_key.

    dogpile's sha1_mangle_key function expects an encoded string, so we
    should take steps to properly handle multiple inputs before passing
    the key through.
    """
    try:
        key = key.encode('utf-8', errors='xmlcharrefreplace')
    except (UnicodeError, AttributeError):
        # NOTE(stevemar): if encoding fails just continue anyway.
        pass
    return util.sha1_mangle_key(key)

def configure_cache_region(region):
    """Configure a cache region.

    :param region: optional CacheRegion object, if not provided a new region
                   will be instantiated
    :raises: exception.ConfigurationError
    :returns: dogpile.cache.CacheRegion
    """
    if not isinstance(region, dogpile.cache.CacheRegion):
        raise exception.ConfigurationError(
            _('region not type dogpile.cache.CacheRegion'))

    if not region.is_configured:
        # NOTE(morganfainberg): this is how you tell if a region is configured.
        # There is a request logged with dogpile.cache upstream to make this
        # easier / less ugly.

        config_dict = _build_cache_config()
        region.configure_from_config(config_dict,
                                     '%s.' % _CONF.cache.config_prefix)

        if _CONF.cache.debug_cache_backend:
            region.wrap(DebugProxy)

        # NOTE(morganfainberg): if the backend requests the use of a
        # key_mangler, we should respect that key_mangler function.  If a
        # key_mangler is not defined by the backend, use the sha1_mangle_key
        # mangler provided by dogpile.cache. This ensures we always use a fixed
        # size cache-key.
        if region.key_mangler is None:
            region.key_mangler = _sha1_mangle_key

        for class_path in _CONF.cache.proxies:
            # NOTE(morganfainberg): if we have any proxy wrappers, we should
            # ensure they are added to the cache region's backend.  Since
            # configure_from_config doesn't handle the wrap argument, we need
            # to manually add the Proxies. For information on how the
            # ProxyBackends work, see the dogpile.cache documents on
            # "changing-backend-behavior"
            cls = importutils.import_class(class_path)
            _LOG.debug("Adding cache-proxy '%s' to backend.", class_path)
            region.wrap(cls)

    return region

def _get_should_cache_fn(section):
    """Build a function that returns a config section's caching status.

    For any given object that has caching capabilities, a boolean config option
    for that object's section should exist and default to ``True``. This
    function will use that value to tell the caching decorator if caching for
    that object is enabled. To properly use this with the decorator, pass this
    function the configuration section and assign the result to a variable.
    Pass the new variable to the caching decorator as the named argument
    ``should_cache_fn``.  e.g.::

        import oslo_cache

        SHOULD_CACHE = oslo_cache._get_should_cache_fn(section='section1')

        @oslo_cache._on_arguments(should_cache_fn=SHOULD_CACHE)
        def function(arg1, arg2):
            ...

    :param section: name of the configuration section to examine
    :type section: string
    :returns: function reference
    """
    def should_cache(value):
        if not _CONF.cache.enabled:
            return False
        conf_group = getattr(_CONF, section)
        return getattr(conf_group, 'caching', True)
    return should_cache

def _get_expiration_time_fn(section):
    """Build a function that returns a config section's expiration time status.

    For any given object that has caching capabilities, an int config option
    called ``cache_time`` for that driver's section should exist and typically
    default to ``None``. This function will use that value to tell the caching
    decorator of the TTL override for caching the resulting objects. If the
    value of the config option is ``None`` the default value provided in the
    ``[cache] expiration_time`` option will be used by the decorator. The
    default may be set to something other than ``None`` in cases where the
    caching TTL should not be tied to the global default(s).

    To properly use this with the decorator, pass this function the
    configuration section and assign the result to a variable. Pass the new
    variable to the caching decorator as the named argument
    ``expiration_time``.  e.g.::

        import oslo_cache

        EXPIRATION_TIME = oslo_cache._get_expiration_time_fn(
            section='section1')

        @oslo_cache._on_arguments(expiration_time=EXPIRATION_TIME)
        def function(arg1, arg2):
            ...

    :param section: name of the configuration section to examine
    :type section: string
    :rtype: function reference
    """
    def get_expiration_time():
        conf_group = getattr(_CONF, section)
        return getattr(conf_group, 'cache_time', None)
    return get_expiration_time

def _key_generate_to_str(s):
    # NOTE(morganfainberg): Since we need to stringify all arguments, attempt
    # to stringify and handle the Unicode error explicitly as needed.
    try:
        return str(s)
    except UnicodeEncodeError:
        return s.encode('utf-8')

def _function_key_generator(namespace, fn, to_str=_key_generate_to_str):
    # NOTE(morganfainberg): This wraps dogpile.cache's default
    # function_key_generator to change the default to_str mechanism.
    return util.function_key_generator(namespace, fn, to_str=to_str)

_REGION = dogpile.cache.make_region(
    function_key_generator=_function_key_generator)
_on_arguments = _REGION.cache_on_arguments

def get_memoization_decorator(section, expiration_section=None):
    """Build a function based on the `_on_arguments` decorator for the section.

    For any given object that has caching capabilities, a pair of functions is
    required to properly determine the status of the caching capabilities (a
    toggle to indicate caching is enabled and any override of the default TTL
    for cached data). This function will return an object that has the
    memoization decorator ``_on_arguments`` pre-configured for the driver.

    Example usage::

        import oslo_cache

        MEMOIZE = oslo_cache.get_memoization_decorator(section='section1')

        @MEMOIZE
        def function(arg1, arg2):
            ...

        ALTERNATE_MEMOIZE = oslo_cache.get_memoization_decorator(
            section='section2', expiration_section='section3')

        @ALTERNATE_MEMOIZE
        def function2(arg1, arg2):
            ...

    :param section: name of the configuration section to examine
    :type section: string
    :param expiration_section: name of the configuration section to examine
                               for the expiration option. This will fall back
                               to using ``section`` if the value is unspecified
                               or ``None``
    :type expiration_section: string
    :rtype: function reference
    """
    if expiration_section is None:
        expiration_section = section
    should_cache = _get_should_cache_fn(section)
    expiration_time = _get_expiration_time_fn(expiration_section)

    memoize = _REGION.cache_on_arguments(should_cache_fn=should_cache,
                                         expiration_time=expiration_time)

    # Make sure the actual "should_cache" and "expiration_time" methods are
    # available. This is potentially interesting/useful to pre-seed cache
    # values.
    memoize.should_cache = should_cache
    memoize.get_expiration_time = expiration_time

    return memoize

def configure(conf):
    """Configure the library.

    This must be called before conf().

    :param conf: The configuration object.
    :type conf: oslo_config.cfg.ConfigOpts

    """
    _opts.configure(conf)
<|endoftext|>


<commit_before># Copyright (c) 2014 by Ecreall under licence AGPL terms
# avalaible on http://www.gnu.org/licenses/agpl.html

# licence: AGPL
# author: Amen Souissi
"""
This module represent the Idea management process definition
powered by the dace engine. This process is unique, which means that
this process is instantiated only once.
"""
from dace.processdefinition.processdef import ProcessDefinition
from dace.processdefinition.activitydef import ActivityDefinition
from dace.processdefinition.gatewaydef import (
    ExclusiveGatewayDefinition,
    ParallelGatewayDefinition)
from dace.processdefinition.transitiondef import TransitionDefinition
from dace.processdefinition.eventdef import (
    StartEventDefinition,
    EndEventDefinition)
from dace.objectofcollaboration.services.processdef_container import (
  process_definition)
from pontus.core import VisualisableElement

from .behaviors import (
    CreateIdea,
    DuplicateIdea,
    DelIdea,
    EditIdea,
    PublishIdea,
    RecuperateIdea,
    AbandonIdea,
    CommentIdea,
    PresentIdea,
    Associate,
    SeeIdea,
    CompareIdea,
    SubmitIdea,
    ArchiveIdea)
from novaideo import _

@process_definition(name='ideamanagement', id='ideamanagement')
class IdeaManagement(ProcessDefinition, VisualisableElement):
    isUnique = True

    def __init__(self, **kwargs):
        super(IdeaManagement, self).__init__(**kwargs)
        self.title = _('Ideas management')
        self.description = _('Ideas management')

    def _init_definition(self):
        self.defineNodes(
                start = StartEventDefinition(),
                #egs = ExclusiveGatewayDefinition(),
                creat = ActivityDefinition(contexts=[CreateIdea],
                                       description=_("Create an idea"),
                                       title=_("Create an idea"),
                                       groups=[_('Add')]),
                duplicate = ActivityDefinition(contexts=[DuplicateIdea],
                                       description=_("Duplicate this idea"),
                                       title=_("Duplicate"),
                                       groups=[]),
                delidea = ActivityDefinition(contexts=[DelIdea],
                                       description=_("Delete the idea"),
                                       title=_("Delete"),
                                       groups=[]),
                edit = ActivityDefinition(contexts=[EditIdea],
                                       description=_("Edit the idea"),
                                       title=_("Edit"),
                                       groups=[]),
                submit = ActivityDefinition(contexts=[SubmitIdea],
                                       description=_("Submit the idea"),
                                       title=_("Submit for publishing"),
                                       groups=[]),
                publish = ActivityDefinition(contexts=[PublishIdea],
                                       description=_("Publish the idea"),
                                       title=_("Publish"),
                                       groups=[]),
                archive = ActivityDefinition(contexts=[ArchiveIdea],
                                       description=_("Archive the idea"),
                                       title=_("Archive"),
                                       groups=[]),
                recuperate = ActivityDefinition(contexts=[RecuperateIdea],
                                       description=_("Recuperate the idea"),
                                       title=_("Recuperate"),
                                       groups=[]),
                abandon = ActivityDefinition(contexts=[AbandonIdea],
                                       description=_("Archive the idea"),
                                       title=_("Archive"),
                                       groups=[]),
                present = ActivityDefinition(contexts=[PresentIdea],
                                       description=_("Submit the idea to others"),
                                       title=_("Submit to others"),
                                       groups=[]),
                comment = ActivityDefinition(contexts=[CommentIdea],
                                       description=_("Discuss the idea"),
                                       title=_("Discuss"),
                                       groups=[]),
                associate = ActivityDefinition(contexts=[Associate],
                                       description=_("Associate the idea"),
                                       title=_("Associate"),
                                       groups=[]),
                see = ActivityDefinition(contexts=[SeeIdea],
                                       description=_("Details"),
                                       title=_("Details"),
                                       groups=[]),
                compare = ActivityDefinition(contexts=[CompareIdea],
                                       description=_("Compare versions"),
                                       title=_("Compare"),
                                       groups=[]),
                pg = ParallelGatewayDefinition(),
                eg = ExclusiveGatewayDefinition(),
                end = EndEventDefinition(),
        )
        self.defineTransitions(
                TransitionDefinition('start', 'pg'),
                TransitionDefinition('pg', 'creat'),
                TransitionDefinition('pg', 'duplicate'),
                TransitionDefinition('pg', 'edit'),
                TransitionDefinition('pg', 'submit'),
                TransitionDefinition('pg', 'archive'),
                TransitionDefinition('pg', 'publish'),
                TransitionDefinition('pg', 'delidea'),
                TransitionDefinition('pg', 'abandon'),
                TransitionDefinition('pg', 'recuperate'),
                TransitionDefinition('pg', 'comment'),
                TransitionDefinition('pg', 'present'),
                TransitionDefinition('pg', 'associate'),
                TransitionDefinition('pg', 'see'),
                TransitionDefinition('pg', 'compare'),
                TransitionDefinition('creat', 'eg'),
                TransitionDefinition('duplicate', 'eg'),
                TransitionDefinition('recuperate', 'eg'),
                TransitionDefinition('abandon', 'eg'),
                TransitionDefinition('submit', 'eg'),
                TransitionDefinition('publish', 'eg'),
                TransitionDefinition('archive', 'eg'),
                TransitionDefinition('delidea', 'eg'),
                TransitionDefinition('edit', 'eg'),
                TransitionDefinition('comment', 'eg'),
                TransitionDefinition('present', 'eg'),
                TransitionDefinition('associate', 'eg'),
                TransitionDefinition('see', 'eg'),
                TransitionDefinition('compare', 'eg'),
                TransitionDefinition('eg', 'end'),
        )
<commit_msg>new branche : examination<commit_after># Copyright (c) 2014 by Ecreall under licence AGPL terms
# avalaible on http://www.gnu.org/licenses/agpl.html

# licence: AGPL
# author: Amen Souissi
"""
This module represent the Idea management process definition
powered by the dace engine. This process is unique, which means that
this process is instantiated only once.
"""
from dace.processdefinition.processdef import ProcessDefinition
from dace.processdefinition.activitydef import ActivityDefinition
from dace.processdefinition.gatewaydef import (
    ExclusiveGatewayDefinition,
    ParallelGatewayDefinition)
from dace.processdefinition.transitiondef import TransitionDefinition
from dace.processdefinition.eventdef import (
    StartEventDefinition,
    EndEventDefinition)
from dace.objectofcollaboration.services.processdef_container import (
  process_definition)
from pontus.core import VisualisableElement

from .behaviors import (
    CreateIdea,
    DuplicateIdea,
    DelIdea,
    EditIdea,
    PublishIdea,
    RecuperateIdea,
    AbandonIdea,
    CommentIdea,
    PresentIdea,
    Associate,
    SeeIdea,
    CompareIdea,
    SubmitIdea,
    ArchiveIdea)
from novaideo import _

@process_definition(name='ideamanagement', id='ideamanagement')
class IdeaManagement(ProcessDefinition, VisualisableElement):
    isUnique = True

    def __init__(self, **kwargs):
        super(IdeaManagement, self).__init__(**kwargs)
        self.title = _('Ideas management')
        self.description = _('Ideas management')

    def _init_definition(self):
        self.defineNodes(
                start = StartEventDefinition(),
                #egs = ExclusiveGatewayDefinition(),
                creat = ActivityDefinition(contexts=[CreateIdea],
                                       description=_("Create an idea"),
                                       title=_("Create an idea"),
                                       groups=[_('Add')]),
                duplicate = ActivityDefinition(contexts=[DuplicateIdea],
                                       description=_("Duplicate this idea"),
                                       title=_("Duplicate"),
                                       groups=[]),
                delidea = ActivityDefinition(contexts=[DelIdea],
                                       description=_("Delete the idea"),
                                       title=_("Delete"),
                                       groups=[]),
                edit = ActivityDefinition(contexts=[EditIdea],
                                       description=_("Edit the idea"),
                                       title=_("Edit"),
                                       groups=[]),
                #TODO remove
                submit = ActivityDefinition(contexts=[SubmitIdea],
                                       description=_("Submit the idea"),
                                       title=_("Submit for publishing"),
                                       groups=[]),
                publish = ActivityDefinition(contexts=[PublishIdea],
                                       description=_("Publish the idea"),
                                       title=_("Publish"),
                                       groups=[]),
                archive = ActivityDefinition(contexts=[ArchiveIdea],
                                       description=_("Archive the idea"),
                                       title=_("Archive"),
                                       groups=[]),
                recuperate = ActivityDefinition(contexts=[RecuperateIdea],
                                       description=_("Recuperate the idea"),
                                       title=_("Recuperate"),
                                       groups=[]),
                abandon = ActivityDefinition(contexts=[AbandonIdea],
                                       description=_("Archive the idea"),
                                       title=_("Archive"),
                                       groups=[]),
                present = ActivityDefinition(contexts=[PresentIdea],
                                       description=_("Submit the idea to others"),
                                       title=_("Submit to others"),
                                       groups=[]),
                comment = ActivityDefinition(contexts=[CommentIdea],
                                       description=_("Discuss the idea"),
                                       title=_("Discuss"),
                                       groups=[]),
                associate = ActivityDefinition(contexts=[Associate],
                                       description=_("Associate the idea"),
                                       title=_("Associate"),
                                       groups=[]),
                see = ActivityDefinition(contexts=[SeeIdea],
                                       description=_("Details"),
                                       title=_("Details"),
                                       groups=[]),
                compare = ActivityDefinition(contexts=[CompareIdea],
                                       description=_("Compare versions"),
                                       title=_("Compare"),
                                       groups=[]),
                pg = ParallelGatewayDefinition(),
                eg = ExclusiveGatewayDefinition(),
                end = EndEventDefinition(),
        )
        self.defineTransitions(
                TransitionDefinition('start', 'pg'),
                TransitionDefinition('pg', 'creat'),
                TransitionDefinition('pg', 'duplicate'),
                TransitionDefinition('pg', 'edit'),
                TransitionDefinition('pg', 'submit'),
                TransitionDefinition('pg', 'archive'),
                TransitionDefinition('pg', 'publish'),
                TransitionDefinition('pg', 'delidea'),
                TransitionDefinition('pg', 'abandon'),
                TransitionDefinition('pg', 'recuperate'),
                TransitionDefinition('pg', 'comment'),
                TransitionDefinition('pg', 'present'),
                TransitionDefinition('pg', 'associate'),
                TransitionDefinition('pg', 'see'),
                TransitionDefinition('pg', 'compare'),
                TransitionDefinition('creat', 'eg'),
                TransitionDefinition('duplicate', 'eg'),
                TransitionDefinition('recuperate', 'eg'),
                TransitionDefinition('abandon', 'eg'),
                TransitionDefinition('submit', 'eg'),
                TransitionDefinition('publish', 'eg'),
                TransitionDefinition('archive', 'eg'),
                TransitionDefinition('delidea', 'eg'),
                TransitionDefinition('edit', 'eg'),
                TransitionDefinition('comment', 'eg'),
                TransitionDefinition('present', 'eg'),
                TransitionDefinition('associate', 'eg'),
                TransitionDefinition('see', 'eg'),
                TransitionDefinition('compare', 'eg'),
                TransitionDefinition('eg', 'end'),
        )
<|endoftext|>


<commit_before>#BEGIN_HEADER
from biokbase.workspace.client import Workspace as workspaceService
#END_HEADER

class MsneddonContigFilter:
    '''
    Module Name:
    MsneddonContigFilter

    Module Description:
    A KBase module: MsneddonContigFilter
This sample module contains one small method - count_contigs.
    '''

    ######## WARNING FOR GEVENT USERS #######
    # Since asynchronous IO can lead to methods - even the same method -
    # interrupting each other, you must be *very* careful when using global
    # state. A method could easily clobber the state set by another while
    # the latter method is running.
    #########################################
    #BEGIN_CLASS_HEADER
    workspaceURL = None
    #END_CLASS_HEADER

    # config contains contents of config file in a hash or None if it couldn't
    # be found
    def __init__(self, config):
        #BEGIN_CONSTRUCTOR
        self.workspaceURL = config['workspace-url']
        #END_CONSTRUCTOR
        pass

    def filter_contigs(self, ctx, workspace_name, contigset_id, min_length):
        # ctx is the context object
        # return variables are: returnVal
        #BEGIN filter_contigs

        token = ctx['token']
        ws = workspaceService(self.workspaceURL, token=token)
        contigSet = ws.get_objects([{'ref': workspace_name+'/'+contigset_id}])[0]['data']
        provenance = None
        if 'provenance' in ctx:
            provenance = ctx['provenance']
            # add additional info to provenance here if needed

        # save the contigs to a new list
        good_contigs = []
        n_total = 0;
        n_remaining = 0;
        for contig in contigSet['contigs']:
            n_total += 1
            if len(contig['sequence']) >= min_length:
                good_contigs.append(contig)
                n_remaining += 1

        # replace the contigs in the contigSet object in local memory
        contigSet['contigs'] = good_contigs

        # save the new object to the workspace
        obj_info_list = ws.save_objects({
                            'workspace':workspace_name,
                            'objects': [
                                {
                                    'type':'KBaseGenomes.ContigSet',
                                    'data':contigSet,
                                    'name':contigset_id,
                                    'provenance':provenance
                                }
                            ]
                        })
        info = obj_info_list[0]

        returnVal = {
                'new_contigset_ref': str(info[6]) + '/'+str(info[0])+'/'+str(info[4]),
                'n_initial_contigs':n_total,
                'n_contigs_removed':n_total-n_remaining,
                'n_contigs_remaining':n_remaining
            }
        #END filter_contigs

        # At some point might do deeper type checking...
        if not isinstance(returnVal, dict):
            raise ValueError('Method filter_contigs return value ' +
                             'returnVal is not type dict as required.')
        # return the results
        return [returnVal]
<commit_msg>added log messages<commit_after>#BEGIN_HEADER
from biokbase.workspace.client import Workspace as workspaceService
#END_HEADER

class MsneddonContigFilter:
    '''
    Module Name:
    MsneddonContigFilter

    Module Description:
    A KBase module: MsneddonContigFilter
This sample module contains one small method - count_contigs.
    '''

    ######## WARNING FOR GEVENT USERS #######
    # Since asynchronous IO can lead to methods - even the same method -
    # interrupting each other, you must be *very* careful when using global
    # state. A method could easily clobber the state set by another while
    # the latter method is running.
    #########################################
    #BEGIN_CLASS_HEADER
    workspaceURL = None
    #END_CLASS_HEADER

    # config contains contents of config file in a hash or None if it couldn't
    # be found
    def __init__(self, config):
        #BEGIN_CONSTRUCTOR
        self.workspaceURL = config['workspace-url']
        #END_CONSTRUCTOR
        pass

    def filter_contigs(self, ctx, workspace_name, contigset_id, min_length):
        # ctx is the context object
        # return variables are: returnVal
        #BEGIN filter_contigs
        print('Starting filter contigs method.')

        token = ctx['token']
        ws = workspaceService(self.workspaceURL, token=token)
        contigSet = ws.get_objects([{'ref': workspace_name+'/'+contigset_id}])[0]['data']
        provenance = None
        if 'provenance' in ctx:
            provenance = ctx['provenance']
            # add additional info to provenance here if needed

        print('Got ContigSet data.')

        # save the contigs to a new list
        good_contigs = []
        n_total = 0;
        n_remaining = 0;
        for contig in contigSet['contigs']:
            n_total += 1
            if len(contig['sequence']) >= min_length:
                good_contigs.append(contig)
                n_remaining += 1

        # replace the contigs in the contigSet object in local memory
        contigSet['contigs'] = good_contigs

        print('Filtered ContigSet to '+str(n_remaining)+' contigs out of '+str(n_total))

        # save the new object to the workspace
        obj_info_list = ws.save_objects({
                            'workspace':workspace_name,
                            'objects': [
                                {
                                    'type':'KBaseGenomes.ContigSet',
                                    'data':contigSet,
                                    'name':contigset_id,
                                    'provenance':provenance
                                }
                            ]
                        })
        info = obj_info_list[0]

        print('saved:'+str(info))

        returnVal = {
                'new_contigset_ref': str(info[6]) + '/'+str(info[0])+'/'+str(info[4]),
                'n_initial_contigs':n_total,
                'n_contigs_removed':n_total-n_remaining,
                'n_contigs_remaining':n_remaining
            }

        print('returning:'+str(returnVal))

        #END filter_contigs

        # At some point might do deeper type checking...
        if not isinstance(returnVal, dict):
            raise ValueError('Method filter_contigs return value ' +
                             'returnVal is not type dict as required.')
        # return the results
        return [returnVal]
<|endoftext|>


<commit_before>#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4 encoding=utf-8

from django.db import models

class NestedLocation(models.Model):
    """
    rapidsms.contrib.locations.nested makes the following assumptions about the
    needs of a deployment for its locations models:
        * They are concrete, heirarchical, and follow the same structure at every
          level (e.g. districts, subcounties, parishes, and towns are all
          more-or-less the same and serve solely as administrative boundaries.
        * They must be used for aggregation, and querying a subtree must be fast.
    This abstract class allows the default Location class in
    rapidsms.contrib.locations to inherit two additional fields:
     * name :
           As NestedLocations are concrete, they will have instances that
           need to be named.
     * tree_parent :
           As NestedLocations are uniformely typed, the need to have
           a non-generic relation to their parents.
    """
    tree_parent = models.ForeignKey('self', blank=True, null=True, related_name='children')

    class Meta:
        abstract = True
<commit_msg>update comments<commit_after>#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4 encoding=utf-8

from django.db import models

class NestedLocation(models.Model):
    """
    rapidsms.contrib.locations.nested makes the following assumptions about the
    needs of a deployment for its locations models:
        * They are concrete, heirarchical, and follow the same structure at every
          level (e.g. districts, subcounties, parishes, and towns are all
          more-or-less the same and serve solely as administrative boundaries.
        * They must be used for aggregation, and querying a subtree must be fast.
    This abstract class allows the default Location class in
    rapidsms.contrib.locations to inherit two additional fields:
     * tree_parent :
           As NestedLocations are uniformely typed, the need to have
           a non-generic relation to their parents.
    """
    tree_parent = models.ForeignKey('self', blank=True, null=True, related_name='children')

    class Meta:
        abstract = True
<|endoftext|>


<commit_before>import discord
import asyncio
import re
import os
from discord.ext import commands
from .utils.dataIO import dataIO
from __main__ import send_cmd_help

class Dates:

    """Create dates for the chat"""

    def __init__(self, bot):
        self.bot = bot
        self.dates_path = "data/dates/dates.json"
        self.dates = dataIO.load_json(self.dates_path)

    @commands.group(name="termin", pass_context=True)
    async def date(self, ctx):
        """ Verwaltet Termine fürs Team"""
        if ctx.invoked_subcommand is None:
            await send_cmd_help(ctx)

    @date.command(name="neu", pass_context=True)
    async def _new_date(self, ctx, date: str, time: str, note: str):
        """Erstelle einen neuen Termin."""

        newDate = (date, time, note)
        server = ctx.message.server
        if server.id not in self.dates:
            self.dates[server.id] = {}
        if date not in self.dates[server.id]:
            self.dates[server.id][date] = {}
        self.dates[server.id][date][time] = note
        dataIO.save_json(self.dates_path, self.dates)
        self.dates = dataIO.load_json(self.dates_path)
        await self.bot.say("Termin angelegt.")

    @date.command(name="liste", pass_context=True)
    async def _list_dates(self, ctx):
        """Listet alle Termine auf."""

        server = ctx.message.server
        dates = self.dates[server.id]
        embed = discord.Embed(title="Termine", color = 0x00c9f4)
        for date in dates:
            header = date
            for time in self.dates[server.id][date]:
                datetext = "*" + time + "* - " + self.dates[server.id][date][time]
                embed.add_field(name=header, value=datetext)
        await self.bot.say(embed=embed)

    @date.command(name="löschen", pass_context=True)
    async def _del_date(self, ctx, date: str, time: str):
        """Lösche einen Termin mit angegebenem Datum und Uhrzeit."""

        server = ctx.message.server
        if server.id in self.dates:
            if date in self.dates[server.id]:
                if time in self.dates[server.id][date]:
                    del self.dates[server.id][date][time]
                    await self.bot.say("Termin gelöscht.")

        if not self.dates[server.id][date]:
            del self.dates[server.id][date]

        dataIO.save_json(self.dates_path, self.dates)
        self.dates = dataIO.load_json(self.dates_path)

def check_folders():
    if not os.path.exists("data/dates"):
        print("Creating data/dates directory...")
        os.makedirs("data/dates")

def check_files():
    f = "data/dates/dates.json"
    if not dataIO.is_valid_json(f):
        print("Creating data/dates/dates.json...")
        dataIO.save_json(f, {})

def setup(bot):
    check_folders()
    check_files()
    n = Dates(bot)
    bot.add_cog(n)
<commit_msg>Changed format for the embed<commit_after>import discord
import asyncio
import re
import os
from discord.ext import commands
from .utils.dataIO import dataIO
from __main__ import send_cmd_help

class Dates:

    """Create dates for the chat"""

    def __init__(self, bot):
        self.bot = bot
        self.dates_path = "data/dates/dates.json"
        self.dates = dataIO.load_json(self.dates_path)

    @commands.group(name="termin", pass_context=True)
    async def date(self, ctx):
        """ Verwaltet Termine fürs Team"""
        if ctx.invoked_subcommand is None:
            await send_cmd_help(ctx)

    @date.command(name="neu", pass_context=True)
    async def _new_date(self, ctx, date: str, time: str, note: str):
        """Erstelle einen neuen Termin."""

        newDate = (date, time, note)
        server = ctx.message.server
        if server.id not in self.dates:
            self.dates[server.id] = {}
        if date not in self.dates[server.id]:
            self.dates[server.id][date] = {}
        self.dates[server.id][date][time] = note
        dataIO.save_json(self.dates_path, self.dates)
        self.dates = dataIO.load_json(self.dates_path)
        await self.bot.say("Termin angelegt.")

    @date.command(name="liste", pass_context=True)
    async def _list_dates(self, ctx):
        """Listet alle Termine auf."""

        server = ctx.message.server
        dates = self.dates[server.id]
        embed = discord.Embed(title="Termine", color = 0x00c9f4)
        datetext = ""
        for date in dates:
            header = date
            for time in self.dates[server.id][date]:
                datetext += "*" + time + "* - " + self.dates[server.id][date][time] + "\n"
            embed.add_field(name=header, value=datetext)
        await self.bot.say(embed=embed)

    @date.command(name="löschen", pass_context=True)
    async def _del_date(self, ctx, date: str, time: str):
        """Lösche einen Termin mit angegebenem Datum und Uhrzeit."""

        server = ctx.message.server
        if server.id in self.dates:
            if date in self.dates[server.id]:
                if time in self.dates[server.id][date]:
                    del self.dates[server.id][date][time]
                    await self.bot.say("Termin gelöscht.")

        if not self.dates[server.id][date]:
            del self.dates[server.id][date]

        dataIO.save_json(self.dates_path, self.dates)
        self.dates = dataIO.load_json(self.dates_path)

def check_folders():
    if not os.path.exists("data/dates"):
        print("Creating data/dates directory...")
        os.makedirs("data/dates")

def check_files():
    f = "data/dates/dates.json"
    if not dataIO.is_valid_json(f):
        print("Creating data/dates/dates.json...")
        dataIO.save_json(f, {})

def setup(bot):
    check_folders()
    check_files()
    n = Dates(bot)
    bot.add_cog(n)
<|endoftext|>


<commit_before>#!/usr/bin/python

import time
import threading

import SimpleXMLRPCServer,signal,sys,xmlrpclib
import SocketServer
import socket
import logging
import os

try:
	from ssl import *
	HAS_SSL = True
except ImportError:
	HAS_SSL = False

_service={}
_group={}
_res_id=1
_res={}

class ServiceEndPointCall(object):
	def __init__(self,id,method):
		self._id=id
		self._meth=method
	def __call__(self,*args):
		_res[self._id]=self._meth(*args)
		return self._id

class ServiceEndPoint(object):
	def __init__(self, name, id):
		self._id = id
		self._meth={}
		print _service
		s=_service[name]
		for m in s._method:
			self._meth[m]=s._method[m]
	def __getattr__(self, name):
		return ServiceEndPointCall(self._id, self._meth[name])

class Service(object):
	_serviceEndPointID = 0
	def __init__(self, name, audience=''):
		_service[name]=self
		self.__name=name
		self._method={}
		self.exportedMethods=None
		self._response_process=None
		self._response_process_id=None
		self._response=None

	def joinGroup(self,name):
		if not name in _group:
			_group[name]={}
		_group[name][self.__name]=self

	def exportMethod(self, m):
		if callable(m):
			self._method[m.__name__]=m

	def serviceEndPoint(self,s):
		if Service._serviceEndPointID >= 2**16:
			Service._serviceEndPointID = 0
		Service._serviceEndPointID += 1
		return ServiceEndPoint(s, self._serviceEndPointID)

	def conversationId(self):
		return 1

	def processResponse(self,s,id):
		self._response_process, self._response_process_id = s, id

	def processFailure(self,s,id):
		pass

	def resumeResponse(self,s):
		pass

	def cancelResponse(self,s):
		pass

	def suspendResponse(self,s):
		if self._response_process:
			self._response_process(self._response_process_id,
								   _res[self._response_process_id])
		self._response_process=None
		self._response=s(self._response_process_id)

	def abortResponse(self,error, description, origin, details):
		import tools
		if not tools.config['debug_mode']:
			raise Exception("%s -- %s\n\n%s"%(origin,description,details))
		else:
			raise

	def currentFailure(self,s):
		pass

class LocalService(Service):
	def __init__(self, name):
		self.__name=name
		s=_service[name]
		self._service=s
		for m in s._method:
			setattr(self,m,s._method[m])

class ServiceUnavailable(Exception):
	pass

LOG_DEBUG='debug'
LOG_INFO='info'
LOG_WARNING='warn'
LOG_ERROR='error'
LOG_CRITICAL='critical'

def init_logger():
	from tools import config
	import os

	if config['logfile']:
		logf = config['logfile']
		# test if the directories exist, else create them
		try:
			if not os.path.exists(os.path.dirname(logf)):
				os.makedirs(os.path.dirname(logf))
			try:
				fd = open(logf, 'a')
				handler = logging.StreamHandler(fd)
			except IOError:
				sys.stderr.write("ERROR: couldn't open the logfile\n")
				handler = logging.StreamHandler(sys.stdout)
		except OSError:
			sys.stderr.write("ERROR: couldn't create the logfile directory\n")
			handler = logging.StreamHandler(sys.stdout)
	else:
		handler = logging.StreamHandler(sys.stdout)

	# create a format for log messages and dates
	formatter = logging.Formatter('%(asctime)s %(levelname)s:%(name)s:%(message)s', '%a, %d %b %Y %H:%M:%S')

	# tell the handler to use this format
	handler.setFormatter(formatter)

	# add the handler to the root logger
	logging.getLogger().addHandler(handler)
	logging.getLogger().setLevel(logging.INFO)

class Logger(object):
	def notifyChannel(self,name,level,msg):
		log = logging.getLogger(name)
		getattr(log,level)(msg)

class Agent(object):
	_timers = []
	_logger = Logger()

	def setAlarm(self, fn, dt, args=[], kwargs={}):
		wait = dt - time.time()
		if wait > 0:
			self._logger.notifyChannel(
					'timers', LOG_DEBUG,
					"Job scheduled in %s seconds for %s.%s" % (wait,
															   fn.im_class.__name__,
												fn.func_name))
			timer = threading.Timer(wait, fn, args, kwargs)
			timer.start()
			self._timers.append(timer)
		for timer in self._timers[:]:
			if not timer.isAlive():
				self._timers.remove(timer)

	def quit(cls):
		for timer in cls._timers:
			timer.cancel()
	quit=classmethod(quit)

class RpcGateway(object):
	def __init__(self, name):
		self.name=name

class Dispatcher(object):
	def __init__(self):
		pass
	def monitor(self,signal):
		pass
	def run(self):
		pass

class xmlrpc(object):
	class RpcGateway(object):
		def __init__(self, name):
			self.name=name

class GenericXMLRPCRequestHandler:
	def _dispatch(self, method, params):
		import traceback
		try:
			n=self.path.split("/")[-1]
			s=LocalService(n)
			m=getattr(s,method)
			s._service._response=None
			r=m(*params)
			res=s._service._response
			if res!=None:
				r=res
			return r
		except Exception,e:
			logger = Logger()
			logger.notifyChannel("web-services", LOG_ERROR, 'Exception in call: ' + reduce(lambda x, y: x+y, traceback.format_exc()))
			s=str(e)
			import tools
			if tools.config['debug_mode']:
				import pdb
				tb = sys.exc_info()[2]
				pdb.post_mortem(tb)
			raise xmlrpclib.Fault(1,s)

class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
	pass

if HAS_SSL:
	class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler):
		pass
else:
	pass

class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
	def server_bind(self):
		self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)

if HAS_SSL:
	class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer):
		def server_bind(self):
			self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
			SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self)
else:
	pass

class HttpDaemon(threading.Thread):
	def __init__(self, interface,port, secure=False):
		threading.Thread.__init__(self)
		self.__port=port
		self.__interface=interface
		if secure and HAS_SSL:
			self.server = SecureThreadedXMLRPCServer((interface, port), SecureXMLRPCRequestHandler,0)
		else:
			self.server = SimpleThreadedXMLRPCServer((interface, port), SimpleXMLRPCRequestHandler,0)

	def attach(self,path,gw):
		pass

	def stop(self):
		self.running = False
		if hasattr(socket, 'SHUT_RDWR'):
			self.server.socket.shutdown(socket.SHUT_RDWR)
		else:
			self.server.socket.shutdown(2)
		self.server.socket.close()

	def run(self):
		self.server.register_introspection_functions()

		self.running = True
		while self.running:
			self.server.handle_request()
		return True

		# If the server need to be run recursively
		#
		#signal.signal(signal.SIGALRM, self.my_handler)
		#signal.alarm(6)
		#while True:
		#	self.server.handle_request()
		#signal.alarm(0)          # Disable the alarm

import tiny_socket
class TinySocketClientThread(threading.Thread):
	def __init__(self, sock, threads):
		threading.Thread.__init__(self)
		self.sock = sock
		self.threads = threads

	def run(self):
		import traceback
		import time
		import select
		try:
			self.running = True
			ts = tiny_socket.mysocket(self.sock)
			while self.running:
				msg = ts.myreceive()

				try:
					s=LocalService(msg[0])
					m=getattr(s,msg[1])
					s._service._response=None
					r=m(*msg[2:])
					res=s._service._response
					if res!=None:
						r=res
					ts.mysend(r)
				except Exception, e:
					logger = Logger()
					logger.notifyChannel("web-services", LOG_ERROR, 'Exception in call: ' + reduce(lambda x, y: x+y, traceback.format_exc()))
					s=str(e)
					import tools
					if tools.config['debug_mode']:
						import pdb
						tb = sys.exc_info()[2]
						pdb.post_mortem(tb)
					ts.mysend(e, exception=True)
				self.sock.close()
				self.threads.remove(self)
				return True
		except Exception, e:
			self.sock.close()
			return False
	def stop(self):
		self.running = False

class TinySocketServerThread(threading.Thread):
	def __init__(self, interface, port, secure=False):
		threading.Thread.__init__(self)
		self.__port=port
		self.__interface=interface
		self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self.socket.bind((self.__interface, self.__port))
		self.socket.listen(5)
		self.threads = []

	def run(self):
		import select
		try:
			self.running = True
			while self.running:
				(clientsocket, address) = self.socket.accept()
				ct = TinySocketClientThread(clientsocket, self.threads)
				ct.start()
				self.threads.append(ct)
			self.socket.close()
		except Exception, e:
			self.socket.close()
			return False

	def stop(self):
		self.running=False
		for t in self.threads:
			t.stop()
		try:
			if hasattr(socket, 'SHUT_RDWR'):
				self.socket.shutdown(socket.SHUT_RDWR)
			else:
				self.socket.shutdown(2)
			self.socket.close()
		except:
			return False

# vim:noexpandtab:

<commit_msg>KERNEL: use python 2.3 format_exception<commit_after>#!/usr/bin/python

import time
import threading

import SimpleXMLRPCServer,signal,sys,xmlrpclib
import SocketServer
import socket
import logging
import os

try:
	from ssl import *
	HAS_SSL = True
except ImportError:
	HAS_SSL = False

_service={}
_group={}
_res_id=1
_res={}

class ServiceEndPointCall(object):
	def __init__(self,id,method):
		self._id=id
		self._meth=method
	def __call__(self,*args):
		_res[self._id]=self._meth(*args)
		return self._id

class ServiceEndPoint(object):
	def __init__(self, name, id):
		self._id = id
		self._meth={}
		print _service
		s=_service[name]
		for m in s._method:
			self._meth[m]=s._method[m]
	def __getattr__(self, name):
		return ServiceEndPointCall(self._id, self._meth[name])

class Service(object):
	_serviceEndPointID = 0
	def __init__(self, name, audience=''):
		_service[name]=self
		self.__name=name
		self._method={}
		self.exportedMethods=None
		self._response_process=None
		self._response_process_id=None
		self._response=None

	def joinGroup(self,name):
		if not name in _group:
			_group[name]={}
		_group[name][self.__name]=self

	def exportMethod(self, m):
		if callable(m):
			self._method[m.__name__]=m

	def serviceEndPoint(self,s):
		if Service._serviceEndPointID >= 2**16:
			Service._serviceEndPointID = 0
		Service._serviceEndPointID += 1
		return ServiceEndPoint(s, self._serviceEndPointID)

	def conversationId(self):
		return 1

	def processResponse(self,s,id):
		self._response_process, self._response_process_id = s, id

	def processFailure(self,s,id):
		pass

	def resumeResponse(self,s):
		pass

	def cancelResponse(self,s):
		pass

	def suspendResponse(self,s):
		if self._response_process:
			self._response_process(self._response_process_id,
								   _res[self._response_process_id])
		self._response_process=None
		self._response=s(self._response_process_id)

	def abortResponse(self,error, description, origin, details):
		import tools
		if not tools.config['debug_mode']:
			raise Exception("%s -- %s\n\n%s"%(origin,description,details))
		else:
			raise

	def currentFailure(self,s):
		pass

class LocalService(Service):
	def __init__(self, name):
		self.__name=name
		s=_service[name]
		self._service=s
		for m in s._method:
			setattr(self,m,s._method[m])

class ServiceUnavailable(Exception):
	pass

LOG_DEBUG='debug'
LOG_INFO='info'
LOG_WARNING='warn'
LOG_ERROR='error'
LOG_CRITICAL='critical'

def init_logger():
	from tools import config
	import os

	if config['logfile']:
		logf = config['logfile']
		# test if the directories exist, else create them
		try:
			if not os.path.exists(os.path.dirname(logf)):
				os.makedirs(os.path.dirname(logf))
			try:
				fd = open(logf, 'a')
				handler = logging.StreamHandler(fd)
			except IOError:
				sys.stderr.write("ERROR: couldn't open the logfile\n")
				handler = logging.StreamHandler(sys.stdout)
		except OSError:
			sys.stderr.write("ERROR: couldn't create the logfile directory\n")
			handler = logging.StreamHandler(sys.stdout)
	else:
		handler = logging.StreamHandler(sys.stdout)

	# create a format for log messages and dates
	formatter = logging.Formatter('%(asctime)s %(levelname)s:%(name)s:%(message)s', '%a, %d %b %Y %H:%M:%S')

	# tell the handler to use this format
	handler.setFormatter(formatter)

	# add the handler to the root logger
	logging.getLogger().addHandler(handler)
	logging.getLogger().setLevel(logging.INFO)

class Logger(object):
	def notifyChannel(self,name,level,msg):
		log = logging.getLogger(name)
		getattr(log,level)(msg)

class Agent(object):
	_timers = []
	_logger = Logger()

	def setAlarm(self, fn, dt, args=[], kwargs={}):
		wait = dt - time.time()
		if wait > 0:
			self._logger.notifyChannel(
					'timers', LOG_DEBUG,
					"Job scheduled in %s seconds for %s.%s" % (wait,
															   fn.im_class.__name__,
												fn.func_name))
			timer = threading.Timer(wait, fn, args, kwargs)
			timer.start()
			self._timers.append(timer)
		for timer in self._timers[:]:
			if not timer.isAlive():
				self._timers.remove(timer)

	def quit(cls):
		for timer in cls._timers:
			timer.cancel()
	quit=classmethod(quit)

class RpcGateway(object):
	def __init__(self, name):
		self.name=name

class Dispatcher(object):
	def __init__(self):
		pass
	def monitor(self,signal):
		pass
	def run(self):
		pass

class xmlrpc(object):
	class RpcGateway(object):
		def __init__(self, name):
			self.name=name

class GenericXMLRPCRequestHandler:
	def _dispatch(self, method, params):
		import traceback
		try:
			n=self.path.split("/")[-1]
			s=LocalService(n)
			m=getattr(s,method)
			s._service._response=None
			r=m(*params)
			res=s._service._response
			if res!=None:
				r=res
			return r
		except Exception,e:
			logger = Logger()
			logger.notifyChannel("web-services", LOG_ERROR, 'Exception in call: ' + reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)))
			s=str(e)
			import tools
			if tools.config['debug_mode']:
				import pdb
				tb = sys.exc_info()[2]
				pdb.post_mortem(tb)
			raise xmlrpclib.Fault(1,s)

class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
	pass

if HAS_SSL:
	class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler):
		pass
else:
	pass

class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
	def server_bind(self):
		self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)

if HAS_SSL:
	class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer):
		def server_bind(self):
			self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
			SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self)
else:
	pass

class HttpDaemon(threading.Thread):
	def __init__(self, interface,port, secure=False):
		threading.Thread.__init__(self)
		self.__port=port
		self.__interface=interface
		if secure and HAS_SSL:
			self.server = SecureThreadedXMLRPCServer((interface, port), SecureXMLRPCRequestHandler,0)
		else:
			self.server = SimpleThreadedXMLRPCServer((interface, port), SimpleXMLRPCRequestHandler,0)

	def attach(self,path,gw):
		pass

	def stop(self):
		self.running = False
		if hasattr(socket, 'SHUT_RDWR'):
			self.server.socket.shutdown(socket.SHUT_RDWR)
		else:
			self.server.socket.shutdown(2)
		self.server.socket.close()

	def run(self):
		self.server.register_introspection_functions()

		self.running = True
		while self.running:
			self.server.handle_request()
		return True

		# If the server need to be run recursively
		#
		#signal.signal(signal.SIGALRM, self.my_handler)
		#signal.alarm(6)
		#while True:
		#	self.server.handle_request()
		#signal.alarm(0)          # Disable the alarm

import tiny_socket
class TinySocketClientThread(threading.Thread):
	def __init__(self, sock, threads):
		threading.Thread.__init__(self)
		self.sock = sock
		self.threads = threads

	def run(self):
		import traceback
		import time
		import select
		try:
			self.running = True
			ts = tiny_socket.mysocket(self.sock)
			while self.running:
				msg = ts.myreceive()

				try:
					s=LocalService(msg[0])
					m=getattr(s,msg[1])
					s._service._response=None
					r=m(*msg[2:])
					res=s._service._response
					if res!=None:
						r=res
					ts.mysend(r)
				except Exception, e:
					logger = Logger()
					logger.notifyChannel("web-services", LOG_ERROR, 'Exception in call: ' + reduce(lambda x, y: x+y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)))
					s=str(e)
					import tools
					if tools.config['debug_mode']:
						import pdb
						tb = sys.exc_info()[2]
						pdb.post_mortem(tb)
					ts.mysend(e, exception=True)
				self.sock.close()
				self.threads.remove(self)
				return True
		except Exception, e:
			self.sock.close()
			return False
	def stop(self):
		self.running = False

class TinySocketServerThread(threading.Thread):
	def __init__(self, interface, port, secure=False):
		threading.Thread.__init__(self)
		self.__port=port
		self.__interface=interface
		self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		self.socket.bind((self.__interface, self.__port))
		self.socket.listen(5)
		self.threads = []

	def run(self):
		import select
		try:
			self.running = True
			while self.running:
				(clientsocket, address) = self.socket.accept()
				ct = TinySocketClientThread(clientsocket, self.threads)
				ct.start()
				self.threads.append(ct)
			self.socket.close()
		except Exception, e:
			self.socket.close()
			return False

	def stop(self):
		self.running=False
		for t in self.threads:
			t.stop()
		try:
			if hasattr(socket, 'SHUT_RDWR'):
				self.socket.shutdown(socket.SHUT_RDWR)
			else:
				self.socket.shutdown(2)
			self.socket.close()
		except:
			return False

# vim:noexpandtab:

<|endoftext|>


<commit_before>"""
Codes for correcting the differential phase and estimating KDP.

@title: phase
@author: Valentin Louf <valentin.louf@monash.edu>
@institutions: Monash University and the Australian Bureau of Meteorology
@date: 20/11/2017

.. autosummary::
    :toctree: generated/

    check_phidp
    fix_phidp_from_kdp
    phidp_bringi
    phidp_giangrande
    unfold_raw_phidp
"""
# Python Standard Library
import time
import datetime

# Other Libraries
import pyart
import scipy
import netCDF4
import numpy as np

from scipy import integrate
from csu_radartools import csu_kdp

def check_phidp(radar, phi_name="PHIDP"):
    """
    Check if PHIDP range is 180 degrees (half-circle) or 360 degrees.
    Parameters:
    ===========
    radar:
        Py-ART radar structure.
    phi_name: str
        Name of the PHIDP field.

    Return:
    =======
    half_phi: bool
        Is PHIDP range is half circle.
    """
    phi = radar.fields[phi_name]['data']
    if phi.max() - phi.min() <= 200:  # 180 degrees plus some margin for noise...
        half_phi = True
    else:
        half_phi = False

    return half_phi

def fix_phidp_from_kdp(radar, gatefilter, kdp_name="KDP_BRINGI", phidp_name="PHIDP_BRINGI"):
    """
    Correct PHIDP and KDP from spider webs.

    Parameters
    ==========
    radar:
        Py-ART radar data structure.
    gatefilter:
        Gate filter.
    kdp_name: str
        Differential phase key name.
    phidp_name: str
        Differential phase key name.

    Returns:
    ========
    phidp: ndarray
        Differential phase array.
    """
    kdp = radar.fields[kdp_name]['data'].copy()
    phidp = radar.fields[phidp_name]['data'].copy()
    kdp[gatefilter.gate_excluded] = 0
    kdp[(kdp < -2)] = 0
    kdp[kdp > 10] = 10
    interg = integrate.cumtrapz(kdp, radar.range['data'], axis=1)

    phidp[:, :-1] = interg / (len(radar.range['data']))
    return phidp

def phidp_bringi(radar, gatefilter, unfold_phidp_name="PHI_UNF", ncp_name="NCP", rhohv_name="RHOHV_CORR", refl_field='DBZ'):
    """
    Compute PHIDP and KDP Bringi.

    Parameters
    ==========
    radar:
        Py-ART radar data structure.
    gatefilter:
        Gate filter.
    unfold_phidp_name: str
        Differential phase key name.
    refl_field: str
        Reflectivity key name.

    Returns:
    ========
    phidpb: ndarray
        Bringi differential phase array.
    kdpb: ndarray
        Bringi specific differential phase array.
    """
    dp = radar.fields[unfold_phidp_name]['data'].copy()
    dz = radar.fields[refl_field]['data'].copy().filled(-9999)

    # Extract dimensions
    rng = radar.range['data']
    azi = radar.azimuth['data']
    dgate = rng[1] - rng[0]
    [R, A] = np.meshgrid(rng, azi)

    # Compute KDP bringi.
    kdpb, phidpb, _ = csu_kdp.calc_kdp_bringi(dp, dz, R / 1e3, gs=dgate, bad=-9999)

    # Mask array
    phidpb = np.ma.masked_where(phidpb == -9999, phidpb)
    kdpb = np.ma.masked_where(kdpb == -9999, kdpb)

    # Get metadata.
    phimeta = pyart.config.get_metadata("differential_phase")
    phimeta['data'] = phidpb
    kdpmeta = pyart.config.get_metadata("specific_differential_phase")
    kdpmeta['data'] = kdpb

    return phimeta, kdpmeta

def phidp_giangrande(radar, gatefilter, refl_field='DBZ', ncp_field='NCP',
                     rhv_field='RHOHV_CORR', phidp_field='PHI_UNF'):
    """
    Phase processing using the LP method in Py-ART. A LP solver is required,

    Parameters:
    ===========
        radar:
            Py-ART radar structure.
        refl_field: str
            Reflectivity field name.
        ncp_field: str
            Normalised coherent power field name.
        rhv_field: str
            Cross correlation ration field name.
        phidp_field: str
            Phase field name.

    Returns:
    ========
        phidp_gg: dict
            Field dictionary containing processed differential phase shifts.
        kdp_gg: dict
            Field dictionary containing recalculated differential phases.
    """
    phidp_gg, kdp_gg = pyart.correct.phase_proc_lp(radar, 0.0,
                                                   min_rhv=0.95,
                                                   LP_solver='cylp',
                                                   refl_field=refl_field,
                                                   ncp_field=ncp_field,
                                                   rhv_field=rhv_field,
                                                   phidp_field=phidp_field)

    return phidp_gg, kdp_gg

def unfold_raw_phidp(radar, gatefilter, phi_name="PHIDP"):
    """
    Unfold raw PHIDP

    Parameters:
    ===========
    radar:
        Py-ART radar structure.
    gatefilter:
        Gate filter.
    phi_name: str
        Name of the PHIDP field.

    Returns:
    ========
    tru_phi: ndarray
        Unfolded raw PHIDP.
    """
    # Extract data
    phi = radar.fields[phi_name]['data'].copy()
    # For CPOL, PHIDP is properly unfolded before season 2003/2004
    CPOL_DATE_PHIDP_FOLD = datetime.datetime(2003, 10, 1)
    dtime = netCDF4.num2date(radar.time['data'][0], radar.time['units'])
    if dtime < CPOL_DATE_PHIDP_FOLD:
        tru_phi = phi
    else:
        tru_phi = phi + 180
        pmin = phi[gatefilter.gate_included].min()
        tru_phi -= pmin
        tru_phi[tru_phi > 360] -= 360

    return tru_phi
<commit_msg>Improve BRINGI.<commit_after>"""
Codes for correcting the differential phase and estimating KDP.

@title: phase
@author: Valentin Louf <valentin.louf@monash.edu>
@institutions: Monash University and the Australian Bureau of Meteorology
@date: 20/11/2017

.. autosummary::
    :toctree: generated/

    check_phidp
    fix_phidp_from_kdp
    phidp_bringi
    phidp_giangrande
    unfold_raw_phidp
"""
# Python Standard Library
import time
import datetime

# Other Libraries
import pyart
import scipy
import netCDF4
import numpy as np

from scipy import integrate
from csu_radartools import csu_kdp

def check_phidp(radar, phi_name="PHIDP"):
    """
    Check if PHIDP range is 180 degrees (half-circle) or 360 degrees.
    Parameters:
    ===========
    radar:
        Py-ART radar structure.
    phi_name: str
        Name of the PHIDP field.

    Return:
    =======
    half_phi: bool
        Is PHIDP range is half circle.
    """
    phi = radar.fields[phi_name]['data']
    if phi.max() - phi.min() <= 200:  # 180 degrees plus some margin for noise...
        half_phi = True
    else:
        half_phi = False

    return half_phi

def fix_phidp_from_kdp(radar, gatefilter, kdp_name="KDP_BRINGI", phidp_name="PHIDP_BRINGI"):
    """
    Correct PHIDP and KDP from spider webs.

    Parameters
    ==========
    radar:
        Py-ART radar data structure.
    gatefilter:
        Gate filter.
    kdp_name: str
        Differential phase key name.
    phidp_name: str
        Differential phase key name.

    Returns:
    ========
    phidp: ndarray
        Differential phase array.
    """
    kdp = radar.fields[kdp_name]['data'].copy()
    phidp = radar.fields[phidp_name]['data'].copy()
    kdp[gatefilter.gate_excluded] = 0
    kdp[(kdp < -2)] = 0
    kdp[kdp > 10] = 10
    interg = integrate.cumtrapz(kdp, radar.range['data'], axis=1)

    phidp[:, :-1] = interg / (len(radar.range['data']))
    return phidp

def phidp_bringi(radar, gatefilter, unfold_phidp_name="PHI_UNF", ncp_name="NCP", rhohv_name="RHOHV_CORR", refl_field='DBZ'):
    """
    Compute PHIDP and KDP Bringi.

    Parameters
    ==========
    radar:
        Py-ART radar data structure.
    gatefilter:
        Gate filter.
    unfold_phidp_name: str
        Differential phase key name.
    refl_field: str
        Reflectivity key name.

    Returns:
    ========
    phidpb: ndarray
        Bringi differential phase array.
    kdpb: ndarray
        Bringi specific differential phase array.
    """
    dp = radar.fields[unfold_phidp_name]['data'].copy()
    dz = radar.fields[refl_field]['data'].copy().filled(-9999)

    # Extract dimensions
    rng = radar.range['data']
    azi = radar.azimuth['data']
    dgate = rng[1] - rng[0]
    [R, A] = np.meshgrid(rng, azi)

    # Compute KDP bringi.
    kdpb, phidpb, _ = csu_kdp.calc_kdp_bringi(dp, dz, R / 1e3, gs=dgate, bad=-9999, nfilter=3, thsd=24)

    # Mask array
    # phidpb = np.ma.masked_where(phidpb == -9999, phidpb)
    kdpb = np.ma.masked_where(kdpb == -9999, kdpb)
    phi2 = np.cumsum(kdpb.filled(0), axis=1)

    # Get metadata.
    phimeta = pyart.config.get_metadata("differential_phase")
    phimeta['data'] = phi2
    kdpmeta = pyart.config.get_metadata("specific_differential_phase")
    kdpmeta['data'] = kdpb

    return phimeta, kdpmeta

def phidp_giangrande(radar, gatefilter, refl_field='DBZ', ncp_field='NCP',
                     rhv_field='RHOHV_CORR', phidp_field='PHI_UNF'):
    """
    Phase processing using the LP method in Py-ART. A LP solver is required,

    Parameters:
    ===========
        radar:
            Py-ART radar structure.
        refl_field: str
            Reflectivity field name.
        ncp_field: str
            Normalised coherent power field name.
        rhv_field: str
            Cross correlation ration field name.
        phidp_field: str
            Phase field name.

    Returns:
    ========
        phidp_gg: dict
            Field dictionary containing processed differential phase shifts.
        kdp_gg: dict
            Field dictionary containing recalculated differential phases.
    """
    phidp_gg, kdp_gg = pyart.correct.phase_proc_lp(radar, 0.0,
                                                   min_rhv=0.95,
                                                   LP_solver='cylp',
                                                   refl_field=refl_field,
                                                   ncp_field=ncp_field,
                                                   rhv_field=rhv_field,
                                                   phidp_field=phidp_field)

    return phidp_gg, kdp_gg

def unfold_raw_phidp(radar, gatefilter, phi_name="PHIDP"):
    """
    Unfold raw PHIDP

    Parameters:
    ===========
    radar:
        Py-ART radar structure.
    gatefilter:
        Gate filter.
    phi_name: str
        Name of the PHIDP field.

    Returns:
    ========
    tru_phi: ndarray
        Unfolded raw PHIDP.
    """
    # Extract data
    phi = radar.fields[phi_name]['data'].copy()
    # For CPOL, PHIDP is properly unfolded before season 2003/2004
    CPOL_DATE_PHIDP_FOLD = datetime.datetime(2003, 10, 1)
    dtime = netCDF4.num2date(radar.time['data'][0], radar.time['units'])
    if dtime < CPOL_DATE_PHIDP_FOLD:
        tru_phi = phi
    else:
        tru_phi = phi + 180
        pmin = tru_phi[gatefilter.gate_included].min()
        tru_phi -= pmin
        tru_phi[tru_phi > 360] -= 360

    return tru_phi
<|endoftext|>