• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# Copyright 2020 The gRPC Authors
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Utility functions for build file generation scripts."""
16
17import os
18import sys
19import types
20import importlib.util
21from typing import Any, Union, Mapping, List
22
23
24def import_python_module(path: str) -> types.ModuleType:
25    """Imports the Python file at the given path, returns a module object."""
26    module_name = os.path.basename(path).replace('.py', '')
27    spec = importlib.util.spec_from_file_location(module_name, path)
28    module = importlib.util.module_from_spec(spec)
29    sys.modules[module_name] = module
30    spec.loader.exec_module(module)
31    return module
32
33
34class Bunch(dict):
35    """Allows dot-accessible dictionaries."""
36
37    def __init__(self, d: Mapping):
38        dict.__init__(self, d)
39        self.__dict__.update(d)
40
41
42def to_bunch(var: Any) -> Any:
43    """Converts any kind of variable to a Bunch."""
44    if isinstance(var, list):
45        return [to_bunch(i) for i in var]
46    if isinstance(var, dict):
47        ret = {}
48        for k, v in var.items():
49            if isinstance(v, (list, dict)):
50                v = to_bunch(v)
51            ret[k] = v
52        return Bunch(ret)
53    else:
54        return var
55
56
57def merge_json(dst: Union[Mapping, List], add: Union[Mapping, List]) -> None:
58    """Merges JSON objects recursively."""
59    if isinstance(dst, dict) and isinstance(add, dict):
60        for k, v in add.items():
61            if k in dst:
62                if k.startswith('#'):
63                    continue
64                merge_json(dst[k], v)
65            else:
66                dst[k] = v
67    elif isinstance(dst, list) and isinstance(add, list):
68        dst.extend(add)
69    else:
70        raise TypeError(
71            'Tried to merge incompatible objects %s %s\n\n%r\n\n%r' %
72            (type(dst).__name__, type(add).__name__, dst, add))
73