211c215c654c363993a9d480cbda679de0bbd7e9 hiram Fri May 1 13:59:15 2026 -0700 eliminating stderr information to avoid cron job noise refs #31811 diff --git src/hg/utils/otto/userRequests/ottoRequest.py src/hg/utils/otto/userRequests/ottoRequest.py index ebfb5dc8b68..75141e61783 100755 --- src/hg/utils/otto/userRequests/ottoRequest.py +++ src/hg/utils/otto/userRequests/ottoRequest.py @@ -1,27 +1,31 @@ #!/usr/bin/env python3 """ottoRequest.py - check ottoRequest table for pending requests and send email notification for each one found. Intended to run from cron. Reads the notification email address and table name from an hg.conf file. Uses hgsql for database access. Usage: ottoRequest.py [-c /path/to/hg.conf] Options: -c, --conf Path to hg.conf [default: /usr/local/apache/cgi-bin/hg.conf] + +cron entry in the otto user: +1,8,15,22,29,36,43,50,57 * * * * /hive/data/outside/otto/liftRequest/ottoRequest.py + """ import argparse import fcntl import os import re import subprocess import sys NOTIFY_FROM = 'genome-www@soe.ucsc.edu' BCC_BY_TYPE = { 'liftOver': 'chain-file-request-group@ucsc.edu', 'assembly': 'genark-request-group@ucsc.edu', } @@ -101,54 +105,54 @@ out.append('\0') else: out.append(s[i:i+2]) i += 2 else: out.append(s[i]) i += 1 return ''.join(out) def hgsqlQuery(db, sql): """Run a SQL query via hgsql and return rows as list of dicts. hgsql -B emits tabs/newlines/backslashes inside field values as literal \\t / \\n / \\\\ so each row stays on one line undo that on each field before returning.""" - cmd = ['hgsql', db, '-N', '-B', '-e', sql] + cmd = ['/cluster/bin/x86_64/hgsql', db, '-N', '-B', '-e', sql] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: sys.exit(f"hgsql error: {result.stderr.strip()}") rows = [] if not result.stdout.strip(): return rows for line in result.stdout.strip().split('\n'): fields = [unescapeMysql(f) for f in line.split('\t')] rows.append({ 'id': fields[0], 'requestType': fields[1], 'fromDb': fields[2], 'toDb': fields[3], 'email': fields[4], 'comment': fields[5], 'requestTime': fields[6], }) return rows def hgsqlUpdate(db, sql): """Run a SQL update/insert statement via hgsql.""" - cmd = ['hgsql', db, '-N', '-B', '-e', sql] + cmd = ['/cluster/bin/x86_64/hgsql', db, '-N', '-B', '-e', sql] result = subprocess.run(cmd, capture_output=True, text=True) if result.returncode != 0: print(f"hgsql update error: {result.stderr.strip()}", file=sys.stderr) return False return True def parseAssemblyComment(comment): """Assembly requests pack fields into the ottoRequest.comment column via hubApi/findGenome.c:apiAssemblyRequest: name: '<name>'[; betterName: '<bn>'][; comment: '<user comment>'] The user comment may itself contain newlines and apostrophes, so the inner quote pair is matched greedily up to the trailing closing quote. re.DOTALL lets '.' span newlines. Return (name, betterName, userComment)."""