# Path: tripoli/util.py
# def coerce(args=(), invert=False, prefer_symbol=False):
#     """Decorator for coercing arguments to Emacs objects.
# 
#     :param args: An argument or list of argument names to coerce. If empty, all
#         arguments are coerced.
#     :param invert: If *true*, the meaning of *args* will be inverted, i.e. all
#         arguments *not* in this list will be coerced.
#     :param prefer_symbol: If true, string-like arguments will be coerced to
#         symbols if possible. If false, they remain strings. Optionally, it may
#         be a string, in which case an argument named *self* must be present,
#         and objects passed as *self* must have an attribute with the same name
#         as the value of `symbol`. The truth value of this attribute then
#         determines the symbol-coercing behaviour.
# 
#     This decorator will work with :code:`*args` and :code:`**kwargs` as
#     expected, that is, the elements themselves are coerced, not the collections
#     as a whole.
# 
#     .. note:: Arguments named *self* will never be coerced.
#     """
#     if isinstance(args, str):
#         args = (args,)
# 
#     def decorator(fn):
# 
#         # Establish the exceptional and default coercion strategies
#         if args:
#             default_strategy = CoercionStrategy(int(invert))
#             strategies = {name: CoercionStrategy(int(not invert)) for name in args}
#         else:
#             default_strategy = CoercionStrategy.coerce
#             strategies = {}
# 
#         signature = inspect.signature(fn)
# 
#         # If the function signature has splat operators, ensure they are treated correctly
#         splat, doublesplat = None, None
#         for name, param in signature.parameters.items():
#             if param.kind == Parameter.VAR_POSITIONAL and strategies.get(name, default_strategy):
#                 strategies[name] = CoercionStrategy.coerce_args
#             elif param.kind == Parameter.VAR_KEYWORD and strategies.get(name, default_strategy):
#                 strategies[name] = CoercionStrategy.coerce_kwargs
# 
#         # Never coerce self
#         strategies['self'] = CoercionStrategy.ignore
# 
#         @wraps(fn)
#         def ret(*args, **kwargs):
#             binding = signature.bind(*args, **kwargs)
# 
#             # Check whether to prefer symbols or not
#             if isinstance(prefer_symbol, str):
#                 symbol = getattr(binding.arguments['self'], prefer_symbol)
#             else:
#                 symbol = prefer_symbol
# 
#             # Coerce each argument as necessary
#             for key, value in binding.arguments.items():
#                 strategy = strategies.get(key, default_strategy)
#                 if not strategy:
#                     continue
#                 if strategy == CoercionStrategy.coerce:
#                     value = EmacsObject(value, prefer_symbol=symbol)
#                 elif strategy == CoercionStrategy.coerce_args:
#                     value = tuple(EmacsObject(v, prefer_symbol=symbol) for v in value)
#                 elif strategy == CoercionStrategy.coerce_kwargs:
#                     value = {n: EmacsObject(v, prefer_symbol=symbol) for n, v in value.items()}
#                 binding.arguments[key] = value
# 
#             return fn(*binding.args, **binding.kwargs)
#         return ret
#     return decorator


from tripoli.util import coerce
import emacs_raw as er



def test_all():

    @coerce()
    def test(a, b, c, *args, **kwargs):
        assert isinstance(a, er.EmacsObject)
        assert isinstance(b, er.EmacsObject)
        assert isinstance(c, er.EmacsObject)

        assert not isinstance(args, er.EmacsObject)
        assert not isinstance(kwargs, er.EmacsObject)

        for arg in args:
            assert isinstance(arg, er.EmacsObject)
        for name, kwarg in kwargs.items():
            assert not isinstance(name, er.EmacsObject)
            assert isinstance(kwarg, er.EmacsObject)

    test(1, 2, 3)
    test('a', [34], er.intern('q'))
    test('a', [34], er.intern('q'), 'b', 'c', q='d')


def test_almost_all():


# Path: tripoli/util.py
# def coerce(args=(), invert=False, prefer_symbol=False):
#     """Decorator for coercing arguments to Emacs objects.
# 
#     :param args: An argument or list of argument names to coerce. If empty, all
#         arguments are coerced.
#     :param invert: If *true*, the meaning of *args* will be inverted, i.e. all
#         arguments *not* in this list will be coerced.
#     :param prefer_symbol: If true, string-like arguments will be coerced to
#         symbols if possible. If false, they remain strings. Optionally, it may
#         be a string, in which case an argument named *self* must be present,
#         and objects passed as *self* must have an attribute with the same name
#         as the value of `symbol`. The truth value of this attribute then
#         determines the symbol-coercing behaviour.
# 
#     This decorator will work with :code:`*args` and :code:`**kwargs` as
#     expected, that is, the elements themselves are coerced, not the collections
#     as a whole.
# 
#     .. note:: Arguments named *self* will never be coerced.
#     """
#     if isinstance(args, str):
#         args = (args,)
# 
#     def decorator(fn):
# 
#         # Establish the exceptional and default coercion strategies
#         if args:
#             default_strategy = CoercionStrategy(int(invert))
#             strategies = {name: CoercionStrategy(int(not invert)) for name in args}
#         else:
#             default_strategy = CoercionStrategy.coerce
#             strategies = {}
# 
#         signature = inspect.signature(fn)
# 
#         # If the function signature has splat operators, ensure they are treated correctly
#         splat, doublesplat = None, None
#         for name, param in signature.parameters.items():
#             if param.kind == Parameter.VAR_POSITIONAL and strategies.get(name, default_strategy):
#                 strategies[name] = CoercionStrategy.coerce_args
#             elif param.kind == Parameter.VAR_KEYWORD and strategies.get(name, default_strategy):
#                 strategies[name] = CoercionStrategy.coerce_kwargs
# 
#         # Never coerce self
#         strategies['self'] = CoercionStrategy.ignore
# 
#         @wraps(fn)
#         def ret(*args, **kwargs):
#             binding = signature.bind(*args, **kwargs)
# 
#             # Check whether to prefer symbols or not
#             if isinstance(prefer_symbol, str):
#                 symbol = getattr(binding.arguments['self'], prefer_symbol)
#             else:
#                 symbol = prefer_symbol
# 
#             # Coerce each argument as necessary
#             for key, value in binding.arguments.items():
#                 strategy = strategies.get(key, default_strategy)
#                 if not strategy:
#                     continue
#                 if strategy == CoercionStrategy.coerce:
#                     value = EmacsObject(value, prefer_symbol=symbol)
#                 elif strategy == CoercionStrategy.coerce_args:
#                     value = tuple(EmacsObject(v, prefer_symbol=symbol) for v in value)
#                 elif strategy == CoercionStrategy.coerce_kwargs:
#                     value = {n: EmacsObject(v, prefer_symbol=symbol) for n, v in value.items()}
#                 binding.arguments[key] = value
# 
#             return fn(*binding.args, **binding.kwargs)
#         return ret
#     return decorator


# Path: tripoli_tests/test_coerce.py
from tripoli.util import coerce
import emacs_raw as er




def test_all():

    @coerce()
    def test(a, b, c, *args, **kwargs):
        assert isinstance(a, er.EmacsObject)
        assert isinstance(b, er.EmacsObject)
        assert isinstance(c, er.EmacsObject)

        assert not isinstance(args, er.EmacsObject)
        assert not isinstance(kwargs, er.EmacsObject)

        for arg in args:
            assert isinstance(arg, er.EmacsObject)
        for name, kwarg in kwargs.items():
            assert not isinstance(name, er.EmacsObject)
            assert isinstance(kwarg, er.EmacsObject)

    test(1, 2, 3)
    test('a', [34], er.intern('q'))
    test('a', [34], er.intern('q'), 'b', 'c', q='d')


def test_almost_all():


    @coerce('b', invert=True)