Beispiel #1
0
def get_and_start_scan_msgr(server=None, password=None):
    """Get a scanner messenger.

    Args:
        server (str): "server:port" or localhost default if omitted.
        password (str): prompts on the command line if omitted.

    Returns:
        ScanMessenger: authenicated connection to the server.  When you
            are done with this you should call `.closeUser()` and then
            `.stop()`.

    Raises:
        PlomExistingLoginException: scanner is logged in somewhere else.
            TODO: xref the force logout function once it exists.
            TODO: for now use command line tool `plom-scan clear`.
    """
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    if password is None:
        password = getpass.getpass("Please enter the 'scanner' password: "******"scanner", password)
    return msgr
Beispiel #2
0
def clearLogin(server=None, password=None):
    if server and ":" in server:
        s, p = server.split(":")
        scanMessenger = ScanMessenger(s, port=p)
    else:
        scanMessenger = ScanMessenger(server)
    scanMessenger.start()

    # get the password if not specified
    if password is None:
        try:
            pwd = getpass.getpass("Please enter the 'scanner' password:"******"ERROR", error)
            exit(1)
    else:
        pwd = password

    scanMessenger.clearAuthorisation("scanner", pwd)
    print("Scanner login cleared.")
    scanMessenger.stop()
Beispiel #3
0
def checkStatus(server=None, pwd=None):
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    if not pwd:
        pwd = getpass.getpass("Please enter the 'scanner' password:"******"scanner", pwd)
    except PlomExistingLoginException as e:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    spec = msgr.get_spec()

    ST = msgr.getScannedTests(
    )  # returns pairs of [page,version] - only display pages
    UT = msgr.getUnusedTests()
    IT = msgr.getIncompleteTests()
    msgr.closeUser()
    msgr.stop()

    print("Test papers unused: [{}]".format(format_int_list_with_runs(UT)))

    print("Scanned tests in the system:")
    for t in ST:
        scannedTPages = []
        scannedHWPages = []
        for x in ST[t]:
            if x[0][0] == "t":  # is a test page = "t.p"
                p = int(x[0].split(".")[1])
                scannedTPages.append(p)
            elif x[0][0] == "h":  # is a hw page = "h.q.o"
                q = int(x[0].split(".")[1])
                if q not in scannedHWPages:
                    scannedHWPages.append(q)

        print("\t{}: testPages [{}] hwPages [{}]".format(
            t,
            format_int_list_with_runs(scannedTPages),
            format_int_list_with_runs(scannedHWPages),
        ))
    print("Number of scanned tests in the system: {}".format(len(ST)))
    print("Incomplete scans - listed with their missing pages: ")
    for t in IT:
        missingPagesT = []
        missingPagesH = []
        for x in IT[t]:  # each entry is [page, version, scanned?]
            if x[0][0] == "t":  # is a test page
                p = int(x[0].split(".")[1])
                if x[2] is False:
                    missingPagesT.append(p)
            elif x[0][0] == "h":  # is a w page
                q = int(x[0].split(".")[1])
                if x[2] is False:
                    missingPagesH.append(q)
        print("\t{}: t[{}] h[{}]".format(
            t,
            format_int_list_with_runs(missingPagesT),
            format_int_list_with_runs(missingPagesH),
        ))
Beispiel #4
0
def replaceMissingHWQ(server, pwd, student_id, question):
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    if not pwd:
        pwd = getpass.getpass("Please enter the 'scanner' password:"******"scanner", pwd)
    except PlomExistingLoginException as e:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    rval = msgr.replaceMissingHWQuestion(
        student_id=student_id, test=None,
        question=question)  # can replace by SID or by test-number
    msgr.triggerUpdateAfterHWUpload()

    msgr.closeUser()
    msgr.stop()

    return rval
Beispiel #5
0
def get_number_of_questions(server=None, pwd=None):
    """Contact server for number of questions."""
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    if not pwd:
        pwd = getpass.getpass("Please enter the 'scanner' password:"******"scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(-1)

    spec = msgr.get_spec()
    msgr.closeUser()
    msgr.stop()
    return spec["numberOfQuestions"]
Beispiel #6
0
def checkMissingHWQ(server=None, pwd=None):
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    if not pwd:
        pwd = getpass.getpass("Please enter the 'scanner' password:"******"scanner", pwd)
    except PlomExistingLoginException as e:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    missingHWQ = msgr.getMissingHW()
    msgr.closeUser()
    msgr.stop()

    return missingHWQ
Beispiel #7
0
def createNewBundle(bundle_name, md5, server=None, password=None):
    """Create a new bundle with a given name.

    Args:
        bundle_name (str): a bundle name, typically extracted from the
            name of a PDF file.
        md5 (str): the md5sum of the file from which this bundle is
            extracted.  In future, could be extended to a list/dict for
            more than one file.
        server: information to contact a server.
        password: information to contact a server.

    Returns:
        list: either the pair `[True, bundle_name]` or `[False]`.
    """
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    if password is None:
        pwd = getpass.getpass("Please enter the 'scanner' password: "******"scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    try:
        bundle_success = msgr.createNewBundle(bundle_name, md5)
    finally:
        msgr.closeUser()
        msgr.stop()

    return bundle_success
Beispiel #8
0
def doesBundleExist(bundle_file, server=None, password=None):
    """Check if bundle exists and is so does its md5sum match a given file.

    Args:
        bundle_file (str, Path): needs to be the actual file not the
            bundle name because we need to compute the md5sum.

    Returns:
        list: the pair `[True, bundle_name]` where `bundle_name` is a
            `str` or `[False, reason]` where `reason` is a `str`.
    """
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    # get the password if not specified
    if password is None:
        pwd = getpass.getpass("Please enter the 'scanner' password:"******"scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    bundle_name, md5 = bundle_name_and_md5(bundle_file)
    bundle_success = msgr.doesBundleExist(bundle_name, md5)

    msgr.closeUser()
    msgr.stop()

    return bundle_success
Beispiel #9
0
def checkTestHasThatSID(student_id, server=None, password=None):
    """Get test-number corresponding to given student id

    For HW tests should be pre-IDd, so this function is used
    to map a student-id to the underlying test. This means that
    and uploaded HW page can be matched to the test in the database.

    Returns the test-number if the SID is matched to a test in the database
    else returns None.
    """
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    # get the password if not specified
    if password is None:
        try:
            pwd = getpass.getpass("Please enter the 'scanner' password:"******"ERROR", error)
    else:
        pwd = password

    # get started
    try:
        msgr.requestAndSaveToken("scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    # get test_number from SID.
    # response is [true, test_number] or [false, reason]
    test_success = msgr.sidToTest(student_id)

    msgr.closeUser()
    msgr.stop()

    if test_success[0]:  # found it
        return test_success[1]  # return the number
    else:  # couldn't find it
        return None
Beispiel #10
0
def uploadLPages(bundle_name,
                 skip_list,
                 student_id,
                 server=None,
                 password=None):
    """Upload the hw pages to the server.

    lpages uploaded to given student_id.
    Skips pages-image with orders in the skip-list (i.e., the page
    number within the bundle.pdf)

    Bundle must already be created.  We will upload the
    files and then send a 'please trigger an update' message to the server.
    """
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    # get the password if not specified
    if password is None:
        try:
            pwd = getpass.getpass("Please enter the 'scanner' password:"******"ERROR", error)
    else:
        pwd = password

    # get started
    try:
        msgr.requestAndSaveToken("scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-hwscan clear"'
        )
        exit(10)

    file_list = []
    # files are sitting in "bundles/submittedLoose/<bundle_name>"
    os.chdir(os.path.join("bundles", "submittedLoose", bundle_name))
    # Look for pages in pageImages
    for ext in PlomImageExts:
        file_list.extend(
            sorted(glob(os.path.join("pageImages", "*.{}".format(ext)))))

    LUP = sendLFiles(msgr, file_list, skip_list, student_id, bundle_name)

    updates = msgr.triggerUpdateAfterLUpload()

    # go back to original dir
    os.chdir("..")
    os.chdir("..")
    os.chdir("..")

    # close down messenger
    msgr.closeUser()
    msgr.stop()

    return [LUP, updates]
Beispiel #11
0
def uploadTPages(bundleDir, skip_list, server=None, password=None):
    """Upload the test pages to the server.

    Skips pages-image with orders in the skip-list (i.e., the page
    number within the bundle.pdf)

    Bundle must already be created.  We will upload the
    files and then send a 'please trigger an update' message to the server.
    """
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    # get the password if not specified
    if password is None:
        try:
            pwd = getpass.getpass("Please enter the 'scanner' password:"******"ERROR", error)
    else:
        pwd = password

    # get started
    try:
        msgr.requestAndSaveToken("scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear" or "plom-hwscan clear"'
        )
        exit(10)

    if not bundleDir.is_dir():
        raise ValueError("should've been a directory!")

    files = []
    # Look for pages in decodedPages
    for ext in PlomImageExts:
        files.extend(
            sorted((bundleDir / "decodedPages").glob("t*.{}".format(ext))))
    TUP = sendTestFiles(msgr, bundleDir.name, files, skip_list)
    # we do not automatically replace any missing test-pages, since that is a serious issue for tests, and should be done only by manager.

    updates = msgr.triggerUpdateAfterTUpload()

    # close down messenger
    msgr.closeUser()
    msgr.stop()

    return [TUP, updates]
Beispiel #12
0
def processBitmaps(bundle, server=None, password=None):
    examsScannedNow = defaultdict(list)

    if server and ":" in server:
        s, p = server.split(":")
        scanMessenger = ScanMessenger(s, port=p)
    else:
        scanMessenger = ScanMessenger(server)
    scanMessenger.start()

    # get the password if not specified
    if password is None:
        try:
            pwd = getpass.getpass("Please enter the 'scanner' password:"******"ERROR", error)
            exit(1)
    else:
        pwd = password

    # get started
    try:
        scanMessenger.requestAndSaveToken("scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    spec = scanMessenger.get_spec()
    scanMessenger.closeUser()
    scanMessenger.stop()

    decodeQRs(bundle / "pageImages")
    checkQRsValid(bundle, spec, examsScannedNow)
    validateQRsAgainstSpec(spec, examsScannedNow)
    moveScansIntoPlace(examsScannedNow)
Beispiel #13
0
def upload_collisions(bundleDir, server=None, password=None):
    if server and ":" in server:
        s, p = server.split(":")
        scanMessenger = ScanMessenger(s, port=p)
    else:
        scanMessenger = ScanMessenger(server)
    scanMessenger.start()

    if password is None:
        pwd = getpass.getpass("Please enter the 'scanner' password: "******"scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-scan clear"'
        )
        exit(10)

    try:
        if not bundleDir.is_dir():
            raise ValueError("should've been a directory!")

        files = []
        for ext in PlomImageExts:
            files.extend(
                (bundleDir / "uploads/collidingPages").glob("*.{}".format(ext))
            )
        sendCollidingFiles(scanMessenger, bundleDir.name, files)
    finally:
        scanMessenger.closeUser()
        scanMessenger.stop()
Beispiel #14
0
def verifiedComplete(server=None, password=None):

    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    # get the password if not specified
    if password is None:
        try:
            pwd = getpass.getpass("Please enter the 'scanner' password:"******"ERROR", error)
    else:
        pwd = password

    # get started
    try:
        msgr.requestAndSaveToken("scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-hwscan clear"'
        )
        exit(10)

    # grab number of questions - so we can work out what is missing
    spec = msgr.get_spec()
    numberOfQuestions = spec["numberOfQuestions"]

    msgr.closeUser()
    msgr.stop()

    hwByQ = defaultdict(list)
    for fn in glob.glob("submittedHWByQ/*.pdf"):
        IDQ = IDQorIDorBad(fn)
        if len(IDQ) == 3:
            sid, q = IDQ[1:]
            hwByQ[sid].append([fn, q])
    # return fileNames belonging to complete homeworks
    validFiles = []
    for sid in hwByQ:
        if len(hwByQ[sid]) == numberOfQuestions:
            validFiles += [x[0] for x in hwByQ[sid]]
    return validFiles
Beispiel #15
0
def whoSubmittedWhatOnServer(server, password):
    if server and ":" in server:
        s, p = server.split(":")
        msgr = ScanMessenger(s, port=p)
    else:
        msgr = ScanMessenger(server)
    msgr.start()

    # get the password if not specified
    if password is None:
        try:
            pwd = getpass.getpass("Please enter the 'scanner' password:"******"ERROR", error)
    else:
        pwd = password

    # get started
    try:
        msgr.requestAndSaveToken("scanner", pwd)
    except PlomExistingLoginException:
        print(
            "You appear to be already logged in!\n\n"
            "  * Perhaps a previous session crashed?\n"
            "  * Do you have another scanner-script running,\n"
            "    e.g., on another computer?\n\n"
            'In order to force-logout the existing authorisation run "plom-hwscan clear"'
        )
        exit(10)

    missingHWQ = msgr.getMissingHW()  # passes back dict
    completeHW = msgr.getCompleteHW()  # passes back list [test_number, sid]

    msgr.closeUser()
    msgr.stop()

    print(">> Checking incomplete submissions on server <<")
    print(
        "The following students have complete submissions (each question present)"
    )
    print(", ".join(sorted([x[1] for x in completeHW])))
    print(
        "The following students have incomplete submissions (missing questions indicated)"
    )
    for t in missingHWQ:
        print("{} missing {}".format(missingHWQ[t][1], missingHWQ[t][2:]))