# Path: liam2/utils.py
# def unique(iterable):
#     """
#     List all elements once, preserving order. Remember all elements ever seen.
#     """
#     # unique('AAAABBBCCDAABBB') --> A B C D
#     seen = set()
#     seen_add = seen.add
#     for element in iterable:
#         if element not in seen:
#             seen_add(element)
#             yield element


import numpy as np
from liam2.utils import unique
        from liam2.expr import Variable
        self.extra[key] = value

    def __delitem__(self, key):
        del self.extra[key]

    def __contains__(self, key):
        entity = self.entity
        period = self.eval_ctx.period
        array_period = entity.array_period
        # entity.array can be None! (eg. with "explore")
        keyinarray = (self.is_array_period and
                      (key in entity.temp_variables or
                       key in entity.array.dtype.fields))
        # we need to check explicitly whether the key is in array_lag because
        # with output=None it can contain more fields than table.
        keyinlagarray = (entity.array_lag is not None and
                         array_period is not None and
                         period == array_period - 1 and
                         key in entity.array_lag.dtype.fields)
        keyintable = (entity.table is not None and
                      key in entity.table.dtype.fields)
        return key in self.extra or keyinarray or keyinlagarray or keyintable

    def keys(self, extra=True):
        res = list(self.entity.array.dtype.names)
        res.extend(sorted(self.entity.temp_variables.keys()))
        if extra:
            res.extend(sorted(self.extra.keys()))
        # in theory, this should not be needed because we present defining a function argument with the same
        # name than an entity field

# Path: liam2/utils.py
# def unique(iterable):
#     """
#     List all elements once, preserving order. Remember all elements ever seen.
#     """
#     # unique('AAAABBBCCDAABBB') --> A B C D
#     seen = set()
#     seen_add = seen.add
#     for element in iterable:
#         if element not in seen:
#             seen_add(element)
#             yield element


# Path: liam2/context.py
import numpy as np
from liam2.utils import unique
        from liam2.expr import Variable

        self.extra[key] = value

    def __delitem__(self, key):
        del self.extra[key]

    def __contains__(self, key):
        entity = self.entity
        period = self.eval_ctx.period
        array_period = entity.array_period
        # entity.array can be None! (eg. with "explore")
        keyinarray = (self.is_array_period and
                      (key in entity.temp_variables or
                       key in entity.array.dtype.fields))
        # we need to check explicitly whether the key is in array_lag because
        # with output=None it can contain more fields than table.
        keyinlagarray = (entity.array_lag is not None and
                         array_period is not None and
                         period == array_period - 1 and
                         key in entity.array_lag.dtype.fields)
        keyintable = (entity.table is not None and
                      key in entity.table.dtype.fields)
        return key in self.extra or keyinarray or keyinlagarray or keyintable

    def keys(self, extra=True):
        res = list(self.entity.array.dtype.names)
        res.extend(sorted(self.entity.temp_variables.keys()))
        if extra:
            res.extend(sorted(self.extra.keys()))
        # in theory, this should not be needed because we present defining a function argument with the same
        # name than an entity field

        assert list(unique(res)) == res