# Path: src/circular/template/observer.py
# def observe(obj, observer=None, ignore_errors=False):
#     """
#         Returns an observer object monitoring changes to ``obj``.
# 
#         One can specify any instance of EventMixin as the ``observer``
#         parameter. In this case any change events will be emitted
#         (forwarded) by the provided observer.
# 
#         If ``ignore_errors`` is False, the method may throw, e.g. if
#         the user tries to observe a built in type. Otherwise it will
#         just return None in case of error.
# 
#         WARNING: Only instances of user-defined classes can be
#         observed. If you need to observe a ``list`` or a ``dict``
#         wrap them in a ``ListProxy`` or ``DictProxy``. Or, alternatively,
#         consider using the Context class which automatically and
#         recursively wraps any ``list`` and ``Dict`` variables which
#         are assigned to it.
#     """
#     if not hasattr(obj, '_obs____'):
#         if type(obj) in [str, int, dict, list, tuple, set, type(None), bool]:
#             if not ignore_errors:
#                 raise Exception("Cannot observe primitive types:")
#             else:
#                 return None
#         try:
#             if hasattr(obj, '__setitem__'):
#                 extend_instance(obj, ArrayMixin)
#             else:
#                 extend_instance(obj, ObjMixin)
#             obj._create_observer()
#         except Exception as exc:
#             # pylint: disable-broad-except; not sure what possible exceptions can happen here, must catch them though
#             if not ignore_errors:
#                 raise Exception("Cannot observe (is obj a primitive type?):"+str(exc))
#             else:
#                 return None
#     if observer is not None:
#         obj._obs____.bind('change', observer, 'change')
#     return obj._obs____


from circular.utils.events import EventMixin
from .observer import observe
    while state == 'args':
        arg, endt, _pos = _parse(token_stream, [T_COMMA, T_EQUAL, T_RPAREN])
        if endt == T_EQUAL:
            state = 'kwargs'
        elif endt == T_RPAREN:
            args.append(arg)
            return args, kwargs
        else:
            args.append(arg)
    val, endt, _pos = _parse(token_stream, [T_COMMA, T_RPAREN])
    kwargs[arg._ident] = val
    while endt != T_RPAREN:
        arg, endt, _pos = _parse(token_stream, [T_EQUAL])
        val, endt, _pos = _parse(token_stream, [T_COMMA, T_RPAREN])
        kwargs[arg._ident] = val
    return args, kwargs


def parse_lst(token_stream):
    """ Parses a list constant or list comprehension from the token_stream
        and returns the appropriate node """
    elem, endt, _pos = _parse(token_stream, [T_RBRACKET, T_COMMA, T_KEYWORD])
    if endt == T_KEYWORD:
        expr = elem
        var, endt, _pos = _parse(token_stream, [T_KEYWORD])
        lst, endt, _pos = _parse(token_stream, [T_KEYWORD, T_RBRACKET])
        if endt == T_KEYWORD:
            cond, endt, _pos = _parse(token_stream, [T_RBRACKET])
        else:
            cond = None

# Path: src/circular/template/observer.py
# def observe(obj, observer=None, ignore_errors=False):
#     """
#         Returns an observer object monitoring changes to ``obj``.
# 
#         One can specify any instance of EventMixin as the ``observer``
#         parameter. In this case any change events will be emitted
#         (forwarded) by the provided observer.
# 
#         If ``ignore_errors`` is False, the method may throw, e.g. if
#         the user tries to observe a built in type. Otherwise it will
#         just return None in case of error.
# 
#         WARNING: Only instances of user-defined classes can be
#         observed. If you need to observe a ``list`` or a ``dict``
#         wrap them in a ``ListProxy`` or ``DictProxy``. Or, alternatively,
#         consider using the Context class which automatically and
#         recursively wraps any ``list`` and ``Dict`` variables which
#         are assigned to it.
#     """
#     if not hasattr(obj, '_obs____'):
#         if type(obj) in [str, int, dict, list, tuple, set, type(None), bool]:
#             if not ignore_errors:
#                 raise Exception("Cannot observe primitive types:")
#             else:
#                 return None
#         try:
#             if hasattr(obj, '__setitem__'):
#                 extend_instance(obj, ArrayMixin)
#             else:
#                 extend_instance(obj, ObjMixin)
#             obj._create_observer()
#         except Exception as exc:
#             # pylint: disable-broad-except; not sure what possible exceptions can happen here, must catch them though
#             if not ignore_errors:
#                 raise Exception("Cannot observe (is obj a primitive type?):"+str(exc))
#             else:
#                 return None
#     if observer is not None:
#         obj._obs____.bind('change', observer, 'change')
#     return obj._obs____


# Path: src/circular/template/expression.py
from circular.utils.events import EventMixin
from .observer import observe

    while state == 'args':
        arg, endt, _pos = _parse(token_stream, [T_COMMA, T_EQUAL, T_RPAREN])
        if endt == T_EQUAL:
            state = 'kwargs'
        elif endt == T_RPAREN:
            args.append(arg)
            return args, kwargs
        else:
            args.append(arg)
    val, endt, _pos = _parse(token_stream, [T_COMMA, T_RPAREN])
    kwargs[arg._ident] = val
    while endt != T_RPAREN:
        arg, endt, _pos = _parse(token_stream, [T_EQUAL])
        val, endt, _pos = _parse(token_stream, [T_COMMA, T_RPAREN])
        kwargs[arg._ident] = val
    return args, kwargs


def parse_lst(token_stream):
    """ Parses a list constant or list comprehension from the token_stream
        and returns the appropriate node """
    elem, endt, _pos = _parse(token_stream, [T_RBRACKET, T_COMMA, T_KEYWORD])
    if endt == T_KEYWORD:
        expr = elem
        var, endt, _pos = _parse(token_stream, [T_KEYWORD])
        lst, endt, _pos = _parse(token_stream, [T_KEYWORD, T_RBRACKET])
        if endt == T_KEYWORD:
            cond, endt, _pos = _parse(token_stream, [T_RBRACKET])
        else:
            cond = None

        return ListComprNode(expr, var, lst, cond)