Repository: ansible/ansible-lint

Issue:
ansible-lint does not sanitize its output, printing unicode strings is not reliable.
# Issue Type
- Bug report
# How to get there:

Create a file
test.yml

```
- hosts: 127.0.0.1
  connection: local
  gather_facts: no
  vars:
     my_name: a_b_cö   
```

Notice the excessive whitespace of the last line.
# Desired Behaviour

I execute ansible lint and get a warning
# Actual Behaviour (Bug report only)

I get a traceback:
Traceback (most recent call last):
  File "./bin/ansible-lint", line 116, in <module>
    sys.exit(main(sys.argv[1:]))
  File "./bin/ansible-lint", line 106, in main
    print(formatter.format(match))
  File "/private/tmp/bla/bla2/lib/python2.7/site-packages/ansiblelint/formatters/**init**.py", line 9, in format
    match.line)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 19: ordinal not in range(128)



Discussion:
cc @saily


Resolving patch:
diff --git a/lib/ansiblelint/__init__.py b/lib/ansiblelint/__init__.py
--- a/lib/ansiblelint/__init__.py
+++ b/lib/ansiblelint/__init__.py
@@ -24,6 +24,7 @@
 import sys
 
 import ansiblelint.utils
+import codecs
 
 
 class AnsibleLintRule(object):
@@ -68,7 +69,7 @@ def matchtasks(self, file, text):
                     result = self.matchtask(file, task)
                     if result:
                         message = None
-                        if isinstance(result, str):
+                        if isinstance(result, basestring):
                             message = result
                         taskstr = "Task/Handler: " + ansiblelint.utils.task_to_str(task)
                         matches.append(Match(task[ansiblelint.utils.LINE_NUMBER_KEY], taskstr,
@@ -116,7 +117,7 @@ def run(self, playbookfile, tags=set(), skip_list=set()):
         matches = list()
 
         try:
-            with open(playbookfile['path'], 'Ur') as f:
+            with codecs.open(playbookfile['path'], mode='rb', encoding='utf-8') as f:
                 text = f.read()
         except IOError, e:
             print("WARNING: Couldn't open %s - %s" %
@@ -166,7 +167,7 @@ def __init__(self, linenumber, line, filename, rule, message=None):
         self.message = message or rule.shortdesc
 
     def __repr__(self):
-        formatstr = "[{0}] ({1}) matched {2}:{3} {4}"
+        formatstr = u"[{0}] ({1}) matched {2}:{3} {4}"
         return formatstr.format(self.rule.id, self.message,
                                 self.filename, self.linenumber, self.line)
 


Test patch:
diff --git a/test/TestRunner.py b/test/TestRunner.py
--- a/test/TestRunner.py
+++ b/test/TestRunner.py
@@ -23,6 +23,7 @@
 
 import ansiblelint
 from ansiblelint import RulesCollection
+from ansiblelint.formatters import Formatter
 
 
 class TestRule(unittest.TestCase):
@@ -39,13 +40,20 @@ def test_runner_count(self):
     def test_unicode_runner_count(self):
         filename = 'test/unicode.yml'
         runner = ansiblelint.Runner(self.rules, {filename}, [], [], [])
-        assert (len(runner.run()) == 0)
+        assert (len(runner.run()) == 1)
+
+    def test_unicode_formatting(self):
+        filename = 'test/unicode.yml'
+        runner = ansiblelint.Runner(self.rules, {filename}, [], [], [])
+        matches = runner.run()
+        formatter = Formatter()
+        formatter.format(matches[0])
 
     def test_runner_excludes_paths(self):
         files = {'test/unicode.yml', 'examples/lots_of_warnings.yml'}
         excludes = ['examples/lots_of_warnings.yml']
         runner = ansiblelint.Runner(self.rules, files, [], [], excludes)
-        assert (len(runner.run()) == 0)
+        assert (len(runner.run()) == 1)
 
     def test_runner_block_count(self):
         files = {'test/block.yml'}
diff --git a/test/unicode.yml b/test/unicode.yml
--- a/test/unicode.yml
+++ b/test/unicode.yml
@@ -1,6 +1,8 @@
 ---
 - hosts: localhost
   connection: local
+  vars:
+    unicode_var: a_b_cö   
 
   tasks:
   - name: bonjour, ça va?