# Path: pykern/pkcompat.py
# def locale_str(value):
#     def _locale_str(value):
#     def _to_bytes(value):
#     def _from_bytes(value):
#     def _assert_type(value, typ):
#     def _locale_str(value):
#     def _to_bytes(value):
#     def _from_bytes(value):
# def unicode_unescape(value):
# def unicode_getcwd():
# 
# Path: pykern/pkconfig.py
# STRING_TYPES = pkconst.STRING_TYPES
# CHANNEL_ATTR = 'pykern_pkconfig_channel'
# KEY_RE = re.compile('^[a-z][a-z0-9_]*[a-z0-9]$', flags=re.IGNORECASE)
# TUPLE_SEP = ':'
# VALID_CHANNELS = ('dev', 'alpha', 'beta', 'prod')
# INTERNAL_TEST_CHANNELS = VALID_CHANNELS[0:2]
# CHANNEL_DEFAULT = VALID_CHANNELS[0]
# _PARSE_NONE_ATTR = 'pykern_pkconfig_parse_none'
# _PARSE_SECONDS = re.compile(
#     r'^(?:(\d+)d)?(?:(?:(?:(\d+):)?(\d+):)?(\d+))?$',
#     flags=re.IGNORECASE,
# )
# _PARSE_BYTES = re.compile(r'^(\d+)([kmgtp]?)b?$', flags=re.IGNORECASE)
# _PARSE_BYTES_MULTIPLIER = PKDict(
#     k=1024,
#     m=1024**2,
#     g=1024**3,
#     t=1024**4,
# )
# class ReplacedBy(tuple, object):
# class Required(tuple, object):
# class RequiredUnlessDev(tuple, object):
# class _Declaration(object):
# class _Key(str, object):
#     def __new__(cls, new_name):
#     def __new__(cls, *args):
#     def __new__(cls, *args):
# def append_load_path(load_path):
# def channel_in(*args, **kwargs):
# def channel_in_internal_test(channel=None):
# def init(**kwargs):
# def flatten_values(base, new):
# def parse_none(func):
# def parse_bool(value):
# def parse_bytes(value):
# def parse_seconds(value):
# def parse_set(value):
# def parse_tuple(value):
# def raise_error(msg):
# def reset_state_for_testing(add_to_environ=None):
# def to_environ(cfg_keys, values=None, exclude_re=None):
#     def a(k, v):
#     def __init__(self, value):
#     def _fixup_parser(self):
#     def __new__(cls, parts):
# def _clean_environ():
# def _coalesce_values():
# def _flatten_keys(key_parts, values, res):
# def _iter_decls(decls, res):
# def _resolver(decl):
# def _resolve_dict(key, decl):
# def _resolve_list(key, decl):
# def _resolve_value(key, decl):
# def _z(msg):
# 
# Path: pykern/pkconst.py
# STRING_TYPES = None
#     STRING_TYPES = basestring
#     STRING_TYPES = str
#     PY_PATH_LOCAL_TYPE = type(py.path.local())
# BASE62_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
# 
# Path: pykern/pkinspect.py
# _VALID_IDENTIFIER_RE = re.compile(r'^[a-z_]\w*$', re.IGNORECASE)
# class Call(PKDict):
#     def __init__(self, frame_or_log):
#     def __str__(self):
# def caller(ignore_modules=None, exclude_first=True):
# def caller_module(exclude_first=True):
# def is_caller_main():
# def is_valid_identifier(string):
# def module_basename(obj):
# def module_name_join(names):
# def module_name_split(obj):
# def module_functions(func_prefix, module=None):
# def root_package(obj):
# def submodule_name(obj):
# def this_module():


from pykern import pkcompat
from pykern import pkconfig
from pykern import pkconst
from pykern import pkinspect
import datetime
import functools
import inspect
import json
import logging
import os
import pprint
import re
import six
import sys
import threading
import traceback
            obj,
        )

    def _snip(truncated, count_of_original_elements):
        truncated = truncated[:-2]
        return truncated + ', ' + SNIP \
            if count_of_original_elements > cfg.max_elements \
            else truncated

    def _string(value):
        if r'\n' in value:
            value = pkcompat.unicode_unescape(value)
        # '\n File"' is at the start of stack traces. The end of stack
        # traces are more interesting than the beginning so truncate
        # the beginning.
        if '\n  File "' in value and 'Exception was printed at' not in value:
            return SNIP + value[-cfg.max_string:] \
                if len(value) > cfg.max_string else value
        return value[:cfg.max_string] + \
            (value[cfg.max_string:] and SNIP)

    try:
        f = getattr(obj, PKDEBUG_STR_FUNCTION_NAME, None)
        # only call if an instance, otherwise is unbound method
        if f and not isinstance(obj, type):
            s = f()
        else:
            if cfg.redact_and_truncate:
                if isinstance(obj, (dict, list, set, tuple)):
                    return _object(obj, depth)

# Path: pykern/pkcompat.py
# def locale_str(value):
#     def _locale_str(value):
#     def _to_bytes(value):
#     def _from_bytes(value):
#     def _assert_type(value, typ):
#     def _locale_str(value):
#     def _to_bytes(value):
#     def _from_bytes(value):
# def unicode_unescape(value):
# def unicode_getcwd():
# 
# Path: pykern/pkconfig.py
# STRING_TYPES = pkconst.STRING_TYPES
# CHANNEL_ATTR = 'pykern_pkconfig_channel'
# KEY_RE = re.compile('^[a-z][a-z0-9_]*[a-z0-9]$', flags=re.IGNORECASE)
# TUPLE_SEP = ':'
# VALID_CHANNELS = ('dev', 'alpha', 'beta', 'prod')
# INTERNAL_TEST_CHANNELS = VALID_CHANNELS[0:2]
# CHANNEL_DEFAULT = VALID_CHANNELS[0]
# _PARSE_NONE_ATTR = 'pykern_pkconfig_parse_none'
# _PARSE_SECONDS = re.compile(
#     r'^(?:(\d+)d)?(?:(?:(?:(\d+):)?(\d+):)?(\d+))?$',
#     flags=re.IGNORECASE,
# )
# _PARSE_BYTES = re.compile(r'^(\d+)([kmgtp]?)b?$', flags=re.IGNORECASE)
# _PARSE_BYTES_MULTIPLIER = PKDict(
#     k=1024,
#     m=1024**2,
#     g=1024**3,
#     t=1024**4,
# )
# class ReplacedBy(tuple, object):
# class Required(tuple, object):
# class RequiredUnlessDev(tuple, object):
# class _Declaration(object):
# class _Key(str, object):
#     def __new__(cls, new_name):
#     def __new__(cls, *args):
#     def __new__(cls, *args):
# def append_load_path(load_path):
# def channel_in(*args, **kwargs):
# def channel_in_internal_test(channel=None):
# def init(**kwargs):
# def flatten_values(base, new):
# def parse_none(func):
# def parse_bool(value):
# def parse_bytes(value):
# def parse_seconds(value):
# def parse_set(value):
# def parse_tuple(value):
# def raise_error(msg):
# def reset_state_for_testing(add_to_environ=None):
# def to_environ(cfg_keys, values=None, exclude_re=None):
#     def a(k, v):
#     def __init__(self, value):
#     def _fixup_parser(self):
#     def __new__(cls, parts):
# def _clean_environ():
# def _coalesce_values():
# def _flatten_keys(key_parts, values, res):
# def _iter_decls(decls, res):
# def _resolver(decl):
# def _resolve_dict(key, decl):
# def _resolve_list(key, decl):
# def _resolve_value(key, decl):
# def _z(msg):
# 
# Path: pykern/pkconst.py
# STRING_TYPES = None
#     STRING_TYPES = basestring
#     STRING_TYPES = str
#     PY_PATH_LOCAL_TYPE = type(py.path.local())
# BASE62_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
# 
# Path: pykern/pkinspect.py
# _VALID_IDENTIFIER_RE = re.compile(r'^[a-z_]\w*$', re.IGNORECASE)
# class Call(PKDict):
#     def __init__(self, frame_or_log):
#     def __str__(self):
# def caller(ignore_modules=None, exclude_first=True):
# def caller_module(exclude_first=True):
# def is_caller_main():
# def is_valid_identifier(string):
# def module_basename(obj):
# def module_name_join(names):
# def module_name_split(obj):
# def module_functions(func_prefix, module=None):
# def root_package(obj):
# def submodule_name(obj):
# def this_module():


# Path: pykern/pkdebug.py
from pykern import pkcompat
from pykern import pkconfig
from pykern import pkconst
from pykern import pkinspect
import datetime
import functools
import inspect
import json
import logging
import os
import pprint
import re
import six
import sys
import threading
import traceback

            obj,
        )

    def _snip(truncated, count_of_original_elements):
        truncated = truncated[:-2]
        return truncated + ', ' + SNIP \
            if count_of_original_elements > cfg.max_elements \
            else truncated

    def _string(value):
        if r'\n' in value:
            value = pkcompat.unicode_unescape(value)
        # '\n File"' is at the start of stack traces. The end of stack
        # traces are more interesting than the beginning so truncate
        # the beginning.
        if '\n  File "' in value and 'Exception was printed at' not in value:
            return SNIP + value[-cfg.max_string:] \
                if len(value) > cfg.max_string else value
        return value[:cfg.max_string] + \
            (value[cfg.max_string:] and SNIP)

    try:
        f = getattr(obj, PKDEBUG_STR_FUNCTION_NAME, None)
        # only call if an instance, otherwise is unbound method
        if f and not isinstance(obj, type):
            s = f()
        else:
            if cfg.redact_and_truncate:
                if isinstance(obj, (dict, list, set, tuple)):
                    return _object(obj, depth)

                if isinstance(obj, pkconst.STRING_TYPES):