Source code for uppaal2jetracer.versioncontrol.models

"""Models

This file provides all database models stored in the database.

This file can be imported as a module and contains the following classes:

    * Base: Base class which defines a database model.
    * Global: Model for representing a global user in the database.
    * Version: Model for representing a version in the database.
    * Project: Model for representing a project in the database.
"""

from __future__ import annotations

from datetime import datetime, timezone
from typing import NewType

from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import WriteOnlyMapped, WriteOnlyCollection
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship
from sqlalchemy import ForeignKey
from sqlalchemy import String
from sqlalchemy import PickleType
from tzlocal import get_localzone

from uppaal2jetracer.uppaalmodel.system import System
from uppaal2jetracer.versioncontrol.config import Config

Pickle = NewType("pickle", str)

db_config = Config()


[docs] class Base(DeclarativeBase): """ A class for representing a standard database model. """ type_annotation_map = { Pickle: PickleType() }
[docs] class Global(Base): """ A db model for representing the global user. :ivar _g_id: The id of the global model. :vartype _g_id: int :ivar _version_max: The version limit of all projects. :vartype _version_max: int :ivar _c_id: The id of the current project. :vartype _c_id: int :ivar _current_project: The current project. :vartype _current_project: Project """ __tablename__ = "global" _g_id: Mapped[int] = mapped_column(primary_key = True) _version_max: Mapped[int] _c_id: Mapped[int] = mapped_column(ForeignKey("project._p_id"), index = True, nullable = True) _current_project: Mapped[Project] = relationship(back_populates = "_current_user") @property def g_id(self) -> int: """ Get the id of the global model. :return: The id of the global model. :rtype: int """ return self._g_id @property def version_max(self) -> int: """ Get the current version limit. :return: The version limit. :rtype: int """ return self._version_max @property def c_id(self) -> int: """ Get the current project id. :return: The current project id. :rtype: int """ return self._c_id @property def current_project(self) -> Project: """ Get the current project. :return: The project currently being used. :rtype: Project """ return self._current_project @current_project.setter def current_project(self, project: Project): """ Select a project to be the new current project. :param project: The project you wish to select. :type project: Project """ if project is None: self.c_id = None self._current_project = None return self.c_id = project.p_id self._current_project = project @c_id.setter def c_id(self, p_id: int): """ Set the current project id. :param p_id: The project id you wish to set. :type p_id: int """ self._c_id = p_id @version_max.setter def version_max(self, num: int): """ Set a new version limit. :param num: The number the limit should be set to. :type num: int """ self._version_max = num
[docs] def get_model_protected(self) -> dict: """ Get the main attributes of the model. :return: A dictionary with the attributes. :rtype: dict """ return { "g_id": self._g_id, "version_max": self._version_max, "c_id": self._c_id, }
[docs] class Version(Base): """ A db model for representing a version. :ivar _v_id: The id of the version. :vartype _v_id: int :ivar _name: The name of the version. :vartype _name: str :ivar _date: The creation timestamp of the version. :vartype _date: datetime :ivar _favorite: Whether the version is favorited or not. :vartype _favorite: bool :ivar _file: The file data as a pickled object. :vartype _file: Pickle :ivar _p_id: The id of the version's project. :vartype _p_id: int :ivar _project: The version's project. :vartype _project: Project """ __tablename__ = "version" _v_id: Mapped[int] = mapped_column(primary_key = True) _name: Mapped[str] = mapped_column(String(db_config.DB_VERSION_NAME_MAX)) _date: Mapped[datetime] = mapped_column( index = True, default = lambda: datetime.now(timezone.utc).astimezone(get_localzone()) ) _favorite: Mapped[bool] = mapped_column(default = False) _file: Mapped[Pickle] _p_id: Mapped[int] = mapped_column(ForeignKey("project._p_id"), index = True) _project: Mapped[Project] = relationship(back_populates = "_versions")
[docs] def toggle_favorite(self): """ Toggle whether the version is favorited or not. """ self._favorite = not self._favorite
@property def v_id(self) -> int: """ Get the id of the version. :return: The id of the version. :rtype: int """ return self._v_id @property def name(self) -> str: """ Get the name of the version. :return: The name of the version. :rtype: str """ return self._name @property def date(self) -> datetime: """ Get the date of the version. :return: The date of the version. :rtype: datetime """ return self._date @property def favorite(self) -> bool: """ Get whether the version is favorited or not. :return: If the version is favorited. :rtype: bool """ return self._favorite @property def file(self) -> System: """ Get the file data of the version. :return: The System object of the pickled file. :rtype: System """ return self._file @property def p_id(self) -> int: """ Get the project id of the version. :return: The project id of the version. :rtype: int """ return self._p_id @property def project(self) -> Project: """ Get the project of the version. :return: The project this version is inside of. :rtype: Project """ return self._project
[docs] def get_model_protected(self) -> dict: """ Get the main attributes of the model. :return: A dictionary with the attributes. :rtype: dict """ return { "v_id": self._v_id, "name": self._name, "date": self._date.strftime("%Y-%m-%d-%H:%M:%S"), "favorite": self._favorite, "p_id": self._p_id }
[docs] class Project(Base): """ A db model for representing a project. :ivar _p_id: The id of the project. :vartype _p_id: int :ivar _name: The name of the project. :vartype _name: str :ivar _date: The creation timestamp of the project. :vartype _date: datetime :ivar _versions: The versions of the project. :vartype _versions: WriteOnlyMapped[Version] :ivar _current_user: The user model of the project. :vartype _current_user: Global """ __tablename__ = "project" _p_id: Mapped[int] = mapped_column(primary_key = True) _name: Mapped[str] = mapped_column(String(db_config.DB_PROJECT_NAME_MAX)) _date: Mapped[datetime] = mapped_column( index = True, default = lambda: datetime.now(timezone.utc).astimezone(get_localzone()) ) _versions: WriteOnlyMapped[Version] = relationship( back_populates = "_project", passive_deletes = True ) _current_user: Mapped[Global] = relationship(back_populates = "_current_project")
[docs] def add_version(self, version: Version): """ Add a version to the project. :param version: The version to add. :type version: Version """ self._versions.add(version)
[docs] def remove_version(self, version: Version): """ Remove a version from the project. :param version: The version to remove. :type version: Version """ self._versions.remove(version)
@property def p_id(self) -> int: """ Get the id of the project :return: The id of the project. :rtype: int """ return self._p_id @property def name(self) -> str: """ Get the name of the project :return: The name of the project :rtype: str """ return self._name @property def date(self) -> datetime: """ Get the date of the project. :return: The date of the project. :rtype: datetime """ return self._date @property def versions(self) -> WriteOnlyCollection[Version]: """ Get the versions inside the project. :return: Collection of versions in the project. :rtype: WriteOnlyCollection[Version] """ return self._versions @property def current_user(self) -> Global: """ Get the current user of the project. :return: The current user of the project. :rtype: Global """ return self._current_user
[docs] def get_model_protected(self) -> dict: """ Get the main attributes of the model. :return: A dictionary with the attributes. :rtype: dict """ return { "p_id": self._p_id, "name": self._name, "date": self._date.strftime("%Y-%m-%d-%H:%M:%S") }