# Path: graphscale/check.py
# def isinst(obj: Any, ttype: Type, _msg: str=None) -> None:
# def invariant(condition: Any, msg: str) -> None:
# def failed(msg: str) -> NoReturn:
# 
# Path: graphscale/errors.py
# def async_field_error_boundary(async_resolver: Callable) -> Callable:
#     @wraps(async_resolver)
#     async def inner(*args: Any, **kwargs: Any) -> Any:
#         try:
#             return await async_resolver(*args, **kwargs)
#         except Exception as error:
#             raise GraphQLFieldError(error)
# 
#     return inner
# 
# def field_error_boundary(resolver: Callable) -> Callable:
#     @wraps(resolver)
#     def inner(*args: Any, **kwargs: Any) -> Any:
#         try:
#             return resolver(*args, **kwargs)
#         except Exception as error:
#             raise GraphQLFieldError(error)
# 
#     return inner
# 
# Path: graphscale/pent.py
# class PentContext:
#     def __init__(self, *, kvetch: Kvetch, config: PentConfig) -> None:
#         self.__kvetch = kvetch
#         self.__config = config
#         self.loader = PentLoader(self)
# 
#     def cls_from_name(self, name: str) -> Type:
#         return self.__config.get_class_from_name(name)
# 
#     @property
#     def kvetch(self) -> Kvetch:
#         return self.__kvetch
# 
#     @property
#     def config(self) -> PentConfig:
#         return self.__config
# 
#     # had to change things to nuke loader at beginning of request again
#     # @property
#     # def loader(self) -> 'PentLoader':
#     #     return self.__loader
# 
# Path: graphscale/utils.py
# def to_snake_case(camel_case: str) -> str:
#     """Convert a camel case string to snake case. e.g. fooBar ==> foo_bar"""
#     with_underscores = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_case)
#     return re.sub('([a-z0-9])([A-Z])', r'\1_\2', with_underscores).lower()


from typing import Any, Callable, Dict
from graphscale import check
from graphscale.errors import async_field_error_boundary, field_error_boundary
from graphscale.pent import PentContext
from graphscale.utils import to_snake_case
    if 'id' in args:
        args['obj_id'] = args['id']
        del args['id']
    return pythonify_dict(args)


def define_pent_mutation_resolver(python_name: str, pent_data_cls_name: str) -> Callable:
    @async_field_error_boundary
    async def mutation_resolver(obj: Any, args: Dict[str, Any], context: PentContext,
                                *_: Any) -> Any:
        args = process_args(args)
        pent_data_cls = context.cls_from_name(pent_data_cls_name)
        pent_data = pent_data_cls(**args['data'])
        args['data'] = pent_data
        prop = getattr(obj, python_name)
        check.invariant(callable(prop), 'must be async function')
        return await prop(**args)

    return mutation_resolver


def define_default_gen_resolver(python_name: str) -> Callable:
    @async_field_error_boundary
    async def the_resolver(obj: Any, args: Dict[str, Any], *_: Any):
        if args:
            if 'id' in args:
                args['obj_id'] = args['id']
                del args['id']
            args = pythonify_dict(args)
        prop = getattr(obj, python_name)

# Path: graphscale/check.py
# def isinst(obj: Any, ttype: Type, _msg: str=None) -> None:
# def invariant(condition: Any, msg: str) -> None:
# def failed(msg: str) -> NoReturn:
# 
# Path: graphscale/errors.py
# def async_field_error_boundary(async_resolver: Callable) -> Callable:
#     @wraps(async_resolver)
#     async def inner(*args: Any, **kwargs: Any) -> Any:
#         try:
#             return await async_resolver(*args, **kwargs)
#         except Exception as error:
#             raise GraphQLFieldError(error)
# 
#     return inner
# 
# def field_error_boundary(resolver: Callable) -> Callable:
#     @wraps(resolver)
#     def inner(*args: Any, **kwargs: Any) -> Any:
#         try:
#             return resolver(*args, **kwargs)
#         except Exception as error:
#             raise GraphQLFieldError(error)
# 
#     return inner
# 
# Path: graphscale/pent.py
# class PentContext:
#     def __init__(self, *, kvetch: Kvetch, config: PentConfig) -> None:
#         self.__kvetch = kvetch
#         self.__config = config
#         self.loader = PentLoader(self)
# 
#     def cls_from_name(self, name: str) -> Type:
#         return self.__config.get_class_from_name(name)
# 
#     @property
#     def kvetch(self) -> Kvetch:
#         return self.__kvetch
# 
#     @property
#     def config(self) -> PentConfig:
#         return self.__config
# 
#     # had to change things to nuke loader at beginning of request again
#     # @property
#     # def loader(self) -> 'PentLoader':
#     #     return self.__loader
# 
# Path: graphscale/utils.py
# def to_snake_case(camel_case: str) -> str:
#     """Convert a camel case string to snake case. e.g. fooBar ==> foo_bar"""
#     with_underscores = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_case)
#     return re.sub('([a-z0-9])([A-Z])', r'\1_\2', with_underscores).lower()


# Path: graphscale/grapple/grapple_types.py
from typing import Any, Callable, Dict
from graphscale import check
from graphscale.errors import async_field_error_boundary, field_error_boundary
from graphscale.pent import PentContext
from graphscale.utils import to_snake_case

    if 'id' in args:
        args['obj_id'] = args['id']
        del args['id']
    return pythonify_dict(args)


def define_pent_mutation_resolver(python_name: str, pent_data_cls_name: str) -> Callable:
    @async_field_error_boundary
    async def mutation_resolver(obj: Any, args: Dict[str, Any], context: PentContext,
                                *_: Any) -> Any:
        args = process_args(args)
        pent_data_cls = context.cls_from_name(pent_data_cls_name)
        pent_data = pent_data_cls(**args['data'])
        args['data'] = pent_data
        prop = getattr(obj, python_name)
        check.invariant(callable(prop), 'must be async function')
        return await prop(**args)

    return mutation_resolver


def define_default_gen_resolver(python_name: str) -> Callable:
    @async_field_error_boundary
    async def the_resolver(obj: Any, args: Dict[str, Any], *_: Any):
        if args:
            if 'id' in args:
                args['obj_id'] = args['id']
                del args['id']
            args = pythonify_dict(args)
        prop = getattr(obj, python_name)

        check.invariant(callable(prop), 'must be async function')