Source code for plom.db.examDB

# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright (C) 2018-2022 Andrew Rechnitzer
# Copyright (C) 2020-2023 Colin B. Macdonald
# Copyright (C) 2022 Joey Shi
# Copyright (C) 2022 Brennen Chiu

from datetime import datetime, timezone
import logging

import peewee as pw
import pymysql

from plom.db.tables import (
    User,
    Bundle,
    Image,
    Test,
    Group,
    IDPrediction,
    IDGroup,
    DNMGroup,
    QGroup,
    TPage,
    HWPage,
    EXPage,
    UnknownPage,
    CollidingPage,
    DiscardedPage,
    IDPage,
    DNMPage,
    AImage,
    Annotation,
    APage,
    Rubric,
    ARLink,
    Tag,
    QuestionTagLink,
)
from plom.db.tables import database_proxy


log = logging.getLogger("DB")


[docs] class PlomDB: """The main Plom database.""" MySQL = None def __init__( self, dbfile_name="plom.db", *, db_name, db_host, db_port, db_username, db_password, ): db = None if self.should_connect_to_mysql( db_name, db_host, db_port, db_username, db_password ): log.info(f"Connecting to MySQL database: {db_name}...") db = self.connect_mysql(db_name, db_host, db_port, db_username, db_password) log.info(f"Connected to MySQL database: {db_name}") else: log.info("Connecting to SQLite...") db = self.connect_sqlite(dbfile_name) log.info("Connected to SQLite.") self._db = db database_proxy.initialize(self._db) with self._db: self._db.create_tables( [ User, Image, Bundle, Test, ## Group, IDGroup, IDPrediction, DNMGroup, QGroup, ## TPage, HWPage, EXPage, UnknownPage, CollidingPage, DiscardedPage, ## AImage, Annotation, ## APage, IDPage, DNMPage, ## Rubric, ARLink, Tag, QuestionTagLink, ] ) log.info("Database initialised.") # check if HAL has been created if User.get_or_none(name="HAL") is None: # pylint: disable=no-member User.create( name="HAL", password=None, last_activity=datetime.now(timezone.utc), last_action="Created", ) log.info("User 'HAL' created to do all our automated tasks.") def should_connect_to_mysql( self, db_name, db_host, db_port, db_username, db_password ): return True if db_name else False def connect_mysql(self, db_name, db_host, db_port, db_username, db_password): mysql_connection = pymysql.connect( host=db_host, port=db_port, user=db_username, password=db_password, ) mysql_connection.cursor().execute(f"CREATE DATABASE IF NOT EXISTS {db_name};") mysql_connection.close() self.MySQL = mysql_connection return pw.MySQLDatabase( db_name, host=db_host, port=db_port, user=db_username, password=db_password, ) # TODO? db.init? maybe stuff in other file? def connect_sqlite(self, dbfile_name): db = pw.SqliteDatabase(None) # can't handle pathlib? db.init(str(dbfile_name)) return db # User stuff from plom.db.db_user import ( createUser, doesUserExist, setUserPasswordHash, getUserPasswordHash, isUserEnabled, enableUser, disableUser, setUserToken, clearUserToken, getUserToken, userHasToken, validateToken, getUserList, getUserDetails, resetUsersToDo, ) from plom.db.db_create import ( doesBundleExist, createNewBundle, createReplacementBundle, how_many_papers_in_database, is_paper_database_populated, is_paper_database_initialised, addSingleTestToDB, nextqueue_position, createTest, addTPages, createIDGroup, createDNMGroup, createQGroup, getPageVersions, get_question_versions, get_all_question_versions, add_or_change_predicted_id, remove_predicted_id, remove_id_from_paper, hasAutoGenRubrics, ) from plom.db.db_upload import ( createNewImage, attachImageToTPage, createNewHWPage, uploadTestPage, is_sid_used, doesHWHaveIDPage, getMissingDNMPages, uploadHWPage, uploadUnknownPage, uploadCollidingPage, updateDNMGroup, updateIDGroup, buildUpToDateAnnotation, updateQGroup, updateGroupAfterChange, checkTestScanned, updateTestAfterChange, getSIDFromTest, sidToTest, replaceMissingHWQuestion, replaceMissingTestPage, removeAllScannedPages, get_groups_using_image, removeScannedTestPage, removeScannedHWPage, removeScannedEXPage, listBundles, getImagesInBundle, getBundleFromImage, getPageFromBundle, updateImageRotation, ) from plom.db.db_manage import ( getUnknownPages, getDiscardedPages, getCollidingPageNames, getTPageImage, getHWPageImage, getEXPageImage, getAllTestImages, getQuestionImages, testOwnersLoggedIn, moveUnknownToExtraPage, moveUnknownToHWPage, moveUnknownToTPage, checkTPage, removeUnknownImage, moveDiscardToUnknown, moveUnknownToCollision, getCollidingImage, removeCollidingImage, moveCollidingToTPage, ) from plom.db.db_report import ( RgetScannedTests, RgetIncompleteTests, RgetCompleteHW, RgetMissingHWQ, RgetUnusedTests, RgetIdentified, RgetNotAutoIdentified, RgetProgress, RgetMarkHistogram, RgetQuestionUserProgress, RgetCompletionStatus, RgetOutToDo, RgetStatus, RgetSpreadsheet, RgetOriginalFiles, RgetCoverPageInfo, RgetMarkReview, RgetIDReview, RgetUserFullProgress, RgetDanglingPages, RgetFilesInTest, RgetFilesInAllTests, ) from plom.db.db_identify import ( IDcountAll, IDcountIdentified, IDgetIdentifiedTests, IDgetUnidentifiedTests, IDgetNextTask, IDgiveTaskToClient, IDgetDoneTasks, IDgetImage, ID_get_donotmark_images, IDgetImagesOfUnidentified, ID_id_paper, IDgetImageFromATest, IDreviewID, ID_get_predictions, ID_delete_predictions, ) from plom.db.db_mark import ( McountAll, McountMarked, MgetDoneTasks, MgetNextTask, MgiveTaskToClient, MtakeTaskFromClient, Mget_annotations, MgetOneImageFilename, MgetWholePaper, MreviewQuestion, MrevertTask, MgetAllTags, McheckTagKeyExists, McheckTagTextExists, McreateNewTag, MgetTagsOfTask, MaddExistingTag, MremoveExistingTag, MgetOneImageRotation, ) from plom.db.db_rubric import ( McreateRubric, MgetRubrics, MmodifyRubric, Rget_test_rubric_count_matrix, Rget_rubric_counts, Rget_rubric_details, )