<commit_before># This file is part of allegedb, an object relational mapper for versioned graphs.
# Copyright (C) <NAME>. <EMAIL>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
"""The main interface to the allegedb ORM, and some supporting functions and classes"""
from contextlib import ContextDecorator
from weakref import WeakValueDictionary

from blinker import Signal

from allegedb.window import update_window, update_backward_window
from .graph import (
    Graph,
    DiGraph,
    MultiGraph,
    MultiDiGraph,
    Node,
    Edge
)
from .query import QueryEngine, TimeError
from .window import HistoryError


class GraphNameError(KeyError):
    pass


class PlanningContext(ContextDecorator):
    """A context manager for 'hypothetical' edits.

    Start a block of code like:

    with orm.plan:
        ...

    and any changes you make to the world state within that block will be
    'plans,' meaning that they are used as defaults. The world will
    obey your plan unless you make changes to the same entities outside
    of the plan, in which case the world will obey those.

    New branches cannot be started within plans.

    """
    __slots__ = ['orm', 'time']

    def __init__(self, orm):
        self.orm = orm

    def __enter__(self):
        if self.orm._planning:
            raise ValueError("Already planning")
        self.orm._planning = True
        self.time = self.orm.btt()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.orm._obranch, self.orm._oturn, self.orm._otick = self.time
        self.orm._planning = False


class TimeSignal(Signal):
    """Acts like a tuple of the time in (branch, turn) for the most part.

    This is a Signal, so pass a function to the connect(...) method and
    it will be called whenever the time changes. Not when the tick
    changes, though. If you really need something done whenever the
    tick changes, override the _set_tick method of
    :class:`allegedb.ORM`.

    """
    def __init__(self, engine):
        super().__init__()
        self.engine = engine

    def __iter__(self):
        yield self.engine.branch
        yield self.engine.turn<commit_msg>Improve docstrings in allegedb<commit_after># This file is part of allegedb, an object relational mapper for versioned graphs.
# Copyright (C) <NAME>. <EMAIL>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
"""The main interface to the allegedb ORM, and some supporting functions and classes"""
from contextlib import ContextDecorator
from weakref import WeakValueDictionary

from blinker import Signal

from allegedb.window import update_window, update_backward_window
from .graph import (
    Graph,
    DiGraph,
    MultiGraph,
    MultiDiGraph,
    Node,
    Edge
)
from .query import QueryEngine, TimeError
from .window import HistoryError


class GraphNameError(KeyError):
    """For errors involving graphs' names"""


class PlanningContext(ContextDecorator):
    """A context manager for 'hypothetical' edits.

    Start a block of code like:

    ```
    with orm.plan():
        ...
    ```

    and any changes you make to the world state within that block will be
    'plans,' meaning that they are used as defaults. The world will
    obey your plan unless you make changes to the same entities outside
    of the plan, in which case the world will obey those, and cancel any
    future plan.

    New branches cannot be started within plans.

    """
    __slots__ = ['orm', 'time']

    def __init__(self, orm):
        self.orm = orm

    def __enter__(self):
        if self.orm._planning:
            raise ValueError("Already planning")
        self.orm._planning = True
        self.time = self.orm.btt()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.orm._obranch, self.orm._oturn, self.orm._otick = self.time
        self.orm._planning = False


class TimeSignal(Signal):
    """Acts like a list of ``[branch, turn]`` for the most part.

    You can set these to new values, or even replace them with a whole new
    ``[branch, turn]`` if you wish. It's even possible to use the strings
    ``'branch'`` or ``'turn'`` in the place of indices, but at that point
    you might prefer to set ``engine.branch`` or ``engine.turn`` directly.

    This is a Signal, so pass a function to the connect(...) method and
    it will be called whenever the time changes. Not when the tick
    changes, though. If you really need something done whenever the
    tick changes, override the _set_tick method of
    :class:`allegedb.ORM`.

    """
    def __init__(self, engine):
        super().__init__()
        self.engine = engine

    def __iter__(self):
        yield self.engine.branch
        yield self.engine.turn
{'fraction_non_alphanumeric': 0.07515517530615669, 'fraction_numerical': 0.00033551417547391375, 'mean_word_length': 3.148921363952679, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '1437296', 'n_tokens_mistral': 1638, 'n_tokens_neox': 1588, 'n_words': 748}