Beispiel #1
0
    def verify(
        self,
        speedtype="all",
        check=None,
        label=None,
        ratio=None,
        logdir=None,
        parallel=4,
        follow=["errors", "log", "progress"],
        poll_interval=0.1,
        debug=False,
    ):
        """
        Run the tests on this table defined in the lmfdb/verify folder.

        If parallel is True, sage should be in your path or aliased appropriately.

        Note that if check is not provided and parallel is False, no output will be printed, files
        will still be written to the log directory.

        INPUT:

        - ``speedtype`` -- a string: "overall", "overall_long", "fast", "slow" or "all".
        - ``check`` -- a string, giving the function name for a particular test.
            If provided, ``speedtype`` will be ignored.
        - ``label`` -- a string, giving the label for a particular object on which to run tests
            (as in the label_col attribute of the verifier).
        - ``ratio`` -- for slow and fast tests, override the ratio of rows to be tested. Only valid
            if ``check`` is provided.
        - ``logdir`` -- a directory to output log files.  Defaults to LMFDB_ROOT/logs/verification.
        - ``parallel`` -- A cap on the number of threads to use in parallel (if 0, doesn't use parallel).
            If ``check`` or ``label`` is set, parallel is ignored and tests are run directly.
        - ``follow`` -- Which output logs to print to stdout.  'log' contains failed tests,
            'errors' details on errors in tests, and 'progress' shows progress in running tests.
            If False or empty, a subprocess.Popen object to the subprocess will be returned.
        - ``poll_interval`` -- The polling interval to follow the output if executed in parallel.
        - ``debug`` -- if False, will redirect stdout and stderr for the spawned process to /dev/null.
        """
        self._check_verifications_enabled()
        if ratio is not None and check is None:
            raise ValueError(
                "You can only provide a ratio if you specify a check")
        lmfdb_root = os.path.abspath(
            os.path.join(os.path.dirname(os.path.realpath(__file__)), "..",
                         ".."))
        if logdir is None:
            logdir = os.path.join(lmfdb_root, "logs", "verification")
        if not os.path.exists(logdir):
            os.makedirs(logdir)
        if label is not None:
            parallel = 0
        verifier = self._verifier
        if check is None:
            olddir = os.path.join(logdir, "old")
            if not os.path.exists(olddir):
                os.makedirs(olddir)

            def move_to_old(tname):
                for suffix in [
                        ".log", ".errors", ".progress", ".started", ".done"
                ]:
                    filename = os.path.join(logdir, tname + suffix)
                    if os.path.exists(filename):
                        n = 0
                        oldfile = os.path.join(olddir, tname + str(n) + suffix)
                        while os.path.exists(oldfile):
                            n += 1
                            oldfile = os.path.join(olddir,
                                                   tname + str(n) + suffix)
                        shutil.move(filename, oldfile)

            if speedtype == "all":
                types = verifier.all_types()
            else:
                types = [verifier.speedtype(speedtype)]
            tabletypes = [
                "%s.%s" % (self.search_table, typ.shortname) for typ in types
                if verifier.get_checks_count(typ) > 0
            ]
            if len(tabletypes) == 0:
                raise ValueError(
                    "No checks of type %s defined for %s" %
                    (", ".join(typ.__name__
                               for typ in types), self.search_table))
            for tname in tabletypes:
                move_to_old(tname)
            if parallel:
                parallel = min(parallel, len(tabletypes))
                for tabletype in tabletypes:
                    print("Starting %s" % tabletype)
                cmd = os.path.abspath(
                    os.path.join(
                        os.path.dirname(os.path.realpath(__file__)),
                        "..",
                        "verify",
                        "verify_tables.py",
                    ))
                cmd = [
                    "sage",
                    "-python",
                    cmd,
                    "-j%s" % int(parallel),
                    logdir,
                    str(self.search_table),
                    speedtype,
                ]
                if debug:
                    pipe = subprocess.Popen(cmd)
                else:
                    DEVNULL = open(os.devnull, "wb")
                    pipe = subprocess.Popen(cmd,
                                            stdout=DEVNULL,
                                            stderr=DEVNULL)
                if follow:
                    from lmfdb.verify.follower import Follower

                    try:
                        Follower(logdir, tabletypes, follow,
                                 poll_interval).follow()
                    finally:
                        # kill the subprocess
                        # From the man page, the following will terminate child processes
                        if pipe.poll() is None:
                            pipe.send_signal(signal.SIGTERM)
                            pipe.send_signal(signal.SIGTERM)
                else:
                    return pipe
            else:
                for typ in types:
                    if verifier.get_checks_count(typ) == 0:
                        print("No %s checks defined for %s" %
                              (typ.__name__, self.search_table))
                    else:
                        print("Starting %s checks for %s" %
                              (typ.__name__, self.search_table))
                        verifier.run(typ, logdir, label)
        else:
            msg = "Starting check %s" % check
            if label is not None:
                msg += " for label %s" % label
            print(msg)
            verifier.run_check(check, label=label, ratio=ratio)
Beispiel #2
0
    def verify(
        self,
        speedtype="all",
        logdir=None,
        parallel=8,
        follow=["errors", "log", "progress"],
        poll_interval=0.1,
        debug=False,
    ):
        """
        Run verification tests on all tables (if defined in the lmfdb/verify folder).
        For more granular control, see the ``verify`` function on a particular table.

        sage should be in your path or aliased appropriately.

        INPUT:

        - ``speedtype`` -- a string: "overall", "overall_long", "fast", "slow" or "all".
        - ``logdir`` -- a directory to output log files.  Defaults to LMFDB_ROOT/logs/verification.
        - ``parallel`` -- A cap on the number of threads to use in parallel
        - ``follow`` -- The polling interval to follow the output.
            If 0, a parallel subprocess will be started and a subprocess.Popen object to it will be returned.
        - ``debug`` -- if False, will redirect stdout and stderr for the spawned process to /dev/null.
        """
        if not self.is_verifying:
            raise ValueError(
                "Verification not enabled by default; import db from lmfdb.verify to enable"
            )
        if parallel <= 0:
            raise ValueError(
                "Non-parallel runs not supported for whole database")
        lmfdb_root = os.path.abspath(
            os.path.join(os.path.dirname(os.path.realpath(__file__)), "..",
                         ".."))
        if logdir is None:
            logdir = os.path.join(lmfdb_root, "logs", "verification")
        if not os.path.exists(logdir):
            os.makedirs(logdir)
        types = None
        tabletypes = []
        for tablename in self.tablenames:
            table = self[tablename]
            verifier = table._verifier
            if verifier is not None:
                if types is None:
                    if speedtype == "all":
                        types = verifier.all_types()
                    else:
                        types = [verifier.speedtype(speedtype)]
                for typ in types:
                    if verifier.get_checks_count(typ) != 0:
                        tabletypes.append("%s.%s" % (tablename, typ.shortname))
        if len(tabletypes) == 0:
            # Shouldn't occur....
            raise ValueError("No verification tests defined!")
        parallel = min(parallel, len(tabletypes))
        cmd = os.path.abspath(
            os.path.join(os.path.abspath(__file__), "..", "verify",
                         "verify_tables.py"))
        cmd = [
            "sage", "-python", cmd,
            "-j%s" % int(parallel), logdir, "all", speedtype
        ]
        if debug:
            pipe = subprocess.Popen(cmd)
        else:
            DEVNULL = open(os.devnull, "wb")
            pipe = subprocess.Popen(cmd, stdout=DEVNULL, stderr=DEVNULL)
        if follow:
            from lmfdb.verify.follower import Follower

            try:
                Follower(logdir, tabletypes, follow, poll_interval).follow()
            finally:
                # kill the subprocess
                # From the man page, the following will terminate child processes
                pipe.send_signal(signal.SIGTERM)
                pipe.send_signal(signal.SIGTERM)
        else:
            return pipe