blob: 767f3a162d41690d01c001621a649212da108232 [file] [log] [blame]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module for Chrome OS Graphics results database."""
from __future__ import print_function
import datetime
import os
import re
import subprocess
import sys
import uuid
from google.protobuf import json_format
def error(*args, **kwargs):
"""Print an error message."""
print(*args, file=sys.stderr, **kwargs)
def generate_id():
"""Generates a random id.
Returns:
A string.
"""
return str(uuid.uuid4())
def get_cmd_output(cmd):
"""Read output from a command.
Args:
cmd: Command to run.
Returns:
A string with stdout.
"""
return subprocess.check_output(cmd).rstrip().decode('utf-8')
def is_json(filename):
"""Determines if a filename is a JSON file.
Args:
filename: The filnemae to consider.
Returns:
A boolean that is True if so.
"""
return re.search(r'\.json$', filename)
def output_pb(pb, filename):
"""Output protobuf as json, protobuf or to stdout.
Args:
pb: Protobuf to output>
filename: File to write to in either json or binary format.
If not specified, print to stdout.
"""
if filename:
if is_json(filename):
with open(filename, 'w') as f:
f.write(json_format.MessageToJson(pb))
f.write('\n')
else:
with open(filename, 'wb') as f:
f.write(pb.SerializeToString(deterministic=True))
else:
print(pb)
def parse_date(s):
"""Parse s as a date.
Args:
s: A string in one of the following formats:
now (current time)
STRING=FORMAT (strptime format)
YYYYMMDD-HHMMSS
UTCTIMESTAMP
YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]] (iso)
Python locale appropriate format (%c)
Returns:
A datetime or None if nothing can be parsed.
"""
# now
if s.lower() == 'now':
return datetime.datetime.now()
# STRING=FORMAT
m = re.match(r'(?P<date_string>.*)=(?P<format>.*)$', s)
if m:
return datetime.datetime.strptime(m.group(1), m.group(2))
# YYYYMMDD-HHMMSS
m = re.match(r'\d{8}-[0-2]\d{5}$', s)
if m:
return datetime.datetime.strptime(s, '%Y%m%d-%H%M%S')
# UTC timestamp: 1588891489
m = re.match(r'\d{1,0}$', s)
if m:
return datetime.datetime.utcfromtimestamp(int(s))
# isoformat
try:
return datetime.datetime.fromisoformat(s)
except ValueError:
pass
# Locale appropriate.
try:
return datetime.datetime.strptime(s, '%c')
except ValueError:
pass
def read_bios_keyval_file(file):
"""Read a bios log keyval file into a dictionary.
Args:
file: Filename to read.
Returns:
A dictionary.
"""
info = {}
if os.path.exists(file):
with open(file) as f:
for line in f.readlines():
line = line.rstrip()
m = re.search(r'^(\S+)\s+(?:[|=])\s+([^#]+)', line)
if m:
info[m.group(1)] = m.group(2).rstrip()
return info
def read_pb(pb, filename):
"""Reads a protobuf in either JSON or binary format.
Args:
pb: A protobuf Message to read into.
filename: The filename of the protobuf.
"""
if is_json(filename):
with open(filename) as f:
json_format.Parse(f.read(), pb)
else:
with open(filename, 'rb') as f:
pb.ParseFromString(f.read())
def strip_quotes(value):
"""Strip matched quotes or double quotes from a string.
Args:
value: The string to strip quotes from.
Returns:
A string.
"""
value = re.sub(r'^"(.*)"$', r'\1', value)
value = re.sub(r"^'(.*)'$", r'\1', value)
return value
def tryset(p, field, d, dict_key, conv=str):
"""Try and set a protobuf value from a dictionary.
Try and set value d[dict_key] into protobuf p's field if it exists,
converting the value with conv.
Args:
p: Protobuf to assign into.
field: Field of protobuf to assign.
d: Dictionary to read from.
dict_key: Key within dictionary.
conv: conversion function.
"""
if d.get(dict_key):
p.__setattr__(field, conv(d[dict_key]))