| # SPDX-License-Identifier: Apache-2.0 |
| # |
| # Copyright (C) 2015, ARM Limited and contributors. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| # not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| import json |
| import os |
| import re |
| import logging |
| import logging.config |
| |
| |
| class LisaLogging(object): |
| |
| @classmethod |
| def setup(self, filepath='logging.conf', level=logging.INFO): |
| """ |
| Initialize logging used for all the LISA modules. |
| |
| :param filepath: the relative or absolute path of the logging configuration to use. |
| Relative path uses the LISA_HOME environment variable |
| has base folder. |
| :type filepath: str |
| |
| :param level: the default log level to enable, INFO by default |
| :type level: logging.<level> or int in [0..50] |
| """ |
| |
| # Load the specified logfile using an absolute path |
| basepath = os.path.dirname(__file__).replace('/libs/utils', '') |
| filepath = os.path.join(basepath, filepath) |
| if not os.path.exists(filepath): |
| raise ValueError('Logging configuration file not found in: {}'\ |
| .format(filepath)) |
| logging.config.fileConfig(filepath) |
| logging.getLogger().setLevel(level) |
| |
| logging.info('Using LISA logging configuration:') |
| logging.info(' %s', filepath) |
| |
| class JsonConf(object): |
| """ |
| Class for parsing a JSON superset with comments. |
| |
| Simply strips comments and then uses the standard JSON parser. |
| |
| :param filename: Path to file to parse |
| :type filename: str |
| """ |
| |
| def __init__(self, filename): |
| self.filename = filename |
| self.json = None |
| |
| def load(self): |
| """ |
| Parse a JSON file |
| |
| First remove comments and then use the json module package |
| Comments look like : |
| |
| :: |
| |
| // ... |
| |
| or |
| |
| :: |
| |
| /* |
| ... |
| */ |
| |
| """ |
| |
| # Setup logging |
| self._log = logging.getLogger('JsonConf') |
| |
| if not os.path.isfile(self.filename): |
| raise RuntimeError( |
| 'Missing configuration file: {}'.format(self.filename) |
| ) |
| self._log.debug('loading JSON...') |
| |
| with open(self.filename) as fh: |
| content = ''.join(fh.readlines()) |
| |
| ## Looking for comments |
| match = JSON_COMMENTS_RE.search(content) |
| while match: |
| # single line comment |
| content = content[:match.start()] + content[match.end():] |
| match = JSON_COMMENTS_RE.search(content) |
| |
| # Allow trailing commas in dicts an lists in JSON |
| # Note that this simple implementation will mangle things like: |
| # {"config": ", }"} |
| content = re.sub(r',[ \t\r\n]+}', '}', content) |
| content = re.sub(r',[ \t\r\n]+\]', ']', content) |
| |
| # Return json file |
| self.json = json.loads(content, parse_int=int) |
| self._log.debug('Loaded JSON configuration:') |
| self._log.debug(' %s', self.json) |
| |
| return self.json |
| |
| def show(self): |
| """ |
| Pretty-print content of parsed JSON |
| """ |
| print json.dumps(self.json, indent=4) |
| |
| # Regular expression for comments |
| JSON_COMMENTS_RE = re.compile( |
| r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?', |
| re.DOTALL | re.MULTILINE |
| ) |
| |
| |