diff --git a/lib/ansible/parsing/splitter.py b/lib/ansible/parsing/splitter.py index a1dc051d24..f2162814da 100644 --- a/lib/ansible/parsing/splitter.py +++ b/lib/ansible/parsing/splitter.py @@ -264,7 +264,7 @@ def split_args(args): return params def is_quoted(data): - return len(data) > 0 and (data[0] == '"' and data[-1] == '"' or data[0] == "'" and data[-1] == "'") + return len(data) > 1 and data[0] == data[-1] and data[0] in ('"', "'") and data[-2] != '\\' def unquote(data): ''' removes first and last quotes from a string, if the string starts and ends with the same quotes ''' diff --git a/test/units/parsing/test_unquote.py b/test/units/parsing/test_unquote.py new file mode 100644 index 0000000000..afb11d4e23 --- /dev/null +++ b/test/units/parsing/test_unquote.py @@ -0,0 +1,58 @@ +# coding: utf-8 +# (c) 2015, Toshio Kuratomi +# +# 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 + +from nose import tools +from ansible.compat.tests import unittest + +from ansible.parsing.splitter import unquote + + +# Tests using nose's test generators cannot use unittest base class. +# http://nose.readthedocs.org/en/latest/writing_tests.html#test-generators +class TestUnquote: + UNQUOTE_DATA = ( + (u'1', u'1'), + (u'\'1\'', u'1'), + (u'"1"', u'1'), + (u'"1 \'2\'"', u'1 \'2\''), + (u'\'1 "2"\'', u'1 "2"'), + (u'\'1 \'2\'\'', u'1 \'2\''), + (u'"1\\"', u'"1\\"'), + (u'\'1\\\'', u'\'1\\\''), + (u'"1 \\"2\\" 3"', u'1 \\"2\\" 3'), + (u'\'1 \\\'2\\\' 3\'', u'1 \\\'2\\\' 3'), + (u'"', u'"'), + (u'\'', u'\''), + # Not entirely sure these are good but they match the current + # behaviour + (u'"1""2"', u'1""2'), + (u'\'1\'\'2\'', u'1\'\'2'), + (u'"1" 2 "3"', u'1" 2 "3'), + (u'"1"\'2\'"3"', u'1"\'2\'"3'), + ) + + def check_unquote(self, quoted, expected): + tools.eq_(unquote(quoted), expected) + + def test_unquote(self): + for datapoint in self.UNQUOTE_DATA: + yield self.check_unquote, datapoint[0], datapoint[1]