• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- coding: utf-8 -*-
2# Copyright 2015 Google Inc. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Tests for yapf.__init__.main."""
16
17from contextlib import contextmanager
18import sys
19import unittest
20import yapf
21
22from yapf.yapflib import py3compat
23
24
25class IO(object):
26  """IO is a thin wrapper around StringIO.
27
28  This is strictly to wrap the Python 3 StringIO object so that it can supply a
29  "buffer" attribute.
30  """
31
32  class Buffer(object):
33
34    def __init__(self):
35      self.string_io = py3compat.StringIO()
36
37    def write(self, s):
38      if py3compat.PY3 and isinstance(s, bytes):
39        s = str(s, 'utf-8')
40      self.string_io.write(s)
41
42    def getvalue(self):
43      return self.string_io.getvalue()
44
45  def __init__(self):
46    self.buffer = self.Buffer()
47
48  def write(self, s):
49    self.buffer.write(s)
50
51  def getvalue(self):
52    return self.buffer.getvalue()
53
54
55@contextmanager
56def captured_output():
57  new_out, new_err = IO(), IO()
58  old_out, old_err = sys.stdout, sys.stderr
59  try:
60    sys.stdout, sys.stderr = new_out, new_err
61    yield sys.stdout, sys.stderr
62  finally:
63    sys.stdout, sys.stderr = old_out, old_err
64
65
66@contextmanager
67def patched_input(code):
68  """Monkey patch code as though it were coming from stdin."""
69
70  def lines():
71    for line in code.splitlines():
72      yield line
73    raise EOFError()
74
75  def patch_raw_input(lines=lines()):
76    return next(lines)
77
78  try:
79    orig_raw_import = yapf.py3compat.raw_input
80    yapf.py3compat.raw_input = patch_raw_input
81    yield
82  finally:
83    yapf.py3compat.raw_input = orig_raw_import
84
85
86class RunMainTest(unittest.TestCase):
87
88  def testShouldHandleYapfError(self):
89    """run_main should handle YapfError and sys.exit(1)."""
90    expected_message = 'yapf: Input filenames did not match any python files\n'
91    sys.argv = ['yapf', 'foo.c']
92    with captured_output() as (out, err):
93      with self.assertRaises(SystemExit):
94        yapf.run_main()
95      self.assertEqual(out.getvalue(), '')
96      self.assertEqual(err.getvalue(), expected_message)
97
98
99class MainTest(unittest.TestCase):
100
101  def testNoPythonFilesMatched(self):
102    with self.assertRaisesRegexp(yapf.errors.YapfError,
103                                 'did not match any python files'):
104      yapf.main(['yapf', 'foo.c'])
105
106  def testEchoInput(self):
107    code = 'a = 1\nb = 2\n'
108    with patched_input(code):
109      with captured_output() as (out, _):
110        ret = yapf.main([])
111        self.assertEqual(ret, 0)
112        self.assertEqual(out.getvalue(), code)
113
114  def testEchoInputWithStyle(self):
115    code = 'def f(a = 1):\n    return 2*a\n'
116    chromium_code = 'def f(a=1):\n  return 2 * a\n'
117    with patched_input(code):
118      with captured_output() as (out, _):
119        ret = yapf.main(['-', '--style=chromium'])
120        self.assertEqual(ret, 0)
121        self.assertEqual(out.getvalue(), chromium_code)
122
123  def testEchoBadInput(self):
124    bad_syntax = '  a = 1\n'
125    with patched_input(bad_syntax):
126      with captured_output() as (_, _):
127        with self.assertRaisesRegexp(SyntaxError, 'unexpected indent'):
128          yapf.main([])
129
130  def testHelp(self):
131    with captured_output() as (out, _):
132      ret = yapf.main(['-', '--style-help', '--style=pep8'])
133      self.assertEqual(ret, 0)
134      help_message = out.getvalue()
135      self.assertIn('indent_width=4', help_message)
136      self.assertIn('The number of spaces required before a trailing comment.',
137                    help_message)
138
139  def testVersion(self):
140    with captured_output() as (out, _):
141      ret = yapf.main(['-', '--version'])
142      self.assertEqual(ret, 0)
143      version = 'yapf {}\n'.format(yapf.__version__)
144      self.assertEqual(version, out.getvalue())
145