HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/moodle-mlbackend-python/test/time-commits
#!/usr/bin/python3
"""A script to measure performance of various commits.

USAGE: ./test/time-commits REF [REF [REF [...]]]

where REF is a git commit hash, tag, or branch.

This runs the 'stashed_evaluation_long' test on the commits listed and
prints statistics about how well each did.

For example:

$ ./test/time-commits keras-one-layer

keras-one-layer
Switched to branch 'keras-one-layer'
b''
score                0.918
precision            0.921
recall               0.917
score_deviation      0.00262
accuracy             0.917
duration:           67.46

The test as defined in `test/test_webapp.py` in the latest commit is
used. That is, if you go:

[edit test/test_webapp.py]
$ git add test/test_webapp.py
$ git commit -mtest
$ ./test/time-commits old-commit older-commit

"old-commit" and "older-commit" will be tested as if they had the
latest test_webapp.py.
"""

from subprocess import run, CalledProcessError
import re
import sys
import os

SLOW_TESTS = "MOODLE_MLBACKEND_RUN_SLOW_TESTS"

# This environment variable tells test_webapp to allow the slow tests,
# which is what we want for timing purposes.
os.environ[SLOW_TESTS] = '1'

# This one makes the tests use the old style plaintext password string,
# which not all commits might have.
os.environ["MOODLE_MLBACKEND_TEST_OLD_PASSWORDS"] = '1'


TEST_WEBAPP_COMMIT = 'stashed-eval'
TEST = 'stashed_evaluation_long'
#TEST = 'stashed_evaluation_short'

PYTEST = ['python3',
          '-mpytest',
          '-Wignore::DeprecationWarning',
          '-Wignore::FutureWarning',
          '-s',
          '--durations=0']


def checkout_branch(b):
    run(['git',
         'checkout',
         b], check=True)


def checkout_test(b=TEST_WEBAPP_COMMIT):
    # Ensure the test is exactly the same in every test run.
    run(['git',
         'checkout',
         b,
         '--',
         'test/test_webapp.py'], check=True)


def run_test():
    try:
        p = run(PYTEST + ['-k', TEST],
                capture_output=True,
                check=True)
    except CalledProcessError as e:
        print(e.output.decode('utf8'))
        print(e)
        print(f'{SLOW_TESTS}=1 {" ".join(e.cmd)}')
        return

    out = p.stdout.decode('utf8')

    for metric in ['score', 'precision', 'recall', 'score_deviation', 'accuracy',
                   'balanced accuracy']:
        m = re.search(r"'%s': (\d+\.?\d+)" % (metric,), out)
        if m is None:
            print(f"{metric} is missing")
        else:
            name = f"{metric}:"
            val = float(m.group(1))
            print(f"{metric:<20} {val:.3}")

    m = re.search(r"(\d+\.?\d+)s call.+%s" % (TEST,), out)
    if m is None:
        print(f"duration is missing")
    else:
        print(f"duration:           {m.group(1)}")


def current_ref():
    """Get the branch or tag if we are on one, otherwise the commit hash"""
    try:
        p = run(['git',
                 'symbolic-ref',
                 'HEAD',
                 '--short'],
                capture_output=True,
                check=True)
    except CalledProcessError as e:
        print(e)
        p = run(['git',
                 'rev-parse',
                 'HEAD'])

    return p.stdout.decode('utf-8').strip()


def main():
    args = sys.argv[1:]
    if not args or '-h' in args or '--help' in args:
        print(__doc__)
        sys.exit()

    if args in (['-w'], ['--working-tree']):
        run_test()
        sys.exit()

    original_ref = current_ref()
    try:
        for commit in args:
            print()
            print(commit)
            checkout_branch(commit)
            checkout_test(original_ref)
            run_test()
            checkout_test(commit)
    finally:
        checkout_branch(original_ref)


main()