<commit_before># This file is part of LiSE, a framework for life simulation games.
# Copyright (c) 2013-2014 <NAME>,  <EMAIL>
import networkx as nx
from gorm.xjson import json_dump
from .node import Node
from .util import (
    path_len,
    CacheError,
    TravelException,
    encache,
    enkeycache,
    dekeycache,
    cache_forward,
    needcache
)


class Thing(Node):
    """The sort of item that has a particular location at any given time.

    If a Thing is in a Place, it is standing still. If it is in a
    Portal, it is moving through that Portal however fast it must in
    order to arrive at the other end when it is scheduled to. If it is
    in another Thing, then it is wherever that is, and moving the
    same.

    """
    def __init__(self, *args, **kwargs):
        """If caching, initialize the cache."""
        super().__init__(*args, **kwargs)
        self._loccache = {}

    def __iter__(self):
        """Iterate over a cached set of keys if possible and caching's
        enabled.

        Iterate over some special keys too.

        """
        extrakeys = [
            'name',
            'character',
            'location',
            'next_location',
            'arrival_time',
            'next_arrival_time'
        ]
        if not self.engine.caching:
            yield from extrakeys
            yield from super().__iter__()
            return
        (branch, tick) = self.engine.time
        if branch not in self._keycache:
            self._keycache[branch] = {}
        if tick not in self._keycache[branch]:
            self._keycache[branch][tick] = set(
                extrakeys + list(super().__iter__())
            )
        yield from self._keycache[branch][tick]

    def __contains__(self, key):
        if key in (
                'name',
                'character',
                'location',
                'next_location',
                'arrival_time',
                'next_arrival_time',
                'locations'
        ):
            return True
        return super().__contains__(key)

    def __getitem__(self, key):
        """Return one of my stats stored in the database, or a few
        special cases:

        ``name``: return the name that uniquely identifies me within
        my Character

        ``character``: return the name of my character

        ``location``: return the name of my location

        ``arrival_time``: return the tick when I arrived in the
        present location

        ``next_location``: if I'm in transit, return where to, else return None

        ``next_arrival_time``: return the tick when I'm going to
        arrive at ``next_location``

        ``locations``: return a pair of ``(location, next_location)``

        """
        if key == 'name':
            return self.name
        elif key == 'character':
            return self.character.name
        elif key == 'location':
            return self['locations'][0]
        elif key == 'arrival_time':
            if not self.engine.caching:
                return self._get_arrival_time()
            for (branch, tick) in self.engine._active_branches():
                self._load_locs_branch(branch)
                try:
                    return max(
                        t for t in self._loccache[branch]
                        if t <= tick
                    )
                except ValueError:
                    continue
            raise CacheError("Locations not cached correctly")
        elif key == 'next_location':
            return self['locations'][1]
        elif key == 'next_arrival_time':
            if not self.engine.caching:
                return self._get_next_arrival_time()
            for (branch, tick) in self.engine._active_branches():
                self._load_locs_branch(branch)
                try:
                    return min(
                        t for t in self._loccache[branch]
                        if t > tick
                    )
                except ValueError:
                    continue
            return None
        elif key == 'locations':
            if not self.engine.caching:
                return self._loc_and_next()
            for (branch, tick) in self.engine._active_branches():
                self._load_locs_branch(branch)
                try:
                    return self._loccache[branch][self['arrival_time']]
                except ValueError:
                    continue
            raise CacheError("Locations not cached correctly")
        else:
            if not self.engine.caching:
                return super().__getitem__(key)
            (branch, tick) = self.engine.time
            cache_forward(self._cache, key, branch, tick)
            if needcache(self._cache, key, branch, tick):
                encache(self, self._cache, key, super().__getitem__(key))
            r = self._cache[key][branch][tick]
            if r is None:
                raise KeyError("Key {} is not set now".format(key))
            return r<commit_msg>once-again wrap mutable values properly<commit_after># This file is part of LiSE, a framework for life simulation games.
# Copyright (c) 2013-2014 <NAME>,  <EMAIL>
import networkx as nx
from gorm.xjson import json_dump
from .node import Node
from .util import (
    path_len,
    CacheError,
    TravelException,
    encache,
    enkeycache,
    dekeycache,
    cache_forward,
    needcache,
    JSONReWrapper,
    JSONListReWrapper
)


class Thing(Node):
    """The sort of item that has a particular location at any given time.

    If a Thing is in a Place, it is standing still. If it is in a
    Portal, it is moving through that Portal however fast it must in
    order to arrive at the other end when it is scheduled to. If it is
    in another Thing, then it is wherever that is, and moving the
    same.

    """
    def __init__(self, *args, **kwargs):
        """If caching, initialize the cache."""
        super().__init__(*args, **kwargs)
        self._loccache = {}

    def __iter__(self):
        """Iterate over a cached set of keys if possible and caching's
        enabled.

        Iterate over some special keys too.

        """
        extrakeys = [
            'name',
            'character',
            'location',
            'next_location',
            'arrival_time',
            'next_arrival_time'
        ]
        if not self.engine.caching:
            yield from extrakeys
            yield from super().__iter__()
            return
        (branch, tick) = self.engine.time
        if branch not in self._keycache:
            self._keycache[branch] = {}
        if tick not in self._keycache[branch]:
            self._keycache[branch][tick] = set(
                extrakeys + list(super().__iter__())
            )
        yield from self._keycache[branch][tick]

    def __contains__(self, key):
        if key in (
                'name',
                'character',
                'location',
                'next_location',
                'arrival_time',
                'next_arrival_time',
                'locations'
        ):
            return True
        return super().__contains__(key)

    def __getitem__(self, key):
        """Return one of my stats stored in the database, or a few
        special cases:

        ``name``: return the name that uniquely identifies me within
        my Character

        ``character``: return the name of my character

        ``location``: return the name of my location

        ``arrival_time``: return the tick when I arrived in the
        present location

        ``next_location``: if I'm in transit, return where to, else return None

        ``next_arrival_time``: return the tick when I'm going to
        arrive at ``next_location``

        ``locations``: return a pair of ``(location, next_location)``

        """
        if key == 'name':
            return self.name
        elif key == 'character':
            return self.character.name
        elif key == 'location':
            return self['locations'][0]
        elif key == 'arrival_time':
            if not self.engine.caching:
                return self._get_arrival_time()
            for (branch, tick) in self.engine._active_branches():
                self._load_locs_branch(branch)
                try:
                    return max(
                        t for t in self._loccache[branch]
                        if t <= tick
                    )
                except ValueError:
                    continue
            raise CacheError("Locations not cached correctly")
        elif key == 'next_location':
            return self['locations'][1]
        elif key == 'next_arrival_time':
            if not self.engine.caching:
                return self._get_next_arrival_time()
            for (branch, tick) in self.engine._active_branches():
                self._load_locs_branch(branch)
                try:
                    return min(
                        t for t in self._loccache[branch]
                        if t > tick
                    )
                except ValueError:
                    continue
            return None
        elif key == 'locations':
            if not self.engine.caching:
                return self._loc_and_next()
            for (branch, tick) in self.engine._active_branches():
                self._load_locs_branch(branch)
                try:
                    return self._loccache[branch][self['arrival_time']]
                except ValueError:
                    continue
            raise CacheError("Locations not cached correctly")
        else:
            if not self.engine.caching:
                return super().__getitem__(key)
            (branch, tick) = self.engine.time
            cache_forward(self._cache, key, branch, tick)
            if needcache(self._cache, key, branch, tick):
                encache(self, self._cache, key, super().__getitem__(key))
            r = self._cache[key][branch][tick]
            if r is None:
                raise KeyError("Key {} is not set now".format(key))
            return (
                JSONReWrapper(self, key, r) if isinstance(r, dict) else
                JSONListReWrapper(self, key, r) if isinstance(r, list) else
                r
            )
{'fraction_non_alphanumeric': 0.08734939759036145, 'fraction_numerical': 0.00194325689856199, 'mean_word_length': 1.596619576185671, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1818413', 'n_tokens_mistral': 2739, 'n_tokens_neox': 2575, 'n_words': 869}