blob: 5f259c165ad5d44cabbed912674efe1863d1da0f [file] [log] [blame]
# Copyright 2023 The LUCI Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
"""recipe_utils.py stores common utils to be shared between recipe_modules
Many recipes need common helper tasks such as validating parameters,
deleting files recursively without throwing exceptions, and other
miscellaneous tasks. Let's keep these utilities in one place so that
individual recipe_modules can do them consistently.
"""
from typing import Any, Mapping, Sequence, TypeVar
T = TypeVar('T')
def check_type(name: str, var: T, expect: Any) -> T:
"""check_types checks that a variable has the expected type"""
assert isinstance(name, str), f'name has bad type {type(name).__name__}'
if not isinstance(var, expect): # pragma: no cover
if isinstance(expect, tuple):
expect_type = ' or '.join('a ' + t.__name__ for t in expect)
else:
expect_type = 'a ' + expect.__name__
raise TypeError('%s is not %s: %r (%s)' %
(name, expect_type, var, type(var).__name__))
return var
def check_list_type(name: str, var: T, expect_inner: Any) -> T:
"""check_list_type checks that each element of a non-str sequence has the expected type"""
assert isinstance(name, str), f'name has bad type {type(name).__name__}'
if isinstance(var, (str, bytes)): # pragma: no cover
raise TypeError('%s must be a non-string sequence: %s (%r)' %
(name, type(var).__name__, var))
# Allow all non-string sequences, not just tuple and list, because proto
# object repeated fields use a special Sequence type.
check_type(name, var, Sequence)
for i, itm in enumerate(var):
check_type('%s[%d]' % (name, i), itm, expect_inner)
return var
def check_dict_type(name: str, var: T, expect_key: Any, expect_value: Any) -> T:
"""check_dict_type checks that each element of a dictionary has the expected type"""
assert isinstance(name, str), f'name has bad type {type(name).__name__}'
check_type(name, var, Mapping)
for key, value in var.items():
check_type('%s: key' % name, key, expect_key)
check_type('%s[%s]' % (name, key), value, expect_value)
return var