1 $ˆl–Ðz¾”Ji?u4 ^¸ËwÒ˜´oÈ „ N4ÿÇ¿Å99# (c) 2012-2014, Michael DeHaan # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . # Make coding more python3-ish from __future__ import (absolute_import, division, print_function) __metaclass__ = type import re import traceback from collections.abc import Sequence from ansible.errors.yaml_strings import ( YAML_COMMON_DICT_ERROR, YAML_COMMON_LEADING_TAB_ERROR, YAML_COMMON_PARTIALLY_QUOTED_LINE_ERROR, YAML_COMMON_UNBALANCED_QUOTES_ERROR, YAML_COMMON_UNQUOTED_COLON_ERROR, YAML_COMMON_UNQUOTED_VARIABLE_ERROR, YAML_POSITION_DETAILS, YAML_AND_SHORTHAND_ERROR, ) from ansible.module_utils._text import to_native, to_text class AnsibleError(Exception): ''' This is the base class for all errors raised from Ansible code, and can be instantiated with two optional parameters beyond the error message to control whether detailed information is displayed when the error occurred while parsing a data file of some kind. Usage: raise AnsibleError('some message here', obj=obj, show_content=True) Where "obj" is some subclass of ansible.parsing.yaml.objects.AnsibleBaseYAMLObject, which should be returned by the DataLoader() class. ''' def __init__(self, message="", obj=None, show_content=True, suppress_extended_error=False, orig_exc=None): super(AnsibleError, self).__init__(message) self._show_content = show_content self._suppress_extended_error = suppress_extended_error self._message = to_native(message) self.obj = obj self.orig_exc = orig_exc @property def message(self): # we import this here to prevent an import loop problem, # since the objects code also imports ansible.errors from ansible.parsing.yaml.objects import AnsibleBaseYAMLObject message = [self._message] if isinstance(self.obj, AnsibleBaseYAMLObject): extended_error = self._get_extended_error() if extended_error and not self._suppress_extended_error: message.append( '\n\n%s' % to_native(extended_error) ) elif self.orig_exc: message.append('. %s' % to_native(self.orig_exc)) return ''.join(message) @message.setter def message(self, val): self._message = val def __str__(self): return self.message def __repr__(self): return self.message def _get_error_lines_from_file(self, file_name, line_number): ''' Returns the line in the file which corresponds to the reported error location, as well as the line preceding it (if the error did not occur on the first line), to provide context to the error. ''' target_line = '' prev_line = '' with open(file_name, 'r') as f: lines = f.readlines() # In case of a YAML loading error, PyYAML will report the very last line # as the location of the error. Avoid an index error here in order to # return a helpful message. file_length = len(lines) if line_number >= file_length: line_number = file_length - 1 # If target_line contains only whitespace, move backwards until # actual code is found. If there are several empty lines after target_line, # the error lines w