# Path: twiggy/lib/text.py
# def to_text(obj, encoding='utf-8', errors=None, nonstring='simplerepr'):
#     """Make sure that a string is a text string
# 
#     :arg obj: An object to make sure is a text string.  In most cases this
#         will be either a text string or a byte string.  However, with
#         ``nonstring='simplerepr'``, this can be used as a traceback-free
#         version of ``str(obj)``.
#     :kwarg encoding: The encoding to use to transform from a byte string to
#         a text string.  Defaults to using 'utf-8'.
#     :kwarg errors: The error handler to use if the byte string is not
#         decodable using the specified encoding.  Any valid `codecs error
#         handler <https://docs.python.org/2/library/codecs.html#codec-base-classes>`_
#         may be specified.   We support three additional error strategies
#         specifically aimed at helping people to port code:
# 
#             :surrogate_or_strict: Will use surrogateescape if it is a valid
#                 handler, otherwise it will use strict
#             :surrogate_or_replace: Will use surrogateescape if it is a valid
#                 handler, otherwise it will use replace.
#             :surrogate_then_replace: Does the same as surrogate_or_replace but
#                 `was added for symmetry with the error handlers in
#                 :func:`ansible.module_utils._text.to_bytes` (Added in Ansible 2.3)
# 
#         Because surrogateescape was added in Python3 this usually means that
#         Python3 will use `surrogateescape` and Python2 will use the fallback
#         error handler. Note that the code checks for surrogateescape when the
#         module is imported.  If you have a backport of `surrogateescape` for
#         python2, be sure to register the error handler prior to importing this
#         module.
# 
#         The default until Ansible-2.2 was `surrogate_or_replace`
#         In Ansible-2.3 this defaults to `surrogate_then_replace` for symmetry
#         with :func:`ansible.module_utils._text.to_bytes` .
#     :kwarg nonstring: The strategy to use if a nonstring is specified in
#         ``obj``.  Default is 'simplerepr'.  Valid values are:
# 
#         :simplerepr: The default.  This takes the ``str`` of the object and
#             then returns the text version of that string.
#         :empty: Return an empty text string
#         :passthru: Return the object passed in
#         :strict: Raise a :exc:`TypeError`
# 
#     :returns: Typically this returns a text string.  If a nonstring object is
#         passed in this may be a different type depending on the strategy
#         specified by nonstring.  This will never return a byte string.
#         From Ansible-2.3 onwards, the default is `surrogate_then_replace`.
# 
#     .. version_changed:: 2.3
# 
#         Added the surrogate_then_replace error handler and made it the default error handler.
#     """
#     if isinstance(obj, text_type):
#         return obj
# 
#     if errors in _COMPOSED_ERROR_HANDLERS:
#         if HAS_SURROGATEESCAPE:
#             errors = 'surrogateescape'
#         elif errors == 'surrogate_or_strict':
#             errors = 'strict'
#         else:
#             errors = 'replace'
# 
#     if isinstance(obj, binary_type):
#         # Note: We don't need special handling for surrogate_then_replace
#         # because all bytes will either be made into surrogates or are valid
#         # to decode.
#         return obj.decode(encoding, errors)
# 
#     # Note: We do these last even though we have to call to_text again on the
#     # value because we're optimizing the common case
#     if nonstring == 'simplerepr':
#         try:
#             value = str(obj)
#         except UnicodeError:
#             try:
#                 value = repr(obj)
#             except UnicodeError:
#                 # Giving up
#                 return u''
#     elif nonstring == 'passthru':
#         return obj
#     elif nonstring == 'empty':
#         return u''
#     elif nonstring == 'strict':
#         raise TypeError('obj must be a string type')
#     else:
#         raise TypeError('Invalid value %s for to_text\'s nonstring parameter' % nonstring)
# 
#     return to_text(value, encoding, errors)


import sys
import traceback
from string import Template
from six import iteritems
from .lib.text import to_text



__all__ = ['Message']


class Message(object):
    """A log message.  All attributes are read-only."""

    __slots__ = ['fields', 'suppress_newlines', 'traceback', 'text']

    #: default option values. Don't change these!
    _default_options = {'suppress_newlines': True,
                        'trace': None,
                        'style': 'braces'}
    # XXX I need a __repr__!

    def __init__(self, level, format_spec, fields, options,
                 args, kwargs):
        """
        :arg LogLevel level: the level of the message
        :arg string format_spec: the human-readable message template. Should match the ``style``
            in options.
        :arg dict fields: dictionary of fields for :ref:`structured logging <structured-logging>`
        :arg tuple args: substitution arguments for ``format_spec``.
        :arg dict kwargs: substitution keyword arguments for ``format_spec``.
        :arg dict options: a dictionary of :ref:`options <message-options>` to control message
            creation.
        """

# Path: twiggy/lib/text.py
# def to_text(obj, encoding='utf-8', errors=None, nonstring='simplerepr'):
#     """Make sure that a string is a text string
# 
#     :arg obj: An object to make sure is a text string.  In most cases this
#         will be either a text string or a byte string.  However, with
#         ``nonstring='simplerepr'``, this can be used as a traceback-free
#         version of ``str(obj)``.
#     :kwarg encoding: The encoding to use to transform from a byte string to
#         a text string.  Defaults to using 'utf-8'.
#     :kwarg errors: The error handler to use if the byte string is not
#         decodable using the specified encoding.  Any valid `codecs error
#         handler <https://docs.python.org/2/library/codecs.html#codec-base-classes>`_
#         may be specified.   We support three additional error strategies
#         specifically aimed at helping people to port code:
# 
#             :surrogate_or_strict: Will use surrogateescape if it is a valid
#                 handler, otherwise it will use strict
#             :surrogate_or_replace: Will use surrogateescape if it is a valid
#                 handler, otherwise it will use replace.
#             :surrogate_then_replace: Does the same as surrogate_or_replace but
#                 `was added for symmetry with the error handlers in
#                 :func:`ansible.module_utils._text.to_bytes` (Added in Ansible 2.3)
# 
#         Because surrogateescape was added in Python3 this usually means that
#         Python3 will use `surrogateescape` and Python2 will use the fallback
#         error handler. Note that the code checks for surrogateescape when the
#         module is imported.  If you have a backport of `surrogateescape` for
#         python2, be sure to register the error handler prior to importing this
#         module.
# 
#         The default until Ansible-2.2 was `surrogate_or_replace`
#         In Ansible-2.3 this defaults to `surrogate_then_replace` for symmetry
#         with :func:`ansible.module_utils._text.to_bytes` .
#     :kwarg nonstring: The strategy to use if a nonstring is specified in
#         ``obj``.  Default is 'simplerepr'.  Valid values are:
# 
#         :simplerepr: The default.  This takes the ``str`` of the object and
#             then returns the text version of that string.
#         :empty: Return an empty text string
#         :passthru: Return the object passed in
#         :strict: Raise a :exc:`TypeError`
# 
#     :returns: Typically this returns a text string.  If a nonstring object is
#         passed in this may be a different type depending on the strategy
#         specified by nonstring.  This will never return a byte string.
#         From Ansible-2.3 onwards, the default is `surrogate_then_replace`.
# 
#     .. version_changed:: 2.3
# 
#         Added the surrogate_then_replace error handler and made it the default error handler.
#     """
#     if isinstance(obj, text_type):
#         return obj
# 
#     if errors in _COMPOSED_ERROR_HANDLERS:
#         if HAS_SURROGATEESCAPE:
#             errors = 'surrogateescape'
#         elif errors == 'surrogate_or_strict':
#             errors = 'strict'
#         else:
#             errors = 'replace'
# 
#     if isinstance(obj, binary_type):
#         # Note: We don't need special handling for surrogate_then_replace
#         # because all bytes will either be made into surrogates or are valid
#         # to decode.
#         return obj.decode(encoding, errors)
# 
#     # Note: We do these last even though we have to call to_text again on the
#     # value because we're optimizing the common case
#     if nonstring == 'simplerepr':
#         try:
#             value = str(obj)
#         except UnicodeError:
#             try:
#                 value = repr(obj)
#             except UnicodeError:
#                 # Giving up
#                 return u''
#     elif nonstring == 'passthru':
#         return obj
#     elif nonstring == 'empty':
#         return u''
#     elif nonstring == 'strict':
#         raise TypeError('obj must be a string type')
#     else:
#         raise TypeError('Invalid value %s for to_text\'s nonstring parameter' % nonstring)
# 
#     return to_text(value, encoding, errors)


# Path: twiggy/message.py
import sys
import traceback
from string import Template
from six import iteritems
from .lib.text import to_text




__all__ = ['Message']


class Message(object):
    """A log message.  All attributes are read-only."""

    __slots__ = ['fields', 'suppress_newlines', 'traceback', 'text']

    #: default option values. Don't change these!
    _default_options = {'suppress_newlines': True,
                        'trace': None,
                        'style': 'braces'}
    # XXX I need a __repr__!

    def __init__(self, level, format_spec, fields, options,
                 args, kwargs):
        """
        :arg LogLevel level: the level of the message
        :arg string format_spec: the human-readable message template. Should match the ``style``
            in options.
        :arg dict fields: dictionary of fields for :ref:`structured logging <structured-logging>`
        :arg tuple args: substitution arguments for ``format_spec``.
        :arg dict kwargs: substitution keyword arguments for ``format_spec``.
        :arg dict options: a dictionary of :ref:`options <message-options>` to control message
            creation.
        """

        format_spec = to_text(format_spec, errors='surrogate_or_replace')