# Path: pykern/pkcollections.py
# class PKDict(dict):
# class PKDictNameError(NameError):
#     def __copy__(self):
#     def __deepcopy__(self, memo):
#     def __delattr__(self, name):
#     def __getattr__(self, name):
#     def __setattr__(self, name, value):
#     def copy(self):
#     def pkdel(self, name, default=None):
#     def pknested_get(self, dotted_key):
#     def pksetdefault(self, *args, **kwargs):
#     def pkunchecked_nested_get(self, dotted_key):
#     def pkupdate(self, *args, **kwargs):
# def json_load_any(obj, *args, **kwargs):
#     def object_pairs_hook(*args, **kwargs):
# def unchecked_del(obj, *keys):
# 
# 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/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/pkio.py
# TEXT_ENCODING = 'utf-8'
# def atomic_write(path, contents, **kwargs):
# def exception_is_not_found(exc):
# def expand_user_path(path):
# def has_file_extension(filename, to_check):
# def mkdir_parent(path):
# def mkdir_parent_only(path):
# def open_text(filename, **kwargs):
# def py_path(path=None):
# def random_base62(length=16):
# def read_binary(filename):
# def read_text(filename):
# def save_chdir(dirname, mkdir=False, is_pkunit_prefix=False):
# def sorted_glob(path, key=None):
#     def _path_sort_attr(path):
# def unchecked_remove(*paths):
# def walk_tree(dirname, file_re=None):
#     def _walk(dirname):
# def write_binary(path, contents):
# def write_text(path, contents):


from pykern import pkcollections
from pykern import pkcompat
from pykern import pkinspect
from pykern import pkio
    from pykern.pkdebug import pkdpretty
    from pykern import pkyaml
        from pykern.pkdebug import pkdexc
import contextlib
import importlib
import inspect
import json
import os
import py
import pytest
import re
import sys
    import pykern.pkjson
    import pykern.pkconst
            import pykern.pkjinja
    Same for `actual_path`.

    If `expect_path` ends with ``.jinja``, it will be rendered
    with `pykern.pkjina.render_file`, and you must supply `j2_ctx`
    in kwargs.

    Args:
        expect_path (str or py.path): text file to be read; if str, then joined with `data_dir`
        actual (object): string or json data structure; if missing, read `actual_path` (may be positional)
        actual_path (py.path or str): where to write results; if str, then joined with `work_dir`; if None, ``work_dir().join(expect_path.relto(data_dir()))``
        j2_ctx (dict): passed to `pykern.pkjinja.render_file`
    """

    a = 'actual' in kwargs
    if args:
        assert not a, \
            f'have actual as positional arg={args[0]} and kwargs={kwargs["actual"]}'
        assert len(args) == 1, \
            f'too many positional args={args}, may only have one (actual)'
        kwargs['actual'] = args[0]
        a = True
    actual_path = kwargs.get('actual_path')
    if not isinstance(expect_path, pykern.pkconst.PY_PATH_LOCAL_TYPE):
        expect_path = data_dir().join(expect_path)
    j = expect_path.ext == '.jinja'
    b = expect_path.purebasename if j else expect_path.relto(data_dir())
    if actual_path is None:
        actual_path = b
    if not isinstance(actual_path, pykern.pkconst.PY_PATH_LOCAL_TYPE):
        actual_path = work_dir().join(actual_path)

# Path: pykern/pkcollections.py
# class PKDict(dict):
# class PKDictNameError(NameError):
#     def __copy__(self):
#     def __deepcopy__(self, memo):
#     def __delattr__(self, name):
#     def __getattr__(self, name):
#     def __setattr__(self, name, value):
#     def copy(self):
#     def pkdel(self, name, default=None):
#     def pknested_get(self, dotted_key):
#     def pksetdefault(self, *args, **kwargs):
#     def pkunchecked_nested_get(self, dotted_key):
#     def pkupdate(self, *args, **kwargs):
# def json_load_any(obj, *args, **kwargs):
#     def object_pairs_hook(*args, **kwargs):
# def unchecked_del(obj, *keys):
# 
# 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/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/pkio.py
# TEXT_ENCODING = 'utf-8'
# def atomic_write(path, contents, **kwargs):
# def exception_is_not_found(exc):
# def expand_user_path(path):
# def has_file_extension(filename, to_check):
# def mkdir_parent(path):
# def mkdir_parent_only(path):
# def open_text(filename, **kwargs):
# def py_path(path=None):
# def random_base62(length=16):
# def read_binary(filename):
# def read_text(filename):
# def save_chdir(dirname, mkdir=False, is_pkunit_prefix=False):
# def sorted_glob(path, key=None):
#     def _path_sort_attr(path):
# def unchecked_remove(*paths):
# def walk_tree(dirname, file_re=None):
#     def _walk(dirname):
# def write_binary(path, contents):
# def write_text(path, contents):


# Path: pykern/pkunit.py
from pykern import pkcollections
from pykern import pkcompat
from pykern import pkinspect
from pykern import pkio
    from pykern.pkdebug import pkdpretty
    from pykern import pkyaml
        from pykern.pkdebug import pkdexc
import contextlib
import importlib
import inspect
import json
import os
import py
import pytest
import re
import sys
    import pykern.pkjson
    import pykern.pkconst
            import pykern.pkjinja

    Same for `actual_path`.

    If `expect_path` ends with ``.jinja``, it will be rendered
    with `pykern.pkjina.render_file`, and you must supply `j2_ctx`
    in kwargs.

    Args:
        expect_path (str or py.path): text file to be read; if str, then joined with `data_dir`
        actual (object): string or json data structure; if missing, read `actual_path` (may be positional)
        actual_path (py.path or str): where to write results; if str, then joined with `work_dir`; if None, ``work_dir().join(expect_path.relto(data_dir()))``
        j2_ctx (dict): passed to `pykern.pkjinja.render_file`
    """

    a = 'actual' in kwargs
    if args:
        assert not a, \
            f'have actual as positional arg={args[0]} and kwargs={kwargs["actual"]}'
        assert len(args) == 1, \
            f'too many positional args={args}, may only have one (actual)'
        kwargs['actual'] = args[0]
        a = True
    actual_path = kwargs.get('actual_path')
    if not isinstance(expect_path, pykern.pkconst.PY_PATH_LOCAL_TYPE):
        expect_path = data_dir().join(expect_path)
    j = expect_path.ext == '.jinja'
    b = expect_path.purebasename if j else expect_path.relto(data_dir())
    if actual_path is None:
        actual_path = b
    if not isinstance(actual_path, pykern.pkconst.PY_PATH_LOCAL_TYPE):
        actual_path = work_dir().join(actual_path)

    actual = kwargs['actual'] if a else pkio.read_text(actual_path)