diff --git a/v2/ansible/errors/__init__.py b/v2/ansible/errors/__init__.py index 7effe41df7c..bdd6e524489 100644 --- a/v2/ansible/errors/__init__.py +++ b/v2/ansible/errors/__init__.py @@ -92,7 +92,7 @@ class AnsibleError(Exception): error_message = '' try: - (src_file, line_number, col_number) = self._obj.get_position_info() + (src_file, line_number, col_number) = self._obj.ansible_pos error_message += YAML_POSITION_DETAILS % (src_file, line_number, col_number) if src_file not in ('', '') and self._show_content: (target_line, prev_line) = self._get_error_lines_from_file(src_file, line_number - 1) diff --git a/v2/ansible/parsing/__init__.py b/v2/ansible/parsing/__init__.py index f8a3e967465..75465bdfa3e 100644 --- a/v2/ansible/parsing/__init__.py +++ b/v2/ansible/parsing/__init__.py @@ -146,7 +146,7 @@ class DataLoader(): err_obj = None if hasattr(yaml_exc, 'problem_mark'): err_obj = AnsibleBaseYAMLObject() - err_obj.set_position_info(file_name, yaml_exc.problem_mark.line + 1, yaml_exc.problem_mark.column + 1) + err_obj.ansible_pos = (file_name, yaml_exc.problem_mark.line + 1, yaml_exc.problem_mark.column + 1) raise AnsibleParserError(YAML_SYNTAX_ERROR, obj=err_obj, show_content=show_content) diff --git a/v2/ansible/parsing/yaml/constructor.py b/v2/ansible/parsing/yaml/constructor.py index b607f46b055..0043b8a2f04 100644 --- a/v2/ansible/parsing/yaml/constructor.py +++ b/v2/ansible/parsing/yaml/constructor.py @@ -33,23 +33,20 @@ class AnsibleConstructor(Constructor): yield data value = self.construct_mapping(node) data.update(value) - data._line_number = value._line_number - data._column_number = value._column_number - data._data_source = value._data_source + data.ansible_pos = value.ansible_pos def construct_mapping(self, node, deep=False): ret = AnsibleMapping(super(Constructor, self).construct_mapping(node, deep)) - ret._line_number = node.__line__ - ret._column_number = node.__column__ # in some cases, we may have pre-read the data and then # passed it to the load() call for YAML, in which case we # want to override the default datasource (which would be # '') to the actual filename we read in if self._ansible_file_name: - ret._data_source = self._ansible_file_name + data_source = self._ansible_file_name else: - ret._data_source = node.__datasource__ + data_source = node.__datasource__ + ret.ansible_pos = (data_source, node.__line__, node.__column__) return ret @@ -58,16 +55,15 @@ class AnsibleConstructor(Constructor): # to always return unicode objects value = self.construct_scalar(node) value = to_unicode(value) - data = AnsibleUnicode(self.construct_scalar(node)) + ret = AnsibleUnicode(self.construct_scalar(node)) - data._line_number = node.__line__ - data._column_number = node.__column__ if self._ansible_file_name: - data._data_source = self._ansible_file_name + data_source = self._ansible_file_name else: - data._data_source = node.__datasource__ + data_source = node.__datasource__ + ret.ansible_pos = (data_source, node.__line__, node.__column__) - return data + return ret AnsibleConstructor.add_constructor( u'tag:yaml.org,2002:map', diff --git a/v2/ansible/parsing/yaml/objects.py b/v2/ansible/parsing/yaml/objects.py index 69f8c0968d1..15850dd4f87 100644 --- a/v2/ansible/parsing/yaml/objects.py +++ b/v2/ansible/parsing/yaml/objects.py @@ -29,22 +29,19 @@ class AnsibleBaseYAMLObject: _line_number = 0 _column_number = 0 - def get_position_info(self): + def _get_ansible_position(self): return (self._data_source, self._line_number, self._column_number) - def set_position_info(self, src, line, col): + def _set_ansible_position(self, obj): + try: + (src, line, col) = obj + except (TypeError, ValueError): + raise AssertionError('ansible_pos can only be set with a tuple/list of three values: source, line number, column number') self._data_source = src self._line_number = line self._column_number = col - def copy_position_info(self, obj): - ''' copies the position info from another object ''' - assert isinstance(obj, AnsibleBaseYAMLObject) - - (src, line, col) = obj.get_position_info() - self._data_source = src - self._line_number = line - self._column_number = col + ansible_pos = property(_get_ansible_position, _set_ansible_position) class AnsibleMapping(AnsibleBaseYAMLObject, dict): ''' sub class for dictionaries ''' diff --git a/v2/ansible/playbook/helpers.py b/v2/ansible/playbook/helpers.py index 0e147205578..4277e201b7b 100644 --- a/v2/ansible/playbook/helpers.py +++ b/v2/ansible/playbook/helpers.py @@ -74,7 +74,7 @@ def load_list_of_tasks(ds, block=None, role=None, task_include=None, use_handler #if 'include' in task: # cur_basedir = None # if isinstance(task, AnsibleBaseYAMLObject) and loader: - # pos_info = task.get_position_info() + # pos_info = task.ansible_pos # new_basedir = os.path.dirname(pos_info[0]) # cur_basedir = loader.get_basedir() # loader.set_basedir(new_basedir) diff --git a/v2/ansible/playbook/playbook_include.py b/v2/ansible/playbook/playbook_include.py index f7eae230f7c..2e4964fce96 100644 --- a/v2/ansible/playbook/playbook_include.py +++ b/v2/ansible/playbook/playbook_include.py @@ -80,7 +80,7 @@ class PlaybookInclude(Base): # items reduced to a standard structure new_ds = AnsibleMapping() if isinstance(ds, AnsibleBaseYAMLObject): - new_ds.copy_position_info(ds) + new_ds.ansible_pos = ds.ansible_pos for (k,v) in ds.iteritems(): if k == 'include': diff --git a/v2/ansible/playbook/role/definition.py b/v2/ansible/playbook/role/definition.py index fb96a0e55f9..0cb1e45760d 100644 --- a/v2/ansible/playbook/role/definition.py +++ b/v2/ansible/playbook/role/definition.py @@ -66,7 +66,7 @@ class RoleDefinition(Base, Become, Conditional, Taggable): # can preserve file:line:column information if it exists new_ds = AnsibleMapping() if isinstance(ds, AnsibleBaseYAMLObject): - new_ds.copy_position_info(ds) + new_ds.ansible_pos = ds.ansible_pos # first we pull the role name out of the data structure, # and then use that to determine the role path (which may diff --git a/v2/ansible/playbook/task.py b/v2/ansible/playbook/task.py index 0f5e7674866..b36c24167a4 100644 --- a/v2/ansible/playbook/task.py +++ b/v2/ansible/playbook/task.py @@ -159,7 +159,7 @@ class Task(Base, Conditional, Taggable, Become): # attributes of the task class new_ds = AnsibleMapping() if isinstance(ds, AnsibleBaseYAMLObject): - new_ds.copy_position_info(ds) + new_ds.ansible_pos = ds.ansible_pos # use the args parsing class to determine the action, args, # and the delegate_to value from the various possible forms diff --git a/v2/test/errors/test_errors.py b/v2/test/errors/test_errors.py index 3e8e0dd7bac..3993ea5061b 100644 --- a/v2/test/errors/test_errors.py +++ b/v2/test/errors/test_errors.py @@ -44,9 +44,7 @@ class TestErrors(unittest.TestCase): @patch.object(AnsibleError, '_get_error_lines_from_file') def test_error_with_object(self, mock_method): - self.obj._data_source = 'foo.yml' - self.obj._line_number = 1 - self.obj._column_number = 1 + self.obj.ansible_pos = ('foo.yml', 1, 1) mock_method.return_value = ('this is line 1\n', '') e = AnsibleError(self.message, self.obj) @@ -59,16 +57,12 @@ class TestErrors(unittest.TestCase): with patch('{0}.open'.format(BUILTINS), m): # this line will be found in the file - self.obj._data_source = 'foo.yml' - self.obj._line_number = 1 - self.obj._column_number = 1 + self.obj.ansible_pos = ('foo.yml', 1, 1) e = AnsibleError(self.message, self.obj) self.assertEqual(e.message, "ERROR! This is the error message\n\nThe error appears to have been in 'foo.yml': line 1, column 1, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\nthis is line 1\n^ here\n") # this line will not be found, as it is out of the index range - self.obj._data_source = 'foo.yml' - self.obj._line_number = 2 - self.obj._column_number = 1 + self.obj.ansible_pos = ('foo.yml', 2, 1) e = AnsibleError(self.message, self.obj) self.assertEqual(e.message, "ERROR! This is the error message\n\nThe error appears to have been in 'foo.yml': line 2, column 1, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\n(specified line no longer in file, maybe it changed?)") - + diff --git a/v2/test/parsing/yaml/test_loader.py b/v2/test/parsing/yaml/test_loader.py index aba103d37f6..f9144fb2925 100644 --- a/v2/test/parsing/yaml/test_loader.py +++ b/v2/test/parsing/yaml/test_loader.py @@ -54,9 +54,7 @@ class TestAnsibleLoaderBasic(unittest.TestCase): self.assertEqual(data, u'Ansible') self.assertIsInstance(data, unicode) - self.assertEqual(data._line_number, 2) - self.assertEqual(data._column_number, 17) - self.assertEqual(data._data_source, 'myfile.yml') + self.assertEqual(data.ansible_pos, ('myfile.yml', 2, 17)) def test_parse_utf8_string(self): stream = StringIO(""" @@ -67,9 +65,7 @@ class TestAnsibleLoaderBasic(unittest.TestCase): self.assertEqual(data, u'Cafè Eñyei') self.assertIsInstance(data, unicode) - self.assertEqual(data._line_number, 2) - self.assertEqual(data._column_number, 17) - self.assertEqual(data._data_source, 'myfile.yml') + self.assertEqual(data.ansible_pos, ('myfile.yml', 2, 17)) def test_parse_dict(self): stream = StringIO(""" @@ -84,17 +80,10 @@ class TestAnsibleLoaderBasic(unittest.TestCase): self.assertIsInstance(data.values()[0], unicode) # Beginning of the first key - self.assertEqual(data._line_number, 2) - self.assertEqual(data._column_number, 17) - self.assertEqual(data._data_source, 'myfile.yml') + self.assertEqual(data.ansible_pos, ('myfile.yml', 2, 17)) - self.assertEqual(data[u'webster']._line_number, 2) - self.assertEqual(data[u'webster']._column_number, 26) - self.assertEqual(data[u'webster']._data_source, 'myfile.yml') - - self.assertEqual(data[u'oed']._line_number, 3) - self.assertEqual(data[u'oed']._column_number, 22) - self.assertEqual(data[u'oed']._data_source, 'myfile.yml') + self.assertEqual(data[u'webster'].ansible_pos, ('myfile.yml', 2, 26)) + self.assertEqual(data[u'oed'].ansible_pos, ('myfile.yml', 3, 22)) def test_parse_list(self): stream = StringIO(""" @@ -191,109 +180,51 @@ class TestAnsibleLoaderPlay(unittest.TestCase): def check_vars(self): # Numbers don't have line/col information yet - #self.assertEqual(self.data[0][u'vars'][u'number']._line_number, 4) - #self.assertEqual(self.data[0][u'vars'][u'number']._column_number, 21) - #self.assertEqual(self.data[0][u'vars'][u'number']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'vars'][u'string']._line_number, 5) - self.assertEqual(self.data[0][u'vars'][u'string']._column_number, 29) - self.assertEqual(self.data[0][u'vars'][u'string']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'vars'][u'utf8_string']._line_number, 6) - self.assertEqual(self.data[0][u'vars'][u'utf8_string']._column_number, 34) - self.assertEqual(self.data[0][u'vars'][u'utf8_string']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'vars'][u'dictionary']._line_number, 8) - self.assertEqual(self.data[0][u'vars'][u'dictionary']._column_number, 23) - self.assertEqual(self.data[0][u'vars'][u'dictionary']._data_source, self.play_filename) + #self.assertEqual(self.data[0][u'vars'][u'number'].ansible_pos, (self.play_filename, 4, 21)) - self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'webster']._line_number, 8) - self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'webster']._column_number, 32) - self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'webster']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'oed']._line_number, 9) - self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'oed']._column_number, 28) - self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'oed']._data_source, self.play_filename) + self.assertEqual(self.data[0][u'vars'][u'string'].ansible_pos, (self.play_filename, 5, 29)) + self.assertEqual(self.data[0][u'vars'][u'utf8_string'].ansible_pos, (self.play_filename, 6, 34)) + self.assertEqual(self.data[0][u'vars'][u'dictionary'].ansible_pos, (self.play_filename, 8, 23)) + self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'webster'].ansible_pos, (self.play_filename, 8, 32)) + self.assertEqual(self.data[0][u'vars'][u'dictionary'][u'oed'].ansible_pos, (self.play_filename, 9, 28)) # Lists don't yet have line/col information - #self.assertEqual(self.data[0][u'vars'][u'list']._line_number, 10) - #self.assertEqual(self.data[0][u'vars'][u'list']._column_number, 21) - #self.assertEqual(self.data[0][u'vars'][u'list']._data_source, self.play_filename) + #self.assertEqual(self.data[0][u'vars'][u'list'].ansible_pos, (self.play_filename, 10, 21)) def check_tasks(self): # # First Task # - self.assertEqual(self.data[0][u'tasks'][0]._line_number, 16) - self.assertEqual(self.data[0][u'tasks'][0]._column_number, 23) - self.assertEqual(self.data[0][u'tasks'][0]._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][0][u'name']._line_number, 16) - self.assertEqual(self.data[0][u'tasks'][0][u'name']._column_number, 29) - self.assertEqual(self.data[0][u'tasks'][0][u'name']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][0][u'ping']._line_number, 18) - self.assertEqual(self.data[0][u'tasks'][0][u'ping']._column_number, 25) - self.assertEqual(self.data[0][u'tasks'][0][u'ping']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][0][u'ping'][u'data']._line_number, 18) - self.assertEqual(self.data[0][u'tasks'][0][u'ping'][u'data']._column_number, 31) - self.assertEqual(self.data[0][u'tasks'][0][u'ping'][u'data']._data_source, self.play_filename) + self.assertEqual(self.data[0][u'tasks'][0].ansible_pos, (self.play_filename, 16, 23)) + self.assertEqual(self.data[0][u'tasks'][0][u'name'].ansible_pos, (self.play_filename, 16, 29)) + self.assertEqual(self.data[0][u'tasks'][0][u'ping'].ansible_pos, (self.play_filename, 18, 25)) + self.assertEqual(self.data[0][u'tasks'][0][u'ping'][u'data'].ansible_pos, (self.play_filename, 18, 31)) # # Second Task # - self.assertEqual(self.data[0][u'tasks'][1]._line_number, 20) - self.assertEqual(self.data[0][u'tasks'][1]._column_number, 23) - self.assertEqual(self.data[0][u'tasks'][1]._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][1][u'name']._line_number, 20) - self.assertEqual(self.data[0][u'tasks'][1][u'name']._column_number, 29) - self.assertEqual(self.data[0][u'tasks'][1][u'name']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][1][u'ping']._line_number, 22) - self.assertEqual(self.data[0][u'tasks'][1][u'ping']._column_number, 25) - self.assertEqual(self.data[0][u'tasks'][1][u'ping']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][1][u'ping'][u'data']._line_number, 22) - self.assertEqual(self.data[0][u'tasks'][1][u'ping'][u'data']._column_number, 31) - self.assertEqual(self.data[0][u'tasks'][1][u'ping'][u'data']._data_source, self.play_filename) + self.assertEqual(self.data[0][u'tasks'][1].ansible_pos, (self.play_filename, 20, 23)) + self.assertEqual(self.data[0][u'tasks'][1][u'name'].ansible_pos, (self.play_filename, 20, 29)) + self.assertEqual(self.data[0][u'tasks'][1][u'ping'].ansible_pos, (self.play_filename, 22, 25)) + self.assertEqual(self.data[0][u'tasks'][1][u'ping'][u'data'].ansible_pos, (self.play_filename, 22, 31)) # # Third Task # - self.assertEqual(self.data[0][u'tasks'][2]._line_number, 24) - self.assertEqual(self.data[0][u'tasks'][2]._column_number, 23) - self.assertEqual(self.data[0][u'tasks'][2]._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][2][u'name']._line_number, 24) - self.assertEqual(self.data[0][u'tasks'][2][u'name']._column_number, 29) - self.assertEqual(self.data[0][u'tasks'][2][u'name']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'tasks'][2][u'command']._line_number, 25) - self.assertEqual(self.data[0][u'tasks'][2][u'command']._column_number, 32) - self.assertEqual(self.data[0][u'tasks'][2][u'command']._data_source, self.play_filename) + self.assertEqual(self.data[0][u'tasks'][2].ansible_pos, (self.play_filename, 24, 23)) + self.assertEqual(self.data[0][u'tasks'][2][u'name'].ansible_pos, (self.play_filename, 24, 29)) + self.assertEqual(self.data[0][u'tasks'][2][u'command'].ansible_pos, (self.play_filename, 25, 32)) def test_line_numbers(self): # Check the line/column numbers are correct - # Note: Remember, currently dicts begin at the start of their first entry's value - self.assertEqual(self.data[0]._line_number, 2) - self.assertEqual(self.data[0]._column_number, 19) - self.assertEqual(self.data[0]._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'hosts']._line_number, 2) - self.assertEqual(self.data[0][u'hosts']._column_number, 26) - self.assertEqual(self.data[0][u'hosts']._data_source, self.play_filename) - - self.assertEqual(self.data[0][u'vars']._line_number, 4) - self.assertEqual(self.data[0][u'vars']._column_number, 21) - self.assertEqual(self.data[0][u'vars']._data_source, self.play_filename) + # Note: Remember, currently dicts begin at the start of their first entry + self.assertEqual(self.data[0].ansible_pos, (self.play_filename, 2, 19)) + self.assertEqual(self.data[0][u'hosts'].ansible_pos, (self.play_filename, 2, 26)) + self.assertEqual(self.data[0][u'vars'].ansible_pos, (self.play_filename, 4, 21)) self.check_vars() # Lists don't yet have line/col info - #self.assertEqual(self.data[0][u'tasks']._line_number, 17) - #self.assertEqual(self.data[0][u'tasks']._column_number, 28) - #self.assertEqual(self.data[0][u'tasks']._data_source, self.play_filename) + #self.assertEqual(self.data[0][u'tasks'].ansible_pos, (self.play_filename, 17, 28)) self.check_tasks()