blob: 230eedc164f3dd7a8ead14c8ca2b2333ce267876 [file] [log] [blame]
Alex Klein2b236722019-06-19 15:44:26 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Validation helpers for simple input validation in the API."""
7
8from __future__ import print_function
9
10import os
11
12from chromite.lib import cros_build_lib
13from chromite.lib import cros_logging as logging
14
15from google.protobuf import message as protobuf_message
16
17
18def _value(field, message):
19 """Helper function to fetch the value of the field.
20
21 Args:
22 field (str): The field name. Can be nested via . separation.
23 message (Message): The protobuf message it is being fetched from.
24
25 Returns:
26 str|None|int|list|Message|bool - The value of the field.
27 """
28 value = message
29 for part in field.split('.'):
30 if not isinstance(value, protobuf_message.Message):
31 value = None
32 break
33
34 try:
35 value = getattr(value, part)
36 except AttributeError as e:
37 cros_build_lib.Die('Invalid field: %s', e.message)
38
39 return value
40
41#pylint: disable=docstring-misnamed-args
42def exists(*fields):
43 """Validate that the paths in |fields| exist.
44
45 Args:
46 fields (str): The fields being checked. Can be . separated nested
47 fields.
48 """
49 assert fields
50
51 def decorator(func):
52 def _exists(input_proto, *args, **kwargs):
53 for field in fields:
54 logging.debug('Validating %s exists.', field)
55
56 value = _value(field, input_proto)
57 if not value or not os.path.exists(value):
58 cros_build_lib.Die('%s path does not exist: %s' % (field, value))
59
60 return func(input_proto, *args, **kwargs)
61
62 return _exists
63
64 return decorator
65
66
67#pylint: disable=docstring-misnamed-args
68def require(*fields):
69 """Verify |fields| have all been set.
70
71 Args:
72 fields (str): The fields being checked. May be . separated nested
73 fields.
74 """
75 assert fields
76
77 def decorator(func):
78 def _require(input_proto, *args, **kwargs):
79 for field in fields:
80 logging.debug('Validating %s is set.', field)
81
82 value = _value(field, input_proto)
83 if not value:
84 cros_build_lib.Die('%s is required.', field)
85
86 return func(input_proto, *args, **kwargs)
87
88 return _require
89
90 return decorator