1# SPDX-License-Identifier: Apache-2.0 2# 3# Copyright (C) 2015, ARM Limited and contributors. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); you may 6# not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import json 19import os 20import re 21import logging 22import logging.config 23 24 25class LisaLogging(object): 26 27 @classmethod 28 def setup(self, filepath='logging.conf', level=logging.INFO): 29 """ 30 Initialize logging used for all the LISA modules. 31 32 :param filepath: the relative or absolute path of the logging configuration to use. 33 Relative path uses the LISA_HOME environment variable 34 has base folder. 35 :type filepath: str 36 37 :param level: the default log level to enable, INFO by default 38 :type level: logging.<level> or int in [0..50] 39 """ 40 41 # Load the specified logfile using an absolute path 42 basepath = os.path.dirname(__file__).replace('/libs/utils', '') 43 filepath = os.path.join(basepath, filepath) 44 if not os.path.exists(filepath): 45 raise ValueError('Logging configuration file not found in: {}'\ 46 .format(filepath)) 47 logging.config.fileConfig(filepath) 48 logging.getLogger().setLevel(level) 49 50 logging.info('Using LISA logging configuration:') 51 logging.info(' %s', filepath) 52 53class JsonConf(object): 54 """ 55 Class for parsing a JSON superset with comments. 56 57 Simply strips comments and then uses the standard JSON parser. 58 59 :param filename: Path to file to parse 60 :type filename: str 61 """ 62 63 def __init__(self, filename): 64 self.filename = filename 65 self.json = None 66 67 def load(self): 68 """ 69 Parse a JSON file 70 71 First remove comments and then use the json module package 72 Comments look like : 73 74 :: 75 76 // ... 77 78 or 79 80 :: 81 82 /* 83 ... 84 */ 85 86 """ 87 88 # Setup logging 89 self._log = logging.getLogger('JsonConf') 90 91 if not os.path.isfile(self.filename): 92 raise RuntimeError( 93 'Missing configuration file: {}'.format(self.filename) 94 ) 95 self._log.debug('loading JSON...') 96 97 with open(self.filename) as fh: 98 content = ''.join(fh.readlines()) 99 100 ## Looking for comments 101 match = JSON_COMMENTS_RE.search(content) 102 while match: 103 # single line comment 104 content = content[:match.start()] + content[match.end():] 105 match = JSON_COMMENTS_RE.search(content) 106 107 # Allow trailing commas in dicts an lists in JSON 108 # Note that this simple implementation will mangle things like: 109 # {"config": ", }"} 110 content = re.sub(r',[ \t\r\n]+}', '}', content) 111 content = re.sub(r',[ \t\r\n]+\]', ']', content) 112 113 # Return json file 114 self.json = json.loads(content, parse_int=int) 115 self._log.debug('Loaded JSON configuration:') 116 self._log.debug(' %s', self.json) 117 118 return self.json 119 120 def show(self): 121 """ 122 Pretty-print content of parsed JSON 123 """ 124 print json.dumps(self.json, indent=4) 125 126# Regular expression for comments 127JSON_COMMENTS_RE = re.compile( 128 r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?', 129 re.DOTALL | re.MULTILINE 130) 131 132 133