# Path: rep0st/framework/data/transaction.py
# def transactional() -> Any:
# 
#   def decorator(fun: Callable):
#     transactional_configuration = _TransactionalConfiguration()
# 
#     @functools.wraps(fun)
#     def wrapper(*args: Any, **kwargs: Any) -> Any:
#       if not hasattr(transactional_state, 'depth'):
#         transactional_state.depth = 0
#       session = transactional_configuration.database_session_provider.get()
#       if not transactional_state.depth:
#         log.debug(
#             f'Starting transaction on method {transactional_configuration.name}'
#         )
#         # Session start. Implicit with transactional_configuration.injector.get(DatabaseSession)
#         pass
#       transactional_state.depth += 1
#       try:
#         ret = fun(*args, **kwargs)
#         transactional_state.depth -= 1
#         if transactional_state.depth == 0:
#           log.debug(
#               f'Committing transaction on method {transactional_configuration.name}'
#           )
#           # We reached the outer most @transactional(). Commit the transaction.
#           session.commit()
#       except:
#         transactional_state.depth -= 1
#         if transactional_state.depth == 0:
#           log.info(
#               f'Rolling back transaction on method {transactional_configuration.name}'
#           )
#           # We reached the outer most @transactional(). Rollback the transaction.
#           session.rollback()
#         raise
#       finally:
#         if transactional_state.depth == 0:
#           log.debug(
#               f'Removing session on method {transactional_configuration.name}')
#           # Close the session, to remove invalid state in case of errors.
#           session.close()
#           # We reached the outer most @transactional(). Close the session.
#           session_factory = transactional_configuration.database_session_factory_provider.get(
#           )
#           session_factory.remove()
#           delattr(transactional_state, 'depth')
#       return ret
# 
#     wrapper.__transactional__ = transactional_configuration
#     return wrapper
# 
#   return decorator


from typing import Any, Collection, Generic, NamedTuple, Type, TypeVar
from injector import ProviderOf
from sqlalchemy import func, inspect
from sqlalchemy.orm import Query, Session
from rep0st.framework.data.transaction import transactional
      a: key.__getattribute__(a)
      for a in dir(key)
      if not a.startswith('__') and not callable(getattr(key, a))
  }


class Repository(Generic[K, V]):
  session_provider: ProviderOf[Session] = None

  def __init__(self, k_type: Type[K], v_type: Type[V],
               session_provider: ProviderOf[Session]) -> None:
    self._k_type = k_type
    self._v_type = v_type
    self.session_provider = session_provider

  def _get_session(self) -> Session:
    return self.session_provider.get()

  @transactional()
  def add(self, value: V) -> V:
    session = self._get_session()
    session.add(value)
    return value

  @transactional()
  def add_all(self, values: Collection[V]) -> Collection[V]:
    session = self._get_session()
    session.add_all(values)
    return values


# Path: rep0st/framework/data/transaction.py
# def transactional() -> Any:
# 
#   def decorator(fun: Callable):
#     transactional_configuration = _TransactionalConfiguration()
# 
#     @functools.wraps(fun)
#     def wrapper(*args: Any, **kwargs: Any) -> Any:
#       if not hasattr(transactional_state, 'depth'):
#         transactional_state.depth = 0
#       session = transactional_configuration.database_session_provider.get()
#       if not transactional_state.depth:
#         log.debug(
#             f'Starting transaction on method {transactional_configuration.name}'
#         )
#         # Session start. Implicit with transactional_configuration.injector.get(DatabaseSession)
#         pass
#       transactional_state.depth += 1
#       try:
#         ret = fun(*args, **kwargs)
#         transactional_state.depth -= 1
#         if transactional_state.depth == 0:
#           log.debug(
#               f'Committing transaction on method {transactional_configuration.name}'
#           )
#           # We reached the outer most @transactional(). Commit the transaction.
#           session.commit()
#       except:
#         transactional_state.depth -= 1
#         if transactional_state.depth == 0:
#           log.info(
#               f'Rolling back transaction on method {transactional_configuration.name}'
#           )
#           # We reached the outer most @transactional(). Rollback the transaction.
#           session.rollback()
#         raise
#       finally:
#         if transactional_state.depth == 0:
#           log.debug(
#               f'Removing session on method {transactional_configuration.name}')
#           # Close the session, to remove invalid state in case of errors.
#           session.close()
#           # We reached the outer most @transactional(). Close the session.
#           session_factory = transactional_configuration.database_session_factory_provider.get(
#           )
#           session_factory.remove()
#           delattr(transactional_state, 'depth')
#       return ret
# 
#     wrapper.__transactional__ = transactional_configuration
#     return wrapper
# 
#   return decorator


# Path: rep0st/framework/data/repository.py
from typing import Any, Collection, Generic, NamedTuple, Type, TypeVar
from injector import ProviderOf
from sqlalchemy import func, inspect
from sqlalchemy.orm import Query, Session
from rep0st.framework.data.transaction import transactional

      a: key.__getattribute__(a)
      for a in dir(key)
      if not a.startswith('__') and not callable(getattr(key, a))
  }


class Repository(Generic[K, V]):
  session_provider: ProviderOf[Session] = None

  def __init__(self, k_type: Type[K], v_type: Type[V],
               session_provider: ProviderOf[Session]) -> None:
    self._k_type = k_type
    self._v_type = v_type
    self.session_provider = session_provider

  def _get_session(self) -> Session:
    return self.session_provider.get()

  @transactional()
  def add(self, value: V) -> V:
    session = self._get_session()
    session.add(value)
    return value

  @transactional()
  def add_all(self, values: Collection[V]) -> Collection[V]:
    session = self._get_session()
    session.add_all(values)
    return values


  @transactional()