# Path: charms/reactive/flags.py
# @cmdline.subcommand()
# def get_flags():
#     """
#     Return a list of all flags which are set.
#     """
#     flags = unitdata.kv().getrange('reactive.states.', strip=True) or {}
#     return sorted(flags.keys())
# 
# Path: charms/reactive/flags.py
# def _get_flag_value(flag, default=None):
#     return unitdata.kv().get('reactive.states.%s' % flag, default)
# 
# Path: charms/reactive/flags.py
# @cmdline.subcommand()
# @cmdline.no_output
# def set_flag(flag, value=None):
#     """set_flag(flag)
#     Set the given flag as active.
# 
#     :param str flag: Name of flag to set.
# 
#     .. note:: **Changes to flags are reset when a handler crashes.** Changes to
#        flags happen immediately, but they are only persisted at the end of a
#        complete and successful run of the reactive framework. All unpersisted
#        changes are discarded when a hook crashes.
#     """
#     old_flags = get_flags()
#     unitdata.kv().update({flag: value}, prefix='reactive.states.')
#     if flag not in old_flags:
#         tracer().set_flag(flag)
#         FlagWatch.change(flag)
#         trigger = _get_trigger(flag, None)
#         for flag_name in trigger['set_flag']:
#             set_flag(flag_name)
#         for flag_name in trigger['clear_flag']:
#             clear_flag(flag_name)
#         for callback in trigger['callbacks']:
#             callback()
# 
# Path: charms/reactive/flags.py
# @cmdline.subcommand()
# @cmdline.no_output
# def clear_flag(flag):
#     """
#     Clear / deactivate a flag.
# 
#     :param str flag: Name of flag to set.
# 
#     .. note:: **Changes to flags are reset when a handler crashes.** Changes to
#        flags happen immediately, but they are only persisted at the end of a
#        complete and successful run of the reactive framework. All unpersisted
#        changes are discarded when a hook crashes.
#     """
#     old_flags = get_flags()
#     unitdata.kv().unset('reactive.states.%s' % flag)
#     unitdata.kv().set('reactive.dispatch.removed_state', True)
#     if flag in old_flags:
#         tracer().clear_flag(flag)
#         FlagWatch.change(flag)
#         trigger = _get_trigger(None, flag)
#         for flag_name in trigger['set_flag']:
#             set_flag(flag_name)
#         for flag_name in trigger['clear_flag']:
#             clear_flag(flag_name)
#         for callback in trigger['callbacks']:
#             callback()
# 
# Path: charms/reactive/flags.py
# class StateList(object):
#     """
#     .. deprecated:: 0.5.0
#        use flag instead
# 
#     Base class for a set of states that can be set by a relation or layer.
# 
#     This class should be used so that they can be discovered and introspected,
#     for documentation, composition, or linting.
# 
#     Example usage::
# 
#         class MyRelation(RelationBase):
#             class states(StateList):
#                 connected = State('{relation_name}.connected')
#                 available = State('{relation_name}.available')
#     """
#     pass
# 
# Path: charms/reactive/bus.py
# def _append_path(d):
#     if d not in sys.path:
#         sys.path.append(d)


import os
import sys
import importlib
from inspect import isclass
from charmhelpers.core import hookenv
from charmhelpers.core import unitdata
from charmhelpers.cli import cmdline
from charms.reactive.flags import get_flags
from charms.reactive.flags import _get_flag_value
from charms.reactive.flags import set_flag
from charms.reactive.flags import clear_flag
from charms.reactive.flags import StateList
from charms.reactive.bus import _append_path
    from importlib.metadata import entry_points
    from pkg_resources import iter_entry_points

    @classmethod
    def from_flag(cls, state):
        raise NotImplementedError()


def relation_factory(relation_name):
    """Get the RelationFactory for the given relation name.

    Looks for a RelationFactory in the first file matching:
    ``$CHARM_DIR/hooks/relations/{interface}/{provides,requires,peer}.py``
    """
    factory = RelationFactory.get_factory(relation_name)
    if factory:
        return factory
    role, interface = hookenv.relation_to_role_and_interface(relation_name)
    if not (role and interface):
        hookenv.log('Unable to determine role and interface for relation '
                    '{}'.format(relation_name), hookenv.ERROR)
        return None
    return _find_relation_factory(_relation_module(role, interface))


def _relation_module(role, interface):
    """
    Return module for relation based on its role and interface, or None.

    Prefers new location (reactive/relations) over old (hooks/relations).
    """
    _append_path(hookenv.charm_dir())

# Path: charms/reactive/flags.py
# @cmdline.subcommand()
# def get_flags():
#     """
#     Return a list of all flags which are set.
#     """
#     flags = unitdata.kv().getrange('reactive.states.', strip=True) or {}
#     return sorted(flags.keys())
# 
# Path: charms/reactive/flags.py
# def _get_flag_value(flag, default=None):
#     return unitdata.kv().get('reactive.states.%s' % flag, default)
# 
# Path: charms/reactive/flags.py
# @cmdline.subcommand()
# @cmdline.no_output
# def set_flag(flag, value=None):
#     """set_flag(flag)
#     Set the given flag as active.
# 
#     :param str flag: Name of flag to set.
# 
#     .. note:: **Changes to flags are reset when a handler crashes.** Changes to
#        flags happen immediately, but they are only persisted at the end of a
#        complete and successful run of the reactive framework. All unpersisted
#        changes are discarded when a hook crashes.
#     """
#     old_flags = get_flags()
#     unitdata.kv().update({flag: value}, prefix='reactive.states.')
#     if flag not in old_flags:
#         tracer().set_flag(flag)
#         FlagWatch.change(flag)
#         trigger = _get_trigger(flag, None)
#         for flag_name in trigger['set_flag']:
#             set_flag(flag_name)
#         for flag_name in trigger['clear_flag']:
#             clear_flag(flag_name)
#         for callback in trigger['callbacks']:
#             callback()
# 
# Path: charms/reactive/flags.py
# @cmdline.subcommand()
# @cmdline.no_output
# def clear_flag(flag):
#     """
#     Clear / deactivate a flag.
# 
#     :param str flag: Name of flag to set.
# 
#     .. note:: **Changes to flags are reset when a handler crashes.** Changes to
#        flags happen immediately, but they are only persisted at the end of a
#        complete and successful run of the reactive framework. All unpersisted
#        changes are discarded when a hook crashes.
#     """
#     old_flags = get_flags()
#     unitdata.kv().unset('reactive.states.%s' % flag)
#     unitdata.kv().set('reactive.dispatch.removed_state', True)
#     if flag in old_flags:
#         tracer().clear_flag(flag)
#         FlagWatch.change(flag)
#         trigger = _get_trigger(None, flag)
#         for flag_name in trigger['set_flag']:
#             set_flag(flag_name)
#         for flag_name in trigger['clear_flag']:
#             clear_flag(flag_name)
#         for callback in trigger['callbacks']:
#             callback()
# 
# Path: charms/reactive/flags.py
# class StateList(object):
#     """
#     .. deprecated:: 0.5.0
#        use flag instead
# 
#     Base class for a set of states that can be set by a relation or layer.
# 
#     This class should be used so that they can be discovered and introspected,
#     for documentation, composition, or linting.
# 
#     Example usage::
# 
#         class MyRelation(RelationBase):
#             class states(StateList):
#                 connected = State('{relation_name}.connected')
#                 available = State('{relation_name}.available')
#     """
#     pass
# 
# Path: charms/reactive/bus.py
# def _append_path(d):
#     if d not in sys.path:
#         sys.path.append(d)


# Path: charms/reactive/relations.py
import os
import sys
import importlib
from inspect import isclass
from charmhelpers.core import hookenv
from charmhelpers.core import unitdata
from charmhelpers.cli import cmdline
from charms.reactive.flags import get_flags
from charms.reactive.flags import _get_flag_value
from charms.reactive.flags import set_flag
from charms.reactive.flags import clear_flag
from charms.reactive.flags import StateList
from charms.reactive.bus import _append_path
    from importlib.metadata import entry_points
    from pkg_resources import iter_entry_points


    @classmethod
    def from_flag(cls, state):
        raise NotImplementedError()


def relation_factory(relation_name):
    """Get the RelationFactory for the given relation name.

    Looks for a RelationFactory in the first file matching:
    ``$CHARM_DIR/hooks/relations/{interface}/{provides,requires,peer}.py``
    """
    factory = RelationFactory.get_factory(relation_name)
    if factory:
        return factory
    role, interface = hookenv.relation_to_role_and_interface(relation_name)
    if not (role and interface):
        hookenv.log('Unable to determine role and interface for relation '
                    '{}'.format(relation_name), hookenv.ERROR)
        return None
    return _find_relation_factory(_relation_module(role, interface))


def _relation_module(role, interface):
    """
    Return module for relation based on its role and interface, or None.

    Prefers new location (reactive/relations) over old (hooks/relations).
    """
    _append_path(hookenv.charm_dir())

    _append_path(os.path.join(hookenv.charm_dir(), 'hooks'))